diff options
author | Treeston <treeston.mmoc@gmail.com> | 2017-06-07 02:33:47 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-07 02:33:47 +0200 |
commit | 1660bb7d27d6f42b49012a6b57e3c2b2eab20fd3 (patch) | |
tree | cf63a9cb6e89e621d7ae8b901684bc98a40a7e08 /src | |
parent | 2335b9de1a46a409c714a1dc89cbd0565545e70e (diff) |
Pet/Guardian AI hook re-organizing (#19824)
* Pet/Guardian AI hook re-organizing:
- Adjust OwnerAttacked/OwnerAttackedBy hooks on CreatureAI to fire for all owned units, not just player pets. This should allow guardians to more reliably recognize valid targets.
- Kill off the AttackedBy hook. While it was defined in CreatureAI.h as virtual, it was only ever invoked for player pets in specific situations. This makes it classic developer bait.
- Adjust PetAI to use DamageTaken instead of AttackedBy.
- Adjust behavior of AttackStart on PetAI to compensate.
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/AI/CoreAI/PetAI.cpp | 38 | ||||
-rw-r--r-- | src/server/game/AI/CoreAI/PetAI.h | 6 | ||||
-rw-r--r-- | src/server/game/AI/CoreAI/UnitAI.h | 1 | ||||
-rw-r--r-- | src/server/game/AI/CreatureAI.cpp | 27 | ||||
-rw-r--r-- | src/server/game/AI/CreatureAI.h | 8 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 27 | ||||
-rw-r--r-- | src/server/game/Handlers/PetHandler.cpp | 15 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 8 | ||||
-rw-r--r-- | src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp | 11 | ||||
-rw-r--r-- | src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp | 8 | ||||
-rw-r--r-- | src/server/scripts/EasternKingdoms/zone_wetlands.cpp | 11 | ||||
-rw-r--r-- | src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp | 11 |
12 files changed, 61 insertions, 110 deletions
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index c242f4baf54..e278d1f79fb 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -126,7 +126,7 @@ void PetAI::UpdateAI(uint32 diff) // Aggressive - Allow auto select if owner or pet don't have a target // Stay - Only pick from pet or owner targets / attackers so targets won't run by // while chasing our owner. Don't do auto select. - // All other cases (ie: defensive) - Targets are assigned by AttackedBy(), OwnerAttackedBy(), OwnerAttacked(), etc. + // All other cases (ie: defensive) - Targets are assigned by DamageTaken(), OwnerAttackedBy(), OwnerAttacked(), etc. Unit* nextTarget = SelectNextTarget(me->HasReactState(REACT_AGGRESSIVE)); if (nextTarget) @@ -320,8 +320,18 @@ void PetAI::KilledUnit(Unit* victim) void PetAI::AttackStart(Unit* target) { - // Overrides Unit::AttackStart to correctly evaluate Pet states + // Overrides Unit::AttackStart to prevent pet from switching off its assigned target + if (!target || target == me) + return; + + if (me->GetVictim() && me->EnsureVictim()->IsAlive()) + return; + + _AttackStart(target); +} +void PetAI::_AttackStart(Unit* target) +{ // Check all pet states to decide if we can attack this target if (!CanAttack(target)) return; @@ -335,7 +345,7 @@ void PetAI::OwnerAttackedBy(Unit* attacker) // Called when owner takes damage. This function helps keep pets from running off // simply due to owner gaining aggro. - if (!attacker) + if (!attacker || !me->IsAlive()) return; // Passive pets don't do anything @@ -356,7 +366,7 @@ void PetAI::OwnerAttacked(Unit* target) // that they need to assist // Target might be NULL if called from spell with invalid cast targets - if (!target) + if (!target || !me->IsAlive()) return; // Passive pets don't do anything @@ -622,23 +632,3 @@ void PetAI::ClearCharmInfoFlags() ci->SetIsReturning(false); } } - -void PetAI::AttackedBy(Unit* attacker) -{ - // Called when pet takes damage. This function helps keep pets from running off - // simply due to gaining aggro. - - if (!attacker) - return; - - // Passive pets don't do anything - if (me->HasReactState(REACT_PASSIVE)) - return; - - // Prevent pet from disengaging from current target - if (me->GetVictim() && me->EnsureVictim()->IsAlive()) - return; - - // Continue to evaluate and attack if necessary - AttackStart(attacker); -} diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h index b88feac3fc3..7dda6a38644 100644 --- a/src/server/game/AI/CoreAI/PetAI.h +++ b/src/server/game/AI/CoreAI/PetAI.h @@ -37,11 +37,12 @@ class TC_GAME_API PetAI : public CreatureAI static int32 Permissible(Creature const* creature); void KilledUnit(Unit* /*victim*/) override; - void AttackStart(Unit* target) override; + void AttackStart(Unit* target) override; // only start attacking if not attacking something else already + void _AttackStart(Unit* target); // always start attacking if possible void MovementInform(uint32 moveType, uint32 data) override; void OwnerAttackedBy(Unit* attacker) override; void OwnerAttacked(Unit* target) override; - void AttackedBy(Unit* attacker) override; + void DamageTaken(Unit* attacker, uint32& /*damage*/) override { AttackStart(attacker); } void ReceiveEmote(Player* player, uint32 textEmote) override; // The following aren't used by the PetAI but need to be defined to override @@ -54,7 +55,6 @@ class TC_GAME_API PetAI : public CreatureAI void OnCharmed(bool /*apply*/) override; private: - bool _isVisible(Unit*) const; bool _needToStop(void); void _stopAttack(void); diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h index bbd2e7de74c..0e0d2200280 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -266,7 +266,6 @@ class TC_GAME_API UnitAI // Called at any Damage from any attacker (before damage apply) // Note: it for recalculation damage or special reaction at damage - // for attack reaction use AttackedBy called for not DOT damage in Unit::DealDamage also virtual void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) { } // Called when the creature receives heal diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index 9bc5a397ea5..281795c0ed1 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -132,15 +132,22 @@ void CreatureAI::MoveInLineOfSight(Unit* who) if (me->GetVictim()) return; - if (me->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET) // non-combat pets should just stand there and look good;) - return; - if (me->HasReactState(REACT_AGGRESSIVE) && me->CanStartAttack(who, false)) AttackStart(who); - //else if (who->GetVictim() && me->IsFriendlyTo(who) - // && me->IsWithinDistInMap(who, sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS)) - // && me->CanStartAttack(who->GetVictim(), true)) /// @todo if we use true, it will not attack it when it arrives - // me->GetMotionMaster()->MoveChase(who->GetVictim()); +} + +void CreatureAI::_OnOwnerCombatInteraction(Unit* target) +{ + if (!target || !me->IsAlive()) + return; + + if (!me->HasReactState(REACT_PASSIVE) && me->CanStartAttack(target, true)) + { + if (me->IsInCombat()) + me->AddThreat(target, 0.0f); + else + AttackStart(target); + } } // Distract creature, if player gets too close while stealthed/prowling @@ -196,12 +203,6 @@ void CreatureAI::EnterEvadeMode(EvadeReason why) me->GetVehicleKit()->Reset(true); } -/*void CreatureAI::AttackedBy(Unit* attacker) -{ - if (!me->GetVictim()) - AttackStart(attacker); -}*/ - void CreatureAI::SetGazeOn(Unit* target) { if (me->IsValidAttackTarget(target)) diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h index 7fc930210d0..79bcefb3946 100644 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -131,8 +131,6 @@ class TC_GAME_API CreatureAI : public UnitAI // Called when spell hits a target virtual void SpellHitTarget(Unit* /*target*/, SpellInfo const* /*spell*/) { } - // Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc) - virtual void AttackedBy(Unit* /*attacker*/) { } virtual bool IsEscorted() const { return false; } // Called when creature is spawned or respawned @@ -152,15 +150,14 @@ class TC_GAME_API CreatureAI : public UnitAI virtual void ReceiveEmote(Player* /*player*/, uint32 /*emoteId*/) { } // Called when owner takes damage - virtual void OwnerAttackedBy(Unit* /*attacker*/) { } + virtual void OwnerAttackedBy(Unit* attacker) { _OnOwnerCombatInteraction(attacker); } // Called when owner attacks something - virtual void OwnerAttacked(Unit* /*target*/) { } + virtual void OwnerAttacked(Unit* target) { _OnOwnerCombatInteraction(target); } /// == Triggered Actions Requested ================== // Called when creature attack expected (if creature can and no have current victim) - // Note: for reaction at hostile action must be called AttackedBy function. //virtual void AttackStart(Unit*) { } // Called at World update tick @@ -208,6 +205,7 @@ class TC_GAME_API CreatureAI : public UnitAI private: bool m_MoveInLineOfSight_locked; + void _OnOwnerCombatInteraction(Unit* target); }; enum Permitions : int32 diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f16366e50e9..e1633edbeaa 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -683,20 +683,16 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam // Signal to pets that their owner was attacked - except when DOT. if (damagetype != DOT) { - Pet* pet = victim->ToPlayer()->GetPet(); - - if (pet && pet->IsAlive()) - pet->AI()->OwnerAttackedBy(this); + for (Unit* controlled : victim->m_Controlled) + if (Creature* cControlled = controlled->ToCreature()) + if (cControlled->IsAIEnabled) + cControlled->AI()->OwnerAttackedBy(this); } if (victim->ToPlayer()->GetCommandStatus(CHEAT_GOD)) return 0; } - // Signal the pet it was attacked so the AI can respond if needed - if (victim->GetTypeId() == TYPEID_UNIT && this != victim && victim->IsPet() && victim->IsAlive()) - victim->ToPet()->AI()->AttackedBy(this); - if (damagetype != NODAMAGE) { // interrupting auras with AURA_INTERRUPT_FLAG_DAMAGE before checking !damage (absorbed damage breaks that type of auras) @@ -5894,10 +5890,10 @@ bool Unit::Attack(Unit* victim, bool meleeAttack) // Spells such as auto-shot and others handled in WorldSession::HandleCastSpellOpcode if (GetTypeId() == TYPEID_PLAYER) { - Pet* playerPet = this->ToPlayer()->GetPet(); - - if (playerPet && playerPet->IsAlive()) - playerPet->AI()->OwnerAttacked(victim); + for (Unit* controlled : m_Controlled) + if (Creature* cControlled = controlled->ToCreature()) + if (cControlled->IsAIEnabled) + cControlled->AI()->OwnerAttacked(victim); } return true; @@ -8682,12 +8678,7 @@ void Unit::CombatStart(Unit* target, bool initialAggro) if (!target->IsInCombat() && target->GetTypeId() != TYPEID_PLAYER && !target->ToCreature()->HasReactState(REACT_PASSIVE) && target->ToCreature()->IsAIEnabled) - { - if (target->IsPet()) - target->ToCreature()->AI()->AttackedBy(this); // PetAI has special handler before AttackStart() - else - target->ToCreature()->AI()->AttackStart(this); - } + target->ToCreature()->AI()->AttackStart(this); SetInCombatWith(target); target->SetInCombatWith(this); diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index c618978dff0..53dc69ffd94 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -26,6 +26,7 @@ #include "Spell.h" #include "ObjectAccessor.h" #include "CreatureAI.h" +#include "PetAI.h" #include "Util.h" #include "Pet.h" #include "World.h" @@ -216,7 +217,11 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe charmInfo->SetIsCommandFollow(false); charmInfo->SetIsReturning(false); - pet->ToCreature()->AI()->AttackStart(TargetUnit); + CreatureAI* AI = pet->ToCreature()->AI(); + if (PetAI* petAI = dynamic_cast<PetAI*>(AI)) + petAI->_AttackStart(TargetUnit); // force target switch + else + AI->AttackStart(TargetUnit); //10% chance to play special pet attack talk, else growl if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) @@ -365,7 +370,13 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe { pet->GetMotionMaster()->Clear(); if (pet->ToCreature()->IsAIEnabled) - pet->ToCreature()->AI()->AttackStart(unit_target); + { + CreatureAI* AI = pet->ToCreature()->AI(); + if (PetAI* petAI = dynamic_cast<PetAI*>(AI)) + petAI->_AttackStart(unit_target); // force victim switch + else + AI->AttackStart(unit_target); + } } } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 83d19be8472..4b08d3bf9c3 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3116,9 +3116,11 @@ void Spell::_cast(bool skipCheck) // Let any pets know we've attacked something. Check DmgClass for harmful spells only // This prevents spells such as Hunter's Mark from triggering pet attack if (this->GetSpellInfo()->DmgClass != SPELL_DAMAGE_CLASS_NONE) - if (Pet* playerPet = playerCaster->GetPet()) - if (playerPet->IsAlive() && playerPet->isControlled() && (m_targets.GetTargetMask() & TARGET_FLAG_UNIT)) - playerPet->AI()->OwnerAttacked(m_targets.GetUnitTarget()); + if (Unit* unitTarget = m_targets.GetUnitTarget()) + for (Unit* controlled : playerCaster->m_Controlled) + if (Creature* cControlled = controlled->ToCreature()) + if (cControlled->IsAIEnabled) + cControlled->AI()->OwnerAttacked(unitTarget); } SetExecutedCurrently(true); diff --git a/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp b/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp index 576b6ac7e98..dab69c434e6 100644 --- a/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp +++ b/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp @@ -66,17 +66,6 @@ public: me->SetFaction(m_uiNormalFaction); } - void AttackedBy(Unit* pAttacker) override - { - if (me->GetVictim()) - return; - - if (me->IsFriendlyTo(pAttacker)) - return; - - AttackStart(pAttacker); - } - void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) override { if (uiDamage > me->GetHealth() || me->HealthBelowPctDamaged(15, uiDamage)) diff --git a/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp b/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp index e17dd6a805a..a8d6b67b718 100644 --- a/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp +++ b/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp @@ -80,14 +80,6 @@ public: void EnterCombat(Unit* /*who*/) override { } - void AttackedBy(Unit* pAttacker) override - { - if (me->GetVictim() || me->IsFriendlyTo(pAttacker)) - return; - - AttackStart(pAttacker); - } - void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) override { if (uiDamage > me->GetHealth() || me->HealthBelowPctDamaged(15, uiDamage)) diff --git a/src/server/scripts/EasternKingdoms/zone_wetlands.cpp b/src/server/scripts/EasternKingdoms/zone_wetlands.cpp index d460f3ec1e3..2966af7a3c5 100644 --- a/src/server/scripts/EasternKingdoms/zone_wetlands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_wetlands.cpp @@ -106,17 +106,6 @@ public: summoned->AI()->AttackStart(player); } - void AttackedBy(Unit* pAttacker) override - { - if (me->GetVictim()) - return; - - if (me->IsFriendlyTo(pAttacker)) - return; - - AttackStart(pAttacker); - } - void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) override { if (HealthBelowPct(20)) diff --git a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp index d743f8ff07d..2c44c1b91aa 100644 --- a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp +++ b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp @@ -122,17 +122,6 @@ public: me->RestoreFaction(); } - void AttackedBy(Unit* pAttacker) override - { - if (me->GetVictim()) - return; - - if (me->IsFriendlyTo(pAttacker)) - return; - - AttackStart(pAttacker); - } - void DamageTaken(Unit* pDoneBy, uint32 &Damage) override { if (Damage > me->GetHealth() || me->HealthBelowPctDamaged(20, Damage)) |