From 0b8b92b7f69fcff9d3bc08ec44ab76dd21dd115c Mon Sep 17 00:00:00 2001 From: gsemaj Date: Tue, 12 Apr 2022 23:29:11 -0400 Subject: [PATCH] (WIP) Transitions + hook definitions + onRetreat hook implementation --- src/Abilities.cpp | 24 +++----------------- src/Combat.cpp | 29 ++++++++++++++++++------ src/Entities.hpp | 9 +++++++- src/MobAI.cpp | 56 +++++++++++++++++++++++++---------------------- src/MobAI.hpp | 6 +++++ 5 files changed, 69 insertions(+), 55 deletions(-) diff --git a/src/Abilities.cpp b/src/Abilities.cpp index a84fddb..988947b 100644 --- a/src/Abilities.cpp +++ b/src/Abilities.cpp @@ -449,13 +449,7 @@ bool doDamageNDebuff(Mob* mob, sSkillResult_Damage_N_Debuff* respdata, int i, in respdata[i].iConditionBitFlag = plr->iConditionBitFlag; if (plr->HP <= 0) { - mob->target = nullptr; - mob->state = AIState::RETREAT; - if (!MobAI::aggroCheck(mob, getTime())) { - MobAI::clearDebuff(mob); - if (mob->groupLeader != 0) - MobAI::groupRetreat(mob); - } + mob->transition(AIState::RETREAT); } return true; @@ -529,13 +523,7 @@ bool doDamage(Mob* mob, sSkillResult_Damage* respdata, int i, int32_t targetID, respdata[i].iHP = plr->HP -= damage; if (plr->HP <= 0) { - mob->target = nullptr; - mob->state = AIState::RETREAT; - if (!MobAI::aggroCheck(mob, getTime())) { - MobAI::clearDebuff(mob); - if (mob->groupLeader != 0) - MobAI::groupRetreat(mob); - } + mob->transition(AIState::RETREAT); } return true; @@ -587,13 +575,7 @@ bool doLeech(Mob* mob, sSkillResult_Heal_HP* healdata, int i, int32_t targetID, damagedata->iHP = plr->HP -= damage; if (plr->HP <= 0) { - mob->target = nullptr; - mob->state = AIState::RETREAT; - if (!MobAI::aggroCheck(mob, getTime())) { - MobAI::clearDebuff(mob); - if (mob->groupLeader != 0) - MobAI::groupRetreat(mob); - } + mob->transition(AIState::RETREAT); } return true; diff --git a/src/Combat.cpp b/src/Combat.cpp index d881183..7d9f4f4 100644 --- a/src/Combat.cpp +++ b/src/Combat.cpp @@ -128,6 +128,27 @@ void CombatNPC::step(time_t currTime) { } } +void CombatNPC::transition(AIState newState) { + state = newState; + switch (newState) { + case AIState::INACTIVE: + onInactive(); + break; + case AIState::ROAMING: + onRoamStart(); + break; + case AIState::COMBAT: + onCombatStart(); + break; + case AIState::RETREAT: + onRetreat(); + break; + case AIState::DEAD: + onDeath(); + break; + } +} + static std::pair getDamage(int attackPower, int defensePower, bool shouldCrit, bool batteryBoost, int attackerStyle, int defenderStyle, int difficulty) { @@ -282,13 +303,7 @@ void Combat::npcAttackPc(Mob *mob, time_t currTime) { PlayerManager::sendToViewable(mob->target, respbuf, P_FE2CL_NPC_ATTACK_PCs); if (plr->HP <= 0) { - mob->target = nullptr; - mob->state = AIState::RETREAT; - if (!MobAI::aggroCheck(mob, currTime)) { - MobAI::clearDebuff(mob); - if (mob->groupLeader != 0) - MobAI::groupRetreat(mob); - } + mob->transition(AIState::RETREAT); } } diff --git a/src/Entities.hpp b/src/Entities.hpp index 8c3bfea..cbfeb32 100644 --- a/src/Entities.hpp +++ b/src/Entities.hpp @@ -152,10 +152,17 @@ struct CombatNPC : public BaseNPC, public ICombatant { virtual int32_t getID() override; virtual void step(time_t currTime) override; - virtual void roamingStep(time_t currTime) {} // no-op by default + virtual void roamingStep(time_t currTime) {} // no-ops by default virtual void combatStep(time_t currTime) {} virtual void retreatStep(time_t currTime) {} virtual void deadStep(time_t currTime) {} + + virtual void transition(AIState newState); + virtual void onInactive() {} // no-ops by default + virtual void onRoamStart() {} + virtual void onCombatStart() {} + virtual void onRetreat() {} + virtual void onDeath() {} }; // Mob is in MobAI.hpp, Player is in Player.hpp diff --git a/src/MobAI.cpp b/src/MobAI.cpp index a16478c..0e9675b 100644 --- a/src/MobAI.cpp +++ b/src/MobAI.cpp @@ -266,13 +266,8 @@ static void dealCorruption(Mob *mob, std::vector targetData, int skillID, i respdata[i].iConditionBitFlag = plr->iConditionBitFlag; if (plr->HP <= 0) { - mob->target = nullptr; - mob->state = AIState::RETREAT; - if (!aggroCheck(mob, getTime())) { - clearDebuff(mob); - if (mob->groupLeader != 0) - groupRetreat(mob); - } + if (!MobAI::aggroCheck(mob, getTime())) + mob->transition(AIState::RETREAT); } } @@ -500,13 +495,8 @@ void Mob::combatStep(time_t currTime) { // lose aggro if the player lost connection if (PlayerManager::players.find(target) == PlayerManager::players.end()) { - target = nullptr; - state = AIState::RETREAT; - if (!aggroCheck(this, currTime)) { - clearDebuff(this); - if (groupLeader != 0) - groupRetreat(this); - } + if (!MobAI::aggroCheck(this, getTime())) + transition(AIState::RETREAT); return; } @@ -515,13 +505,8 @@ void Mob::combatStep(time_t currTime) { // lose aggro if the player became invulnerable or died if (plr->HP <= 0 || (plr->iSpecialState & CN_SPECIAL_STATE_FLAG__INVULNERABLE)) { - target = nullptr; - state = AIState::RETREAT; - if (!aggroCheck(this, currTime)) { - clearDebuff(this); - if (groupLeader != 0) - groupRetreat(this); - } + if (!MobAI::aggroCheck(this, getTime())) + transition(AIState::RETREAT); return; } @@ -626,11 +611,7 @@ void Mob::combatStep(time_t currTime) { int xyDistance = hypot(plr->x - roamX, plr->y - roamY); distance = hypot(xyDistance, plr->z - roamZ); if (distance >= data["m_iCombatRange"]) { - target = nullptr; - state = AIState::RETREAT; - clearDebuff(this); - if (groupLeader != 0) - groupRetreat(this); + transition(AIState::RETREAT); } } @@ -773,3 +754,26 @@ void Mob::retreatStep(time_t currTime) { clearDebuff(this); } } + +void Mob::onInactive() { + // stub +} + +void Mob::onRoamStart() { + // stub +} + +void Mob::onCombatStart() { + // stub +} + +void Mob::onRetreat() { + target = nullptr; + MobAI::clearDebuff(this); + if (groupLeader != 0) + MobAI::groupRetreat(this); +} + +void Mob::onDeath() { + // stub +} diff --git a/src/MobAI.hpp b/src/MobAI.hpp index 1c6c178..86721e6 100644 --- a/src/MobAI.hpp +++ b/src/MobAI.hpp @@ -76,6 +76,12 @@ struct Mob : public CombatNPC { virtual void retreatStep(time_t currTime) override; virtual void deadStep(time_t currTime) override; + virtual void onInactive() override; + virtual void onRoamStart() override; + virtual void onCombatStart() override; + virtual void onRetreat() override; + virtual void onDeath() override; + auto operator[](std::string s) { return data[s]; }