aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShocker <shocker@freakz.ro>2012-04-06 18:42:37 -0700
committerShocker <shocker@freakz.ro>2012-04-06 18:42:37 -0700
commit1fccaae4b00d0a4e6019ea2735e32ad7dd1962f4 (patch)
tree703b380beb1c1d97f1129ae92df7cc9eb8f0c3c6 /src
parent33d5e7c753f484c33f7bbc017bbfc52549a12e30 (diff)
parentcc03f2db361be852302a35389a58ce6888ce6bd5 (diff)
Merge pull request #6070 from MrSmite/PetAI_3.1
Core/Pets: Improve PetAI Closes #6048 Closes #6070
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/AI/CoreAI/PetAI.cpp61
-rwxr-xr-xsrc/server/game/AI/CoreAI/PetAI.h2
-rwxr-xr-xsrc/server/game/AI/CreatureAI.h6
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp19
-rwxr-xr-xsrc/server/game/Handlers/PetHandler.cpp2
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp13
6 files changed, 93 insertions, 10 deletions
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index 295768f9d3e..bcec8d273b9 100755
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -109,17 +109,25 @@ void PetAI::UpdateAI(const uint32 diff)
}
else if (owner && me->GetCharmInfo()) //no victim
{
- Unit* nextTarget = SelectNextTarget();
+ // Only aggressive pets do target search every update.
+ // Defensive pets do target search only in these cases:
+ // * Owner attacks something - handled by OwnerAttacked()
+ // * Owner receives damage - handled by OwnerDamagedBy()
+ // * Pet is in combat and current target dies - handled by KilledUnit()
+ if (me->HasReactState(REACT_AGGRESSIVE))
+ {
+ Unit* nextTarget = SelectNextTarget();
- if (me->HasReactState(REACT_PASSIVE))
- _stopAttack();
- else if (nextTarget)
- AttackStart(nextTarget);
+ if (nextTarget)
+ AttackStart(nextTarget);
+ else
+ HandleReturnMovement();
+ }
else
HandleReturnMovement();
}
else if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW)) // no charm info and no victim
- me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle());
+ HandleReturnMovement();
if (!me->GetCharmInfo())
return;
@@ -302,6 +310,47 @@ void PetAI::AttackStart(Unit* target)
DoAttack(target, true);
}
+void PetAI::OwnerDamagedBy(Unit* attacker)
+{
+ // Called when owner takes damage. Allows defensive pets to know
+ // that their owner might need help
+
+ 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->getVictim()->isAlive())
+ return;
+
+ // Continue to evaluate and attack if necessary
+ AttackStart(attacker);
+}
+
+void PetAI::OwnerAttacked(Unit* target)
+{
+ // Called when owner attacks something. Allows defensive pets to know
+ // that they need to assist
+
+ // Target might be NULL if called from spell with invalid cast targets
+ if (!target)
+ return;
+
+ // Passive pets don't do anything
+ if (me->HasReactState(REACT_PASSIVE))
+ return;
+
+ // Prevent pet from disengaging from current target
+ if (me->getVictim() && me->getVictim()->isAlive())
+ return;
+
+ // Continue to evaluate and attack if necessary
+ AttackStart(target);
+}
+
Unit* PetAI::SelectNextTarget()
{
// Provides next target selection after current target death
diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h
index 730ab12a3ca..ed3e2305556 100755
--- a/src/server/game/AI/CoreAI/PetAI.h
+++ b/src/server/game/AI/CoreAI/PetAI.h
@@ -40,6 +40,8 @@ class PetAI : public CreatureAI
void KilledUnit(Unit* /*victim*/);
void AttackStart(Unit* target);
void MovementInform(uint32 moveType, uint32 data);
+ void OwnerDamagedBy(Unit* attacker);
+ void OwnerAttacked(Unit* target);
private:
bool _isVisible(Unit*) const;
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index 423b00291e7..94ac452b9f3 100755
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -138,6 +138,12 @@ class CreatureAI : public UnitAI
// Called at text emote receive from player
virtual void ReceiveEmote(Player* /*player*/, uint32 /*emoteId*/) {}
+ // Called when owner takes damage
+ virtual void OwnerDamagedBy(Unit* /*attacker*/) {}
+
+ // Called when owner attacks something
+ virtual void OwnerAttacked(Unit* /*target*/) {}
+
/// == Triggered Actions Requested ==================
// Called when creature attack expected (if creature can and no have current victim)
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index b49ce1bf075..94ef6edbeca 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -572,6 +572,15 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (IsAIEnabled)
GetAI()->DamageDealt(victim, damage, damagetype);
+ // Signal to pets that their owner was attacked
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ {
+ Pet* pet = victim->ToPlayer()->GetPet();
+
+ if (pet && pet->isAlive())
+ pet->AI()->OwnerDamagedBy(this);
+ }
+
if (damagetype != NODAMAGE)
{
// interrupting auras with AURA_INTERRUPT_FLAG_DAMAGE before checking !damage (absorbed damage breaks that type of auras)
@@ -9515,6 +9524,16 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
if (meleeAttack)
SendMeleeAttackStart(victim);
+ // Let the pet know we've started attacking someting. Handles melee attacks only
+ // Spells such as auto-shot and others handled in WorldSession::HandleCastSpellOpcode
+ if (this->GetTypeId() == TYPEID_PLAYER)
+ {
+ Pet* playerPet = this->ToPlayer()->GetPet();
+
+ if (playerPet && playerPet->isAlive())
+ playerPet->AI()->OwnerAttacked(victim);
+ }
+
return true;
}
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index 1fa6d9fc0ed..e54bee96b8b 100755
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -153,8 +153,6 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid
switch (spellid)
{
case COMMAND_STAY: //flat=1792 //STAY
- pet->AttackStop();
- pet->InterruptNonMeleeSpells(false);
pet->StopMoving();
pet->GetMotionMaster()->Clear(false);
pet->GetMotionMaster()->MoveIdle();
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 82a89e97e4b..8759cfd9acc 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -3101,11 +3101,20 @@ void Spell::cast(bool skipCheck)
return;
}
- // now that we've done the basic check, now run the scripts
- // should be done before the spell is actually executed
if (Player* playerCaster = m_caster->ToPlayer())
+ {
+ // now that we've done the basic check, now run the scripts
+ // should be done before the spell is actually executed
sScriptMgr->OnPlayerSpellCast(playerCaster, this, skipCheck);
+ // Let any pets know we've attacked something. As of 3.0.2 pets begin
+ // attacking their owner's target immediately
+ if (Pet* playerPet = playerCaster->GetPet())
+ {
+ if (playerPet->isAlive() && playerPet->isControlled() && (m_targets.GetTargetMask() & TARGET_FLAG_UNIT))
+ playerPet->AI()->OwnerAttacked(m_targets.GetObjectTarget()->ToUnit());
+ }
+ }
SetExecutedCurrently(true);
if (m_caster->GetTypeId() != TYPEID_PLAYER && m_targets.GetUnitTarget() && m_targets.GetUnitTarget() != m_caster)