diff --git a/src/Battling/Flow/ChoiceQueue.hpp b/src/Battling/Flow/ChoiceQueue.hpp index 1735eff..5d6975c 100644 --- a/src/Battling/Flow/ChoiceQueue.hpp +++ b/src/Battling/Flow/ChoiceQueue.hpp @@ -7,12 +7,12 @@ namespace CreatureLib::Battling{ class ChoiceQueue { - std::vector _queue; + std::vector _queue; size_t _current = 0; public: bool HasCompletedQueue = false; - explicit ChoiceQueue(std::vector queue) + explicit ChoiceQueue(std::vector queue) :_queue(std::move(queue)){} const BaseTurnChoice* Dequeue(){ @@ -25,7 +25,7 @@ namespace CreatureLib::Battling{ return _current < _queue.size(); } - std::vector& GetInnerQueue(){ + std::vector& GetInnerQueue(){ return _queue; } }; diff --git a/src/Battling/Flow/TurnOrdering.cpp b/src/Battling/Flow/TurnOrdering.cpp index ac0eb0f..75cc559 100644 --- a/src/Battling/Flow/TurnOrdering.cpp +++ b/src/Battling/Flow/TurnOrdering.cpp @@ -1,8 +1,6 @@ #include "TurnOrdering.hpp" #include "../TurnChoices/AttackTurnChoice.hpp" -#include "../Models/Creature.hpp" #include "../Models/Battle.hpp" -#include "../../Core/Exceptions/NotImplementedException.hpp" #include @@ -15,8 +13,8 @@ bool ___ChoiceOrderFunc(const BaseTurnChoice* a, const BaseTurnChoice* b, Core:: if (aKind != bKind) return aKind > bKind; if (aKind == TurnChoiceKind::Attack){ - auto aPriority = static_cast(a)->GetPriority(); - auto bPriority = static_cast(b)->GetPriority(); + auto aPriority = dynamic_cast(a)->GetPriority(); + auto bPriority = dynamic_cast(b)->GetPriority(); if (aPriority != bPriority) return aPriority > bPriority; } @@ -29,7 +27,7 @@ bool ___ChoiceOrderFunc(const BaseTurnChoice* a, const BaseTurnChoice* b, Core:: return randomValue == 0; } -void TurnOrdering::OrderChoices(std::vector &vec, Core::Random& rand) { +void TurnOrdering::OrderChoices(std::vector &vec, Core::Random& rand) { auto comp = [&](const BaseTurnChoice * a,const BaseTurnChoice * b)-> bool { return ___ChoiceOrderFunc(a,b,rand); }; diff --git a/src/Battling/Flow/TurnOrdering.hpp b/src/Battling/Flow/TurnOrdering.hpp index e760f92..b84c452 100644 --- a/src/Battling/Flow/TurnOrdering.hpp +++ b/src/Battling/Flow/TurnOrdering.hpp @@ -8,7 +8,7 @@ namespace CreatureLib::Battling { class TurnOrdering { public: - static void OrderChoices(std::vector& vec, CreatureLib::Core::Random& rand); + static void OrderChoices(std::vector& vec, CreatureLib::Core::Random& rand); }; } diff --git a/src/Battling/Models/Battle.cpp b/src/Battling/Models/Battle.cpp index 338d933..e657045 100644 --- a/src/Battling/Models/Battle.cpp +++ b/src/Battling/Models/Battle.cpp @@ -33,10 +33,10 @@ void Battle::CheckChoicesSetAndRun() { return; } } - auto choices = std::vector(_numberOfSides * _creaturesPerSide); + auto choices = std::vector(_numberOfSides * _creaturesPerSide); auto i = 0; for (auto side: _sides){ - for (const BaseTurnChoice* choice: side->GetChoices()){ + for (BaseTurnChoice* choice: side->GetChoices()){ if (choice->GetKind() == TurnChoiceKind::Attack){ auto attack = dynamic_cast(choice)->GetAttack(); uint8_t uses = 1; @@ -93,6 +93,6 @@ void Battle::FillRecall(uint8_t side, uint8_t, Creature *c) { } } -void Battle::GetActiveScripts(ScriptAggregator &aggr) const { - aggr.Add(&_volatile); +void Battle::GetActiveScripts(std::vector &scripts) { + scripts.emplace_back(&_volatile); } diff --git a/src/Battling/Models/Battle.hpp b/src/Battling/Models/Battle.hpp index cdcef0c..d49d129 100644 --- a/src/Battling/Models/Battle.hpp +++ b/src/Battling/Models/Battle.hpp @@ -42,7 +42,7 @@ namespace CreatureLib::Battling { void FillRecall(uint8_t side, uint8_t, Creature* c); - void GetActiveScripts(ScriptAggregator &aggr) const override; + void GetActiveScripts(std::vector &scripts) override; }; } diff --git a/src/Battling/Models/BattleSide.cpp b/src/Battling/Models/BattleSide.cpp index 6331ca1..10379c7 100644 --- a/src/Battling/Models/BattleSide.cpp +++ b/src/Battling/Models/BattleSide.cpp @@ -16,11 +16,11 @@ void BattleSide::ResetChoices() { } } -const std::vector& BattleSide::GetChoices() const{ +const std::vector& BattleSide::GetChoices() const{ return _choices; } -void BattleSide::SetChoice(const BaseTurnChoice *choice) { +void BattleSide::SetChoice(BaseTurnChoice *choice) { auto find = std::find(_creatures.begin(), _creatures.end(), choice->GetUser()); if (find ==_creatures.end()) throw CreatureException("User not found"); @@ -41,7 +41,7 @@ Creature *BattleSide::GetCreature(uint8_t index) const { return _creatures[index]; } -void BattleSide::GetActiveScripts(ScriptAggregator &aggr) const { - aggr.Add(&_volatile); - _battle->GetActiveScripts(aggr); +void BattleSide::GetActiveScripts(std::vector &scripts) { + scripts.emplace_back(&_volatile); + _battle->GetActiveScripts(scripts); } diff --git a/src/Battling/Models/BattleSide.hpp b/src/Battling/Models/BattleSide.hpp index c4a95bf..1c10d31 100644 --- a/src/Battling/Models/BattleSide.hpp +++ b/src/Battling/Models/BattleSide.hpp @@ -9,7 +9,7 @@ namespace CreatureLib::Battling{ class BattleSide : public ScriptSource{ uint8_t _creaturesPerSide; std::vector _creatures; - std::vector _choices; + std::vector _choices; uint8_t _choicesSet = 0; ScriptSet _volatile; Battle* _battle; @@ -21,9 +21,9 @@ namespace CreatureLib::Battling{ } [[nodiscard]] bool AllChoicesSet() const; - [[nodiscard]] const std::vector& GetChoices() const; + [[nodiscard]] const std::vector& GetChoices() const; - void SetChoice(const BaseTurnChoice* choice); + void SetChoice(BaseTurnChoice* choice); void ResetChoices(); void SetCreature(Creature* creature, uint8_t index); @@ -31,7 +31,7 @@ namespace CreatureLib::Battling{ Creature* GetCreature(uint8_t index) const; bool CreatureOnSide(const Creature* creature) const; - void GetActiveScripts(ScriptAggregator &aggr) const override; + void GetActiveScripts(std::vector &scripts) override; }; } diff --git a/src/Battling/Models/Creature.cpp b/src/Battling/Models/Creature.cpp index a263447..8fa1c93 100644 --- a/src/Battling/Models/Creature.cpp +++ b/src/Battling/Models/Creature.cpp @@ -1,4 +1,5 @@ #include +#include #include "Creature.hpp" #include "../Models/Battle.hpp" @@ -20,9 +21,9 @@ Battling::Creature::Creature(const Library::CreatureSpecies* species, const Libr __Gender(gender), __Coloring(coloring), __HeldItem(heldItem), - _nickname(nickname), + _nickname(std::move(nickname)), _talentIndex(talent), - _attacks(attacks) + _attacks(std::move(attacks)) {} @@ -140,8 +141,8 @@ bool Battling::Creature::HasType(uint8_t type) const { return std::find(t.begin(), t.end(), type) != t.end(); } -void Battling::Creature::GetActiveScripts(Battling::ScriptAggregator &aggr) const { - aggr.Add(_status); - aggr.Add(&_volatile); - _side->GetActiveScripts(aggr); +void Battling::Creature::GetActiveScripts(std::vector &scripts) { + scripts.emplace_back(&_status); + scripts.emplace_back(&_volatile); + _side->GetActiveScripts(scripts); } diff --git a/src/Battling/Models/Creature.hpp b/src/Battling/Models/Creature.hpp index 9b4b18a..b8f7885 100644 --- a/src/Battling/Models/Creature.hpp +++ b/src/Battling/Models/Creature.hpp @@ -18,7 +18,8 @@ namespace CreatureLib::Battling{ class Creature : public ScriptSource{ GetProperty(const Library::CreatureSpecies*, Species); - GetProperty(const Library::SpeciesVariant*, Variant); + GetProperty(const Library::SpeciesVariant*, Variant) + GetProperty(uint8_t, Level); GetProperty(uint32_t, Experience); GetProperty(Core::StatisticSet, StatExperience); @@ -67,7 +68,7 @@ namespace CreatureLib::Battling{ [[nodiscard]] const std::vector& GetTypes() const; [[nodiscard]] bool HasType(uint8_t type) const; - void GetActiveScripts(ScriptAggregator& aggr) const override; + void GetActiveScripts(std::vector &scripts) override; //region Stat APIs @@ -85,6 +86,7 @@ namespace CreatureLib::Battling{ void RecalculateBoostedStats(); void RecalculateFlatStat(Core::Statistic); void RecalculateBoostedStat(Core::Statistic); + //endregion diff --git a/src/Battling/Models/ExecutingAttack.hpp b/src/Battling/Models/ExecutingAttack.hpp index 0f5870d..e61ee09 100644 --- a/src/Battling/Models/ExecutingAttack.hpp +++ b/src/Battling/Models/ExecutingAttack.hpp @@ -89,8 +89,10 @@ namespace CreatureLib::Battling { return _attack; } - void GetActiveScripts(ScriptAggregator &aggr) const override { - aggr.Add(_script); + protected: + void GetActiveScripts(std::vector &scripts) override { + scripts.emplace_back(&_script); + GetUser()->GetActiveScripts(scripts); } }; } diff --git a/src/Battling/ScriptHandling/ScriptAggregator.hpp b/src/Battling/ScriptHandling/ScriptAggregator.hpp index 1d7b09f..0e0654f 100644 --- a/src/Battling/ScriptHandling/ScriptAggregator.hpp +++ b/src/Battling/ScriptHandling/ScriptAggregator.hpp @@ -6,26 +6,23 @@ #include "Script.hpp" #include "ScriptSet.hpp" #include "../../Core/Exceptions/NotReachableException.hpp" +#include "ScriptWrapper.hpp" namespace CreatureLib::Battling{ class ScriptAggregator{ - std::queue _queue; + __gnu_cxx::__normal_iterator> _selfIterator; + __gnu_cxx::__normal_iterator> _selfEnd; bool _isSetSet = false; std::__detail::_Node_const_iterator, false, true> _setIterator; std::__detail::_Node_const_iterator, false, true> _setEnd; public: - ScriptAggregator() = default; - - void Add(Script* script){ - _queue.push(script); - } - - void Add(const ScriptSet* scriptSet){ - _queue.push(scriptSet); - } + ScriptAggregator(std::vector scripts){ + _selfIterator = scripts.begin(); + _selfEnd = scripts.end(); + }; bool HasNext(){ - return !_queue.empty() || _isSetSet; + return _selfIterator != _selfEnd || _isSetSet; } Script* GetNext(){ @@ -42,15 +39,17 @@ namespace CreatureLib::Battling{ } return s; } - if (_queue.empty()) + if (_selfIterator == _selfEnd) return nullptr; - auto next = _queue.front(); - _queue.pop(); - if (next.type() == typeid(Script*)){ - return std::any_cast(next); + auto next = *_selfIterator; + if (!next.IsSet()){ + auto scriptPtr = next.GetScript(); + if (scriptPtr == nullptr) + return GetNext(); + return *scriptPtr; } else{ - auto set = std::any_cast(next); + auto set = next.GetScriptSet(); if (set->Count() == 0) return GetNext(); auto it = set->GetIterator(); diff --git a/src/Battling/ScriptHandling/ScriptMacros.cpp b/src/Battling/ScriptHandling/ScriptMacros.cpp index d4d89f4..ca5b288 100644 --- a/src/Battling/ScriptHandling/ScriptMacros.cpp +++ b/src/Battling/ScriptHandling/ScriptMacros.cpp @@ -1,7 +1,6 @@ #define HOOK(hookName, source, ... ) \ { \ -auto aggregator = CreatureLib::Battling::ScriptAggregator(); \ -source -> GetActiveScripts(aggregator); \ +auto aggregator = source -> GetScriptIterator(); \ while (aggregator.HasNext()){ \ auto next = aggregator.GetNext(); \ if (next == nullptr) continue; \ diff --git a/src/Battling/ScriptHandling/ScriptSource.hpp b/src/Battling/ScriptHandling/ScriptSource.hpp index 9a8d3de..0e964a9 100644 --- a/src/Battling/ScriptHandling/ScriptSource.hpp +++ b/src/Battling/ScriptHandling/ScriptSource.hpp @@ -7,8 +7,18 @@ namespace CreatureLib::Battling{ class ScriptSource { + bool _areScriptsInitialized = false; + std::vector _scripts; + protected: + virtual void GetActiveScripts(std::vector& scripts) = 0; public: - virtual void GetActiveScripts(ScriptAggregator& aggr) const = 0; + ScriptAggregator GetScriptIterator(){ + if (!_areScriptsInitialized){ + GetActiveScripts(_scripts); + _areScriptsInitialized = true; + } + return ScriptAggregator(_scripts); + } }; } diff --git a/src/Battling/ScriptHandling/ScriptWrapper.cpp b/src/Battling/ScriptHandling/ScriptWrapper.cpp new file mode 100644 index 0000000..aaef513 --- /dev/null +++ b/src/Battling/ScriptHandling/ScriptWrapper.cpp @@ -0,0 +1,3 @@ + + +#include "ScriptWrapper.hpp" diff --git a/src/Battling/ScriptHandling/ScriptWrapper.hpp b/src/Battling/ScriptHandling/ScriptWrapper.hpp new file mode 100644 index 0000000..412211a --- /dev/null +++ b/src/Battling/ScriptHandling/ScriptWrapper.hpp @@ -0,0 +1,33 @@ + + +#ifndef CREATURELIB_SCRIPTWRAPPER_HPP +#define CREATURELIB_SCRIPTWRAPPER_HPP + +#include +#include "Script.hpp" +#include "ScriptSet.hpp" + +namespace CreatureLib::Battling{ + class ScriptWrapper { + std::variant _value; + bool _isSet; + public: + ScriptWrapper(Script** s) : _value(s), _isSet(false){} + ScriptWrapper(ScriptSet* s) : _value(s), _isSet(true){} + + bool IsSet() const{ + return _isSet; + } + + Script** GetScript() const{ + return std::get(_value); + } + + ScriptSet* GetScriptSet() const{ + return std::get(_value); + } + }; +} + + +#endif //CREATURELIB_SCRIPTWRAPPER_HPP diff --git a/src/Battling/TurnChoices/AttackTurnChoice.hpp b/src/Battling/TurnChoices/AttackTurnChoice.hpp index 3c1fe8b..b5dacfa 100644 --- a/src/Battling/TurnChoices/AttackTurnChoice.hpp +++ b/src/Battling/TurnChoices/AttackTurnChoice.hpp @@ -31,10 +31,12 @@ namespace CreatureLib::Battling{ return _target; } - void GetActiveScripts(ScriptAggregator &aggr) const override { - aggr.Add(_attackScript); - GetUser()->GetActiveScripts(aggr); + protected: + void GetActiveScripts(std::vector &scripts) override { + scripts.emplace_back(&_attackScript); + GetUser()->GetActiveScripts(scripts); } + }; } diff --git a/src/Battling/TurnChoices/BaseTurnChoice.hpp b/src/Battling/TurnChoices/BaseTurnChoice.hpp index bdd0db9..5058b84 100644 --- a/src/Battling/TurnChoices/BaseTurnChoice.hpp +++ b/src/Battling/TurnChoices/BaseTurnChoice.hpp @@ -17,10 +17,6 @@ namespace CreatureLib::Battling{ [[nodiscard]] inline Creature* GetUser() const{ return _user; } - - void GetActiveScripts(ScriptAggregator &aggr) const override { - - } }; } diff --git a/src/Battling/TurnChoices/PassTurnChoice.hpp b/src/Battling/TurnChoices/PassTurnChoice.hpp index 60b3118..2342334 100644 --- a/src/Battling/TurnChoices/PassTurnChoice.hpp +++ b/src/Battling/TurnChoices/PassTurnChoice.hpp @@ -12,8 +12,9 @@ namespace CreatureLib::Battling { return TurnChoiceKind ::Pass; } - void GetActiveScripts(ScriptAggregator &aggr) const override { - GetUser()->GetActiveScripts(aggr); + protected: + void GetActiveScripts(std::vector &scripts) override { + GetUser()->GetActiveScripts(scripts); } }; } diff --git a/tests/BattleTests/TurnOrderTests.cpp b/tests/BattleTests/TurnOrderTests.cpp index d888084..0f3f7f2 100644 --- a/tests/BattleTests/TurnOrderTests.cpp +++ b/tests/BattleTests/TurnOrderTests.cpp @@ -11,12 +11,12 @@ using namespace CreatureLib::Battling; TEST_CASE( "Turn ordering: Attack before pass", "[Battling]" ) { auto choice1 = new PassTurnChoice(nullptr); auto choice2 = new AttackTurnChoice(nullptr, nullptr, Target(0,0)); - auto vec = std::vector{choice1, choice2}; + auto vec = std::vector{choice1, choice2}; auto rand = Core::Random(); TurnOrdering::OrderChoices(vec,rand); CHECK(vec[0] == choice2); CHECK(vec[1] == choice1); - vec = std::vector{choice2, choice1}; + vec = std::vector{choice2, choice1}; TurnOrdering::OrderChoices(vec,rand); CHECK(vec[0] == choice2); CHECK(vec[1] == choice1); @@ -31,12 +31,12 @@ TEST_CASE( "Turn ordering: High priority goes before no priority", "[Battling]" auto a2 = new LearnedAttack(l->GetAttack("highPriority"), AttackLearnMethod::Unknown); auto choice1 = new AttackTurnChoice(nullptr, a1, Target(0,0)); auto choice2 = new AttackTurnChoice(nullptr, a2, Target(0,0)); - auto vec = std::vector{choice1, choice2}; + auto vec = std::vector{choice1, choice2}; auto rand = Core::Random(); TurnOrdering::OrderChoices(vec,rand); CHECK(vec[0] == choice2); CHECK(vec[1] == choice1); - vec = std::vector{choice2, choice1}; + vec = std::vector{choice2, choice1}; TurnOrdering::OrderChoices(vec,rand); CHECK(vec[0] == choice2); CHECK(vec[1] == choice1); @@ -53,12 +53,12 @@ TEST_CASE( "Turn ordering: Higher priority goes before high priority", "[Battlin auto a2 = new LearnedAttack(l->GetAttack("higherPriority"), AttackLearnMethod::Unknown); auto choice1 = new AttackTurnChoice(nullptr, a1, Target(0,0)); auto choice2 = new AttackTurnChoice(nullptr, a2, Target(0,0)); - auto vec = std::vector{choice1, choice2}; + auto vec = std::vector{choice1, choice2}; auto rand = Core::Random(); TurnOrdering::OrderChoices(vec,rand); CHECK(vec[0] == choice2); CHECK(vec[1] == choice1); - vec = std::vector{choice2, choice1}; + vec = std::vector{choice2, choice1}; TurnOrdering::OrderChoices(vec,rand); CHECK(vec[0] == choice2); CHECK(vec[1] == choice1); @@ -75,12 +75,12 @@ TEST_CASE( "Turn ordering: High priority goes before low priority", "[Battling]" auto a2 = new LearnedAttack(l->GetAttack("higherPriority"), AttackLearnMethod::Unknown); auto choice1 = new AttackTurnChoice(nullptr, a1, Target(0,0)); auto choice2 = new AttackTurnChoice(nullptr, a2, Target(0,0)); - auto vec = std::vector{choice1, choice2}; + auto vec = std::vector{choice1, choice2}; auto rand = Core::Random(); TurnOrdering::OrderChoices(vec,rand); CHECK(vec[0] == choice2); CHECK(vec[1] == choice1); - vec = std::vector{choice2, choice1}; + vec = std::vector{choice2, choice1}; TurnOrdering::OrderChoices(vec,rand); CHECK(vec[0] == choice2); CHECK(vec[1] == choice1); @@ -97,12 +97,12 @@ TEST_CASE( "Turn ordering: No priority goes before low priority", "[Battling]" ) auto a2 = new LearnedAttack(l->GetAttack("standard"), AttackLearnMethod::Unknown); auto choice1 = new AttackTurnChoice(nullptr, a1, Target(0,0)); auto choice2 = new AttackTurnChoice(nullptr, a2, Target(0,0)); - auto vec = std::vector{choice1, choice2}; + auto vec = std::vector{choice1, choice2}; auto rand = Core::Random(); TurnOrdering::OrderChoices(vec,rand); CHECK(vec[0] == choice2); CHECK(vec[1] == choice1); - vec = std::vector{choice2, choice1}; + vec = std::vector{choice2, choice1}; TurnOrdering::OrderChoices(vec,rand); CHECK(vec[0] == choice2); CHECK(vec[1] == choice1);