#ifndef CREATURELIB_BATTLE_HPP #define CREATURELIB_BATTLE_HPP #include "../EventHooks/EventHook.hpp" #include "../Flow/ChoiceQueue.hpp" #include "../History/HistoryHolder.hpp" #include "../Library/BattleLibrary.hpp" #include "../TurnChoices/BaseTurnChoice.hpp" #include "BattleParty.hpp" #include "BattleRandom.hpp" #include "BattleResult.hpp" #include "BattleSide.hpp" #include "CreatureIndex.hpp" namespace CreatureLib::Battling { class Battle : public ScriptSource { protected: ArbUt::BorrowedPtr _library; ArbUt::UniquePtrList _parties; bool _canFlee; uint8_t _numberOfSides; uint8_t _creaturesPerSide; ArbUt::UniquePtrList _sides; BattleRandom _random; std::unique_ptr _currentTurnQueue = nullptr; bool _hasEnded = false; BattleResult _battleResult = BattleResult::Empty(); EventHook _eventHook; HistoryHolder _historyHolder; uint32_t _currentTurn = 0; ScriptSet _volatile; long _lastTurnTime; public: Battle(const BattleLibrary* library, ArbUt::List parties, bool canFlee = true, uint8_t numberOfSides = 2, uint8_t creaturesPerSide = 1, uint_fast32_t randomSeed = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) .count()) : _library(library), _parties(parties.GetStdList()), _canFlee(canFlee), _numberOfSides(numberOfSides), _creaturesPerSide(creaturesPerSide), _sides(numberOfSides), _random(randomSeed) { EnsureAllNotNull(parties); for (size_t i = 0; i < numberOfSides; i++) { _sides.Append(new BattleSide(i, this, creaturesPerSide)); } } virtual ~Battle() = default; [[nodiscard]] const ArbUt::BorrowedPtr& GetLibrary() const noexcept; [[nodiscard]] uint32_t GetCurrentTurn() const noexcept { return _currentTurn; } inline uint8_t GetCreaturesPerSide() const noexcept { return _creaturesPerSide; } virtual bool CanUse(const ArbUt::BorrowedPtr& choice); virtual bool TrySetChoice(BaseTurnChoice* choice); bool CanFlee() const noexcept { return _canFlee; } void CheckChoicesSetAndRun(); [[nodiscard]] ArbUt::BorrowedPtr GetCurrentTurnQueue() const noexcept; BattleRandom* GetRandom() noexcept; bool CreatureInField(ArbUt::BorrowedPtr creature) const; const ArbUt::OptionalBorrowedPtr& GetCreature(const CreatureIndex& target) const { return _sides[target.GetSideIndex()]->GetCreature(target.GetCreatureIndex()); } const ArbUt::OptionalBorrowedPtr& 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; size_t ScriptCount() const override; void GetActiveScripts(ArbUt::List& scripts) override; void ValidateBattleState(); inline bool HasEnded() const noexcept { return _hasEnded; } inline const BattleResult& GetResult() const noexcept { return _battleResult; } const ArbUt::UniquePtrList& GetParties() const noexcept { return _parties; } const ArbUt::UniquePtrList& GetSides() const noexcept { return _sides; } std::optional> GetVolatileScript(const ArbUt::StringView& key) const { return _volatile.Get(key); } std::optional> GetVolatileScript(uint32_t keyHash) const noexcept { return _volatile.Get(keyHash); } void AddVolatileScript(const ArbUt::StringView& key); void AddVolatileScript(Script* script); void RemoveVolatileScript(const ArbUt::BasicStringView& name) { _volatile.Remove(name); } void RemoveVolatileScript(uint32_t keyHash) { _volatile.Remove(keyHash); } void RemoveVolatileScript(Script* script); bool HasVolatileScript(const ArbUt::BasicStringView& name) const { return _volatile.Has(name); } bool HasVolatileScript(uint32_t keyHash) const { return _volatile.Has(keyHash); } void DisplayText(const ArbUt::StringView& text); void RegisterEventListener(EventHook::EventHookFunc listener) { this->_eventHook.RegisterListener(listener); } template void TriggerEventListener(parameters... args) { try_creature(this->_eventHook.Trigger(args...);, "Exception occurred during event trigger."); } EventHook& GetEventHook() noexcept { return _eventHook; } const EventHook& GetEventHook() const noexcept { return _eventHook; } template void RegisterHistoryElement(parameters... args) { try_creature(this->_historyHolder.Register(args...); , "Exception occurred during history element registration."); } const HistoryHolder& GetHistory() const noexcept { return _historyHolder; } long GetLastTurnTimeMicroseconds() const noexcept { return _lastTurnTime; } }; } #endif // CREATURELIB_BATTLE_HPP