#ifndef CREATURELIB_BATTLESIDE_HPP #define CREATURELIB_BATTLESIDE_HPP #include "../TurnChoices/BaseTurnChoice.hpp" #include "Creature.hpp" namespace CreatureLib::Battling { class BattleSide : public ScriptSource { u8 _index; u8 _creaturesPerSide; ArbUt::List> _creatures; ArbUt::List> _choices; ArbUt::List _fillableSlots; u8 _choicesSet = 0; ScriptSet _volatile; ArbUt::BorrowedPtr _battle; bool _hasFled = false; public: BattleSide(u8 index, ArbUt::BorrowedPtr battle, u8 creaturesPerSide) noexcept : _index(index), _creaturesPerSide(creaturesPerSide), _creatures(creaturesPerSide), _choices(creaturesPerSide), _fillableSlots(creaturesPerSide), _battle(battle) { for (size_t i = 0; i < creaturesPerSide; i++) { _creatures.Append(nullptr); _choices.Append(nullptr); _fillableSlots.Append(true); } ResetChoices(); } virtual ~BattleSide() = default; [[nodiscard]] inline ArbUt::BorrowedPtr GetBattle() const noexcept { return _battle; } [[nodiscard]] bool AllChoicesSet() const noexcept; [[nodiscard]] const ArbUt::List>& GetChoices() const noexcept { return _choices; } [[nodiscard]] bool AllPossibleSlotsFilled() const; void SetChoice(BaseTurnChoice* non_null choice); void ResetChoices() noexcept; void ForceClearCreature(u8 index) { _creatures[index] = {}; } void SetCreature(ArbUt::OptionalBorrowedPtr creature, u8 index); const ArbUt::OptionalBorrowedPtr& GetCreature(u8 index) const; bool CreatureOnSide(const ArbUt::BorrowedPtr& creature) const; size_t ScriptCount() const override; void GetActiveScripts(ArbUt::List& scripts) override; void GetOwnScripts(ArbUt::List& scripts) override; const ArbUt::List>& GetCreatures() { return _creatures; } const ArbUt::OptionalBorrowedPtr& GetCreature(u8 index) { return _creatures[index]; } u8 GetSideIndex() noexcept { return _index; } u8 GetCreatureIndex(const ArbUt::BorrowedPtr& c) { for (size_t i = 0; i < _creatures.Count(); i++) { if (!_creatures[i].HasValue()) continue; if (_creatures[i].GetValue() == c.GetRaw()) return i; } THROW("Unable to find creature on field."); } void MarkSlotAsUnfillable(const ArbUt::BorrowedPtr& creature) noexcept { for (u8 i = 0; i < _creaturesPerSide; i++) { if (!_creatures[i].HasValue()) continue; if (_creatures[i].GetValue() == creature) { _fillableSlots.At(i) = false; return; } } } inline bool IsSlotUnfillabe(const ArbUt::BorrowedPtr& creature) const noexcept { for (u8 i = 0; i < _creaturesPerSide; i++) { if (!_creatures[i].HasValue()) continue; if (_creatures[i].GetValue() == creature) { return _fillableSlots.At(i); } } } bool IsDefeated() noexcept { for (auto b : _fillableSlots) { if (b) return false; } return true; } bool HasFled() noexcept { return _hasFled; } void MarkAsFled() noexcept { _hasFled = true; } u8 GetRandomCreatureIndex(); bool SwapPositions(u8 a, u8 b); BattleSide* non_null CloneWithoutCreatures(ArbUt::BorrowedPtr battle) const; ArbUt::OptionalBorrowedPtr GetVolatileScript(const ArbUt::StringView& key) const { return _volatile.Get(key); } ArbUt::OptionalBorrowedPtr GetVolatileScript(u32 keyHash) const noexcept { return _volatile.Get(keyHash); } BattleScript* non_null AddVolatileScript(const ArbUt::StringView& key); BattleScript* non_null AddVolatileScript(BattleScript* non_null script); void RemoveVolatileScript(const ArbUt::BasicStringView& name) { _volatile.Remove(name); } void RemoveVolatileScript(u32 keyHash) { _volatile.Remove(keyHash); } void RemoveVolatileScript(BattleScript* non_null script); bool HasVolatileScript(const ArbUt::BasicStringView& name) const { return _volatile.Has(name); } bool HasVolatileScript(u32 keyHash) const { return _volatile.Has(keyHash); } }; } #endif // CREATURELIB_BATTLESIDE_HPP