Furter rework on script hooks, simplifying required logic.
This commit is contained in:
parent
f72fd5f905
commit
3488784409
|
@ -24,6 +24,10 @@ namespace CreatureLib::Battling{
|
|||
[[nodiscard]] bool HasNext() const{
|
||||
return _current < _queue.size();
|
||||
}
|
||||
|
||||
std::vector<const BaseTurnChoice*>& GetInnerQueue(){
|
||||
return _queue;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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<ScriptSource*, 1> targetSources = {target};
|
||||
std::array<ScriptSource*, 1> 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<ScriptSource*, 1> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<const AttackTurnChoice*>(choice)->GetAttack()->GetRemainingUses() > 1;
|
||||
return dynamic_cast<const AttackTurnChoice*>(choice)->GetAttack()->GetRemainingUses() > 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ void Battle::CheckChoicesSetAndRun() {
|
|||
auto choices = std::vector<const BaseTurnChoice*>(_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<const AttackTurnChoice*>(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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "BattleSide.hpp"
|
||||
#include "../../Core/Exceptions/CreatureException.hpp"
|
||||
#include <algorithm>
|
||||
#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);
|
||||
}
|
||||
|
|
|
@ -6,14 +6,16 @@
|
|||
#include "../TurnChoices/BaseTurnChoice.hpp"
|
||||
|
||||
namespace CreatureLib::Battling{
|
||||
class BattleSide {
|
||||
class BattleSide : public ScriptSource{
|
||||
uint8_t _creaturesPerSide;
|
||||
std::vector<Creature*> _creatures;
|
||||
std::vector<const BaseTurnChoice*> _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;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -65,10 +65,7 @@ namespace CreatureLib::Battling{
|
|||
[[nodiscard]] const std::vector<uint8_t>& 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
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ namespace CreatureLib::Battling {
|
|||
return _attack;
|
||||
}
|
||||
|
||||
void GetActiveScripts(ScriptAggregator &aggr) override {
|
||||
void GetActiveScripts(ScriptAggregator &aggr) const override {
|
||||
aggr.Add(_script);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <vector>
|
||||
|
||||
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){};
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
#include <queue>
|
||||
#include "Script.hpp"
|
||||
#include "ScriptSet.hpp"
|
||||
#include "../../Core/Exceptions/NotReachableException.hpp"
|
||||
|
||||
namespace CreatureLib::Battling{
|
||||
class ScriptAggregator{
|
||||
std::queue<std::any> _queue;
|
||||
bool _isSetSet = false;
|
||||
std::__detail::_Node_iterator<std::pair<const std::string, Script *>, false, true> _setIterator;
|
||||
std::__detail::_Node_iterator<std::pair<const std::string, Script *>, false, true> _setEnd;
|
||||
std::__detail::_Node_const_iterator<std::pair<const std::string, Script *>, false, true> _setIterator;
|
||||
std::__detail::_Node_const_iterator<std::pair<const std::string, Script *>, 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<Script*>(next);
|
||||
}
|
||||
else{
|
||||
auto set = std::any_cast<ScriptSet*>(next);
|
||||
auto set = std::any_cast<const ScriptSet*>(next);
|
||||
if (set->Count() == 0)
|
||||
return GetNext();
|
||||
auto it = set->GetIterator();
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace CreatureLib::Battling{
|
|||
return _scripts.size();
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, Script *> * GetIterator(){
|
||||
const std::unordered_map<std::string, Script *> * GetIterator() const{
|
||||
return &_scripts;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace CreatureLib::Battling{
|
||||
class ScriptSource {
|
||||
public:
|
||||
virtual void GetActiveScripts(ScriptAggregator& aggr) = 0;
|
||||
virtual void GetActiveScripts(ScriptAggregator& aggr) const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,10 @@ namespace CreatureLib::Battling {
|
|||
TurnChoiceKind GetKind() const override {
|
||||
return TurnChoiceKind ::Pass;
|
||||
}
|
||||
|
||||
void GetActiveScripts(ScriptAggregator &aggr) const override {
|
||||
GetUser()->GetActiveScripts(aggr);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue