aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2017-06-07 02:33:47 +0200
committerGitHub <noreply@github.com>2017-06-07 02:33:47 +0200
commit1660bb7d27d6f42b49012a6b57e3c2b2eab20fd3 (patch)
treecf63a9cb6e89e621d7ae8b901684bc98a40a7e08 /src
parent2335b9de1a46a409c714a1dc89cbd0565545e70e (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.cpp38
-rw-r--r--src/server/game/AI/CoreAI/PetAI.h6
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.h1
-rw-r--r--src/server/game/AI/CreatureAI.cpp27
-rw-r--r--src/server/game/AI/CreatureAI.h8
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp27
-rw-r--r--src/server/game/Handlers/PetHandler.cpp15
-rw-r--r--src/server/game/Spells/Spell.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp11
-rw-r--r--src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/zone_wetlands.cpp11
-rw-r--r--src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp11
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))