diff options
-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_wetlands.cpp | 11 | ||||
-rw-r--r-- | src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp | 11 |
10 files changed, 61 insertions, 91 deletions
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index c16e1f945eb..a1c1b72e9b0 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -128,7 +128,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) @@ -322,8 +322,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; @@ -337,7 +347,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 @@ -358,7 +368,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 @@ -626,23 +636,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 4455c1cd494..e243d06debc 100644 --- a/src/server/game/AI/CoreAI/PetAI.h +++ b/src/server/game/AI/CoreAI/PetAI.h @@ -36,11 +36,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 @@ -53,7 +54,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 508d9e70d70..39f54dff66a 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -246,7 +246,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 80d59e4e7cc..54fbabd0b50 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -147,15 +147,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 @@ -211,12 +218,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 41e6ab2501d..754e936862d 100644 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -119,8 +119,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 @@ -146,15 +144,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 @@ -202,6 +199,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 e089a9974a7..088e9345a44 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -730,20 +730,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) @@ -5762,10 +5758,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; @@ -8001,12 +7997,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 3d91ce9afaa..ffc3108c1db 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -35,6 +35,7 @@ #include "SpellInfo.h" #include "SpellMgr.h" #include "SpellPackets.h" +#include "PetAI.h" #include "Util.h" #include "World.h" #include "WorldPacket.h" @@ -211,7 +212,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) @@ -372,7 +377,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 f0e999141f1..94d1b67a895 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3170,9 +3170,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_wetlands.cpp b/src/server/scripts/EasternKingdoms/zone_wetlands.cpp index f192a4bcf8f..c7c4dbbeb5b 100644 --- a/src/server/scripts/EasternKingdoms/zone_wetlands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_wetlands.cpp @@ -105,17 +105,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 88429574c30..fe11aefc77d 100644 --- a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp +++ b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp @@ -120,17 +120,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)) |