diff options
author | Shocker <shocker@freakz.ro> | 2012-04-06 18:42:37 -0700 |
---|---|---|
committer | Shocker <shocker@freakz.ro> | 2012-04-06 18:42:37 -0700 |
commit | 1fccaae4b00d0a4e6019ea2735e32ad7dd1962f4 (patch) | |
tree | 703b380beb1c1d97f1129ae92df7cc9eb8f0c3c6 /src | |
parent | 33d5e7c753f484c33f7bbc017bbfc52549a12e30 (diff) | |
parent | cc03f2db361be852302a35389a58ce6888ce6bd5 (diff) |
Merge pull request #6070 from MrSmite/PetAI_3.1
Core/Pets: Improve PetAI
Closes #6048
Closes #6070
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/AI/CoreAI/PetAI.cpp | 61 | ||||
-rwxr-xr-x | src/server/game/AI/CoreAI/PetAI.h | 2 | ||||
-rwxr-xr-x | src/server/game/AI/CreatureAI.h | 6 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 19 | ||||
-rwxr-xr-x | src/server/game/Handlers/PetHandler.cpp | 2 | ||||
-rwxr-xr-x | src/server/game/Spells/Spell.cpp | 13 |
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) |