#ifndef CREATURELIB_BATTLE_HPP #define CREATURELIB_BATTLE_HPP #include #include #include "../EventHooks/EventHook.hpp" #include "../Flow/ChoiceQueue.hpp" #include "../Library/BattleLibrary.hpp" #include "../TurnChoices/BaseTurnChoice.hpp" #include "BattleParty.hpp" #include "BattleRandom.hpp" #include "BattleResult.hpp" #include "BattleSide.hpp" #include "CreatureIndex.hpp" using namespace Arbutils::Collections; namespace CreatureLib::Battling { class Battle : public ScriptSource { const BattleLibrary* _library; List _parties; bool _canFlee; uint8_t _numberOfSides; uint8_t _creaturesPerSide; List _sides; BattleRandom _random; ChoiceQueue* _currentTurnQueue = nullptr; bool _hasEnded = false; BattleResult _battleResult = BattleResult::Empty(); EventHook _eventHook = EventHook(); uint32_t _currentTurn = 0; ScriptSet _volatile; public: Battle(const BattleLibrary* library, List parties, bool canFlee = true, uint8_t numberOfSides = 2, uint8_t creaturesPerSide = 1) : _library(library), _parties(std::move(parties)), _canFlee(canFlee), _numberOfSides(numberOfSides), _creaturesPerSide(creaturesPerSide) { AssertNotNull(_library) for (auto p : parties) AssertNotNull(p) _sides = List(numberOfSides); for (size_t i = 0; i < numberOfSides; i++) { _sides[i] = new BattleSide(i, this, creaturesPerSide); } } virtual ~Battle() { for (auto s : _sides) { delete s; } for (auto party : _parties) { delete party; } delete _currentTurnQueue; } [[nodiscard]] const BattleLibrary* GetLibrary() const noexcept; [[nodiscard]] uint32_t GetCurrentTurn() const noexcept { return _currentTurn; } virtual bool CanUse(const BaseTurnChoice* choice); virtual bool TrySetChoice(BaseTurnChoice* choice); bool CanFlee() const noexcept { return _canFlee; } void CheckChoicesSetAndRun(); [[nodiscard]] ChoiceQueue* GetCurrentTurnQueue() const noexcept; BattleRandom* GetRandom() noexcept; bool CreatureInField(const Creature* creature) const; Creature* GetCreature(const CreatureIndex& target) const { return _sides[target.GetSideIndex()]->GetCreature(target.GetCreatureIndex()); } Creature* GetCreature(uint8_t side, uint8_t target) const { return _sides[side]->GetCreature(target); } void ForceRecall(uint8_t side, uint8_t index); void SwitchCreature(uint8_t side, uint8_t index, Creature* c); bool CanSlotBeFilled(uint8_t side, uint8_t index) const; void GetActiveScripts(Arbutils::Collections::List& scripts) override; void ValidateBattleState(); inline bool HasEnded() const noexcept { return _hasEnded; } inline const BattleResult& GetResult() const noexcept { return _battleResult; } const List& GetSides() const noexcept { return _sides; } Script* GetVolatileScript(const ConstString& key) const { return _volatile.Get(key); } Script* GetVolatileScript(uint32_t keyHash) const noexcept { return _volatile.Get(keyHash); } void AddVolatileScript(const ConstString& key); void AddVolatileScript(Script* script); void RemoveVolatileScript(const ConstString& name) { _volatile.Remove(name); } void RemoveVolatileScript(uint32_t keyHash) { _volatile.Remove(keyHash); } void RemoveVolatileScript(Script* script); bool HasVolatileScript(const ConstString& name) const { return _volatile.Has(name); } bool HasVolatileScript(uint32_t keyHash) const { return _volatile.Has(keyHash); } void DisplayText(const std::string& text) const; void RegisterEventListener(EVENT_HOOK_FUNC(listener)) { this->_eventHook.RegisterListener(listener); } void TriggerEventListener(EventData* data) const { this->_eventHook.TriggerEvent(data); } }; } #endif // CREATURELIB_BATTLE_HPP