From 348878440935b4c717d72f740f982dfcde0a4400 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sun, 10 Nov 2019 14:32:05 +0100 Subject: [PATCH] Furter rework on script hooks, simplifying required logic. --- src/Battling/Flow/ChoiceQueue.hpp | 4 ++++ src/Battling/Flow/TurnHandler.cpp | 24 ++++++++++--------- src/Battling/Models/Battle.cpp | 8 +++++-- src/Battling/Models/Battle.hpp | 5 +++- src/Battling/Models/BattleSide.cpp | 6 +++++ src/Battling/Models/BattleSide.hpp | 10 +++++--- src/Battling/Models/Creature.cpp | 6 +++++ src/Battling/Models/Creature.hpp | 5 +--- src/Battling/Models/ExecutingAttack.hpp | 2 +- src/Battling/ScriptHandling/Script.hpp | 2 ++ .../ScriptHandling/ScriptAggregator.hpp | 9 +++---- src/Battling/ScriptHandling/ScriptMacros.cpp | 6 ++--- src/Battling/ScriptHandling/ScriptSet.hpp | 2 +- src/Battling/ScriptHandling/ScriptSource.hpp | 2 +- src/Battling/TurnChoices/AttackTurnChoice.hpp | 6 +++++ src/Battling/TurnChoices/BaseTurnChoice.hpp | 7 +++++- src/Battling/TurnChoices/PassTurnChoice.hpp | 4 ++++ tests/BattleTests/ChoiceSetTests.cpp | 8 +++---- 18 files changed, 79 insertions(+), 37 deletions(-) diff --git a/src/Battling/Flow/ChoiceQueue.hpp b/src/Battling/Flow/ChoiceQueue.hpp index e55a848..1735eff 100644 --- a/src/Battling/Flow/ChoiceQueue.hpp +++ b/src/Battling/Flow/ChoiceQueue.hpp @@ -24,6 +24,10 @@ namespace CreatureLib::Battling{ [[nodiscard]] bool HasNext() const{ return _current < _queue.size(); } + + std::vector& GetInnerQueue(){ + return _queue; + } }; } diff --git a/src/Battling/Flow/TurnHandler.cpp b/src/Battling/Flow/TurnHandler.cpp index 84f73d0..8c9bf61 100644 --- a/src/Battling/Flow/TurnHandler.cpp +++ b/src/Battling/Flow/TurnHandler.cpp @@ -7,6 +7,9 @@ using namespace CreatureLib::Battling; void TurnHandler::RunTurn(Battle* battle, ChoiceQueue* queue) { //HOOK: On Before Turn hook for all choices + for (auto choice: queue->GetInnerQueue()){ + HOOK(OnBeforeTurn, choice, choice); + } while (queue->HasNext()){ if (!battle->HasRecalledSlots()){ return; @@ -83,25 +86,25 @@ void TurnHandler::ExecuteAttackChoice(const AttackTurnChoice *choice) { void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, Creature *target, const ExecutingAttack::TargetData &targetData) { auto user = attack->GetUser(); - std::array targetSources = {target}; - std::array userSources = {user}; + ScriptSource* targetSource = target; + ScriptSource* userSource = attack; bool fail = false; - HOOK(FailIncomingAttack, targetSources, attack, target, fail); + HOOK(FailIncomingAttack, targetSource, attack, target, fail); if (fail){ //TODO: Fail handling. return; } bool invulnerable = fail; - HOOK(IsInvulnerable, targetSources, attack, target, invulnerable); + HOOK(IsInvulnerable, targetSource, attack, target, invulnerable); if (invulnerable){ //TODO: We should probably do something when a target is invulnerable. return; } if (!targetData.IsHit()){ - HOOK(OnAttackMiss, targetSources, attack, target); + HOOK(OnAttackMiss, targetSource, attack, target); return; } @@ -122,15 +125,14 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, Creature *targe auto hit = targetData.GetHit(hitIndex); auto hitType = hit.GetType(); - HOOK(ChangeAttackType, targetSources, attack, target, hitIndex, hitType); + HOOK(ChangeAttackType, targetSource, attack, target, hitIndex, hitType); hit.SetEffectiveness(library->GetTypeLibrary()->GetEffectiveness(hitType, target->GetTypes())); hit.SetCritical(library->GetCriticalLibrary()->IsCritical(attack, target, hitIndex)); hit.SetBasePower(dmgLibrary->GetBasePower(attack, target, hitIndex)); hit.SetDamage(dmgLibrary->GetDamage(attack, target, hitIndex)); - std::array attackSource = {attack}; if (attackData->GetCategory() == Library::AttackCategory::Status){ - HOOK(OnStatusMove, attackSource, attack, target, hitIndex); + HOOK(OnStatusMove, userSource, attack, target, hitIndex); } else{ auto damage = hit.GetDamage(); @@ -142,15 +144,15 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, Creature *targe target->Damage(damage, DamageSource::AttackDamage); bool preventSecondary = false; - HOOK(PreventSecondaryEffects, targetSources, attack, target, hitIndex, preventSecondary); + HOOK(PreventSecondaryEffects, targetSource, attack, target, hitIndex, preventSecondary); if (!preventSecondary){ - HOOK(OnSecondaryEffect, attackSource, attack, target, hitIndex); + HOOK(OnSecondaryEffect, userSource, attack, target, hitIndex); } } } } if (!user->IsFainted()){ - HOOK(OnAfterHits, userSources, attack, target); + HOOK(OnAfterHits, userSource, attack, target); } } diff --git a/src/Battling/Models/Battle.cpp b/src/Battling/Models/Battle.cpp index c259f92..338d933 100644 --- a/src/Battling/Models/Battle.cpp +++ b/src/Battling/Models/Battle.cpp @@ -14,7 +14,7 @@ const BattleLibrary *Battle::GetLibrary() const { bool Battle::CanUse(const BaseTurnChoice *choice) { if (choice->GetKind() == TurnChoiceKind::Attack){ //HOOK: change number of uses needed. - return static_cast(choice)->GetAttack()->GetRemainingUses() > 1; + return dynamic_cast(choice)->GetAttack()->GetRemainingUses() > 1; } return true; } @@ -36,7 +36,7 @@ void Battle::CheckChoicesSetAndRun() { auto choices = std::vector(_numberOfSides * _creaturesPerSide); auto i = 0; for (auto side: _sides){ - for (auto choice: side->GetChoices()){ + for (const BaseTurnChoice* choice: side->GetChoices()){ if (choice->GetKind() == TurnChoiceKind::Attack){ auto attack = dynamic_cast(choice)->GetAttack(); uint8_t uses = 1; @@ -92,3 +92,7 @@ void Battle::FillRecall(uint8_t side, uint8_t, Creature *c) { TurnHandler::RunTurn(this, _currentTurnQueue); } } + +void Battle::GetActiveScripts(ScriptAggregator &aggr) const { + aggr.Add(&_volatile); +} diff --git a/src/Battling/Models/Battle.hpp b/src/Battling/Models/Battle.hpp index 288ee41..cdcef0c 100644 --- a/src/Battling/Models/Battle.hpp +++ b/src/Battling/Models/Battle.hpp @@ -9,7 +9,7 @@ #include "Target.hpp" namespace CreatureLib::Battling { - class Battle { + class Battle : public ScriptSource{ const BattleLibrary* _library; uint8_t _numberOfSides; uint8_t _creaturesPerSide; @@ -18,6 +18,7 @@ namespace CreatureLib::Battling { ChoiceQueue* _currentTurnQueue = nullptr; uint8_t _numberOfRecalledSlots = 0; + ScriptSet _volatile; public: [[nodiscard]] const BattleLibrary* GetLibrary() const; @@ -40,6 +41,8 @@ namespace CreatureLib::Battling { void ForceRecall(uint8_t side, uint8_t index); void FillRecall(uint8_t side, uint8_t, Creature* c); + + void GetActiveScripts(ScriptAggregator &aggr) const override; }; } diff --git a/src/Battling/Models/BattleSide.cpp b/src/Battling/Models/BattleSide.cpp index a3da100..6331ca1 100644 --- a/src/Battling/Models/BattleSide.cpp +++ b/src/Battling/Models/BattleSide.cpp @@ -1,6 +1,7 @@ #include "BattleSide.hpp" #include "../../Core/Exceptions/CreatureException.hpp" #include +#include "Battle.hpp" using namespace CreatureLib::Battling; @@ -39,3 +40,8 @@ bool BattleSide::CreatureOnSide(const Creature *creature) const { Creature *BattleSide::GetCreature(uint8_t index) const { return _creatures[index]; } + +void BattleSide::GetActiveScripts(ScriptAggregator &aggr) const { + aggr.Add(&_volatile); + _battle->GetActiveScripts(aggr); +} diff --git a/src/Battling/Models/BattleSide.hpp b/src/Battling/Models/BattleSide.hpp index d2be26a..c4a95bf 100644 --- a/src/Battling/Models/BattleSide.hpp +++ b/src/Battling/Models/BattleSide.hpp @@ -6,14 +6,16 @@ #include "../TurnChoices/BaseTurnChoice.hpp" namespace CreatureLib::Battling{ - class BattleSide { + class BattleSide : public ScriptSource{ uint8_t _creaturesPerSide; std::vector _creatures; std::vector _choices; uint8_t _choicesSet = 0; + ScriptSet _volatile; + Battle* _battle; public: - BattleSide(uint8_t creaturesPerSide) - : _creaturesPerSide(creaturesPerSide), _creatures(creaturesPerSide), _choices(creaturesPerSide) + explicit BattleSide(Battle* battle, uint8_t creaturesPerSide) + : _creaturesPerSide(creaturesPerSide), _creatures(creaturesPerSide), _choices(creaturesPerSide), _battle(battle) { ResetChoices(); } @@ -29,6 +31,8 @@ namespace CreatureLib::Battling{ Creature* GetCreature(uint8_t index) const; bool CreatureOnSide(const Creature* creature) const; + void GetActiveScripts(ScriptAggregator &aggr) const override; + }; } diff --git a/src/Battling/Models/Creature.cpp b/src/Battling/Models/Creature.cpp index 861415f..a263447 100644 --- a/src/Battling/Models/Creature.cpp +++ b/src/Battling/Models/Creature.cpp @@ -139,3 +139,9 @@ bool Battling::Creature::HasType(uint8_t type) const { auto t = GetTypes(); 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); +} diff --git a/src/Battling/Models/Creature.hpp b/src/Battling/Models/Creature.hpp index 2e4238d..3538859 100644 --- a/src/Battling/Models/Creature.hpp +++ b/src/Battling/Models/Creature.hpp @@ -65,10 +65,7 @@ namespace CreatureLib::Battling{ [[nodiscard]] const std::vector& GetTypes() const; [[nodiscard]] bool HasType(uint8_t type) const; - void GetActiveScripts(ScriptAggregator& aggr) override{ - aggr.Add(_status); - aggr.Add(&_volatile); - } + void GetActiveScripts(ScriptAggregator& aggr) const override; //region Stat APIs diff --git a/src/Battling/Models/ExecutingAttack.hpp b/src/Battling/Models/ExecutingAttack.hpp index 279a367..a7f8bd8 100644 --- a/src/Battling/Models/ExecutingAttack.hpp +++ b/src/Battling/Models/ExecutingAttack.hpp @@ -88,7 +88,7 @@ namespace CreatureLib::Battling { return _attack; } - void GetActiveScripts(ScriptAggregator &aggr) override { + void GetActiveScripts(ScriptAggregator &aggr) const override { aggr.Add(_script); } }; diff --git a/src/Battling/ScriptHandling/Script.hpp b/src/Battling/ScriptHandling/Script.hpp index d1ee56a..c39a496 100644 --- a/src/Battling/ScriptHandling/Script.hpp +++ b/src/Battling/ScriptHandling/Script.hpp @@ -7,6 +7,7 @@ #include namespace CreatureLib::Battling{ + class BaseTurnChoice; class ExecutingAttack; class Creature; @@ -23,6 +24,7 @@ namespace CreatureLib::Battling{ return _name; } + virtual void OnBeforeTurn(const BaseTurnChoice* choice); virtual void FailIncomingAttack(ExecutingAttack* attack, Creature* target, bool& result){}; virtual void IsInvulnerable(ExecutingAttack* attack, Creature* target , bool& result){}; virtual void OnAttackMiss(ExecutingAttack* attack, Creature* target){}; diff --git a/src/Battling/ScriptHandling/ScriptAggregator.hpp b/src/Battling/ScriptHandling/ScriptAggregator.hpp index 48036f6..1d7b09f 100644 --- a/src/Battling/ScriptHandling/ScriptAggregator.hpp +++ b/src/Battling/ScriptHandling/ScriptAggregator.hpp @@ -5,13 +5,14 @@ #include #include "Script.hpp" #include "ScriptSet.hpp" +#include "../../Core/Exceptions/NotReachableException.hpp" namespace CreatureLib::Battling{ class ScriptAggregator{ std::queue _queue; bool _isSetSet = false; - std::__detail::_Node_iterator, false, true> _setIterator; - std::__detail::_Node_iterator, false, true> _setEnd; + std::__detail::_Node_const_iterator, false, true> _setIterator; + std::__detail::_Node_const_iterator, false, true> _setEnd; public: ScriptAggregator() = default; @@ -19,7 +20,7 @@ namespace CreatureLib::Battling{ _queue.push(script); } - void Add(ScriptSet* scriptSet){ + void Add(const ScriptSet* scriptSet){ _queue.push(scriptSet); } @@ -49,7 +50,7 @@ namespace CreatureLib::Battling{ return std::any_cast(next); } else{ - auto set = std::any_cast(next); + auto set = std::any_cast(next); 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 784f06d..d4d89f4 100644 --- a/src/Battling/ScriptHandling/ScriptMacros.cpp +++ b/src/Battling/ScriptHandling/ScriptMacros.cpp @@ -1,9 +1,7 @@ -#define HOOK(hookName, sources, ... ) \ +#define HOOK(hookName, source, ... ) \ { \ auto aggregator = CreatureLib::Battling::ScriptAggregator(); \ -for (auto& source: sources){ \ - source -> GetActiveScripts(aggregator); \ -} \ +source -> GetActiveScripts(aggregator); \ while (aggregator.HasNext()){ \ auto next = aggregator.GetNext(); \ if (next == nullptr) continue; \ diff --git a/src/Battling/ScriptHandling/ScriptSet.hpp b/src/Battling/ScriptHandling/ScriptSet.hpp index 7d900aa..ea39e43 100644 --- a/src/Battling/ScriptHandling/ScriptSet.hpp +++ b/src/Battling/ScriptHandling/ScriptSet.hpp @@ -27,7 +27,7 @@ namespace CreatureLib::Battling{ return _scripts.size(); } - std::unordered_map * GetIterator(){ + const std::unordered_map * GetIterator() const{ return &_scripts; } }; diff --git a/src/Battling/ScriptHandling/ScriptSource.hpp b/src/Battling/ScriptHandling/ScriptSource.hpp index ccc52dd..9a8d3de 100644 --- a/src/Battling/ScriptHandling/ScriptSource.hpp +++ b/src/Battling/ScriptHandling/ScriptSource.hpp @@ -8,7 +8,7 @@ namespace CreatureLib::Battling{ class ScriptSource { public: - virtual void GetActiveScripts(ScriptAggregator& aggr) = 0; + virtual void GetActiveScripts(ScriptAggregator& aggr) const = 0; }; } diff --git a/src/Battling/TurnChoices/AttackTurnChoice.hpp b/src/Battling/TurnChoices/AttackTurnChoice.hpp index 7ffc48a..3c1fe8b 100644 --- a/src/Battling/TurnChoices/AttackTurnChoice.hpp +++ b/src/Battling/TurnChoices/AttackTurnChoice.hpp @@ -9,6 +9,7 @@ namespace CreatureLib::Battling{ class AttackTurnChoice : public BaseTurnChoice { LearnedAttack* _attack; Target _target; + Script* _attackScript; public: AttackTurnChoice(Creature* user, LearnedAttack* attack, const Target& target) : BaseTurnChoice(user), _attack(attack), _target(target){} @@ -29,6 +30,11 @@ namespace CreatureLib::Battling{ const Target& GetTarget() const{ return _target; } + + void GetActiveScripts(ScriptAggregator &aggr) const override { + aggr.Add(_attackScript); + GetUser()->GetActiveScripts(aggr); + } }; } diff --git a/src/Battling/TurnChoices/BaseTurnChoice.hpp b/src/Battling/TurnChoices/BaseTurnChoice.hpp index 05e150d..bdd0db9 100644 --- a/src/Battling/TurnChoices/BaseTurnChoice.hpp +++ b/src/Battling/TurnChoices/BaseTurnChoice.hpp @@ -2,11 +2,12 @@ #define CREATURELIB_BASETURNCHOICE_HPP #include "TurnChoiceKind.hpp" +#include "../ScriptHandling/ScriptSource.hpp" namespace CreatureLib::Battling{ class Creature; - class BaseTurnChoice { + class BaseTurnChoice : public ScriptSource { Creature* _user; protected: BaseTurnChoice(Creature* user) : _user(user){}; @@ -16,6 +17,10 @@ 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 ce2013d..60b3118 100644 --- a/src/Battling/TurnChoices/PassTurnChoice.hpp +++ b/src/Battling/TurnChoices/PassTurnChoice.hpp @@ -11,6 +11,10 @@ namespace CreatureLib::Battling { TurnChoiceKind GetKind() const override { return TurnChoiceKind ::Pass; } + + void GetActiveScripts(ScriptAggregator &aggr) const override { + GetUser()->GetActiveScripts(aggr); + } }; } diff --git a/tests/BattleTests/ChoiceSetTests.cpp b/tests/BattleTests/ChoiceSetTests.cpp index fdb09bf..359ec37 100644 --- a/tests/BattleTests/ChoiceSetTests.cpp +++ b/tests/BattleTests/ChoiceSetTests.cpp @@ -8,7 +8,7 @@ using namespace CreatureLib::Battling; TEST_CASE( "Set Choice one-sized side", "[Battling]" ) { - auto side = BattleSide(1); + auto side = BattleSide(nullptr, 1); auto c = CreateCreature(GetLibrary(), "testSpecies1", 5).Create(); side.SetCreature(c, 0); auto choice = new PassTurnChoice(c); @@ -18,7 +18,7 @@ TEST_CASE( "Set Choice one-sized side", "[Battling]" ) { } TEST_CASE( "Set Choice one-sized side, validate all choices set", "[Battling]" ) { - auto side = BattleSide(1); + auto side = BattleSide(nullptr, 1); auto c = CreateCreature(GetLibrary(), "testSpecies1", 5).Create(); side.SetCreature(c, 0); auto choice = new PassTurnChoice(c); @@ -30,7 +30,7 @@ TEST_CASE( "Set Choice one-sized side, validate all choices set", "[Battling]" ) } TEST_CASE( "Set Choice two-sized side", "[Battling]" ) { - auto side = BattleSide(2); + auto side = BattleSide(nullptr, 2); auto c1 = CreateCreature(GetLibrary(), "testSpecies1", 5).Create(); auto c2 = CreateCreature(GetLibrary(), "testSpecies1", 5).Create(); side.SetCreature(c1, 0); @@ -46,7 +46,7 @@ TEST_CASE( "Set Choice two-sized side", "[Battling]" ) { } TEST_CASE( "Set Choice two-sized side, validate all choices set", "[Battling]" ) { - auto side = BattleSide(2); + auto side = BattleSide(nullptr, 2); auto c1 = CreateCreature(GetLibrary(), "testSpecies1", 5).Create(); auto c2 = CreateCreature(GetLibrary(), "testSpecies1", 5).Create(); side.SetCreature(c1, 0);