From d85e95295dcedb12893e7e02546a377d8a534d86 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 14 Apr 2009 07:21:04 +0400 Subject: [PATCH] [7668] Cleanup In CreatureAI function descriptions and AttackStart/AttackedBy use. * Use AI::AttackStart calls only in case explicit request creature attack from core or AI code "attack it if can". Like taunt, pet handler attack command. * Use AI::AttackedBy for reaction at hostile action "do something at hostile action" Like non-dot damage, swing, negative spell landing, or fade fear/etc. And provided by default call AttackStart if no current target. This fix some problems, like: * Civilian will react propertly at attack by another creature (not pet or player). * Will not cases (at least triggred by core) when attack target start run to attacker before any real hostile action apply. --- src/bindings/universal/ScriptMgr.h | 28 +-------------- src/game/CreatureAI.cpp | 7 ++++ src/game/CreatureAI.h | 48 +++++++++++++++---------- src/game/NullCreatureAI.h | 1 + src/game/PetAI.h | 1 - src/game/Spell.cpp | 2 +- src/game/SpellAuras.cpp | 4 +-- src/game/SpellEffects.cpp | 2 +- src/game/TotemAI.cpp | 2 +- src/game/Unit.cpp | 57 ++++++++++++++---------------- src/shared/revision_nr.h | 2 +- 11 files changed, 72 insertions(+), 82 deletions(-) diff --git a/src/bindings/universal/ScriptMgr.h b/src/bindings/universal/ScriptMgr.h index 390296bfe..7bfaf2431 100644 --- a/src/bindings/universal/ScriptMgr.h +++ b/src/bindings/universal/ScriptMgr.h @@ -78,29 +78,15 @@ struct Script #define VISIBLE_RANGE (50.0f) +// Read function descriptions in CreatureAI struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI { explicit ScriptedAI(Creature* creature) : CreatureAI(creature) {} ~ScriptedAI() {} - // Called if IsVisible(Unit *who) is true at each *who move - void MoveInLineOfSight(Unit *) {} - - // Called at each attack of m_creature by any victim - void AttackStart(Unit *) {} - // Called at stopping attack by any attacker void EnterEvadeMode(); - // Called at any heal cast/item used (call non implemented) - void HealBy(Unit* /*healer*/, uint32 /*amount_healed*/) {} - - // Called at any Damage to any victim (before damage apply) - void DamageDeal(Unit* /*done_to*/, uint32& /*damage*/) {} - - // Called at any Damage from any attacker (before damage apply) - void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/) {} - // Is unit visible for MoveInLineOfSight bool IsVisible(Unit* who) const { @@ -110,18 +96,6 @@ struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI // Called at World update tick void UpdateAI(const uint32); - // Called when the creature is killed - void JustDied(Unit *){} - - // Called when the creature kills a unit - void KilledUnit(Unit *){} - - // Called when hit by a spell - void SpellHit(Unit *, const SpellEntry*){} - - // Called when spell hits creature's target - void SpellHitTarget(Unit*, const SpellEntry*) {} - //= Some useful helpers ========================= // Start attack of victim and go to him diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp index b4f916f34..784ea7d35 100644 --- a/src/game/CreatureAI.cpp +++ b/src/game/CreatureAI.cpp @@ -17,7 +17,14 @@ */ #include "CreatureAI.h" +#include "Creature.h" CreatureAI::~CreatureAI() { } + +void CreatureAI::AttackedBy( Unit* attacker ) +{ + if(!m_creature->getVictim()) + AttackStart(attacker); +} diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index fbd2bc57a..9b6e29f29 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -40,14 +40,13 @@ class MANGOS_DLL_SPEC CreatureAI virtual ~CreatureAI(); - // Called if IsVisible(Unit *who) is true at each *who move - virtual void MoveInLineOfSight(Unit *) = 0; + ///== Reactions At ================================= - // Called at each attack of m_creature by any victim - virtual void AttackStart(Unit *) = 0; + // Called if IsVisible(Unit *who) is true at each *who move, reaction at visibility zone enter + virtual void MoveInLineOfSight(Unit *) {} - // Called at stopping attack by any attacker - virtual void EnterEvadeMode() = 0; + // Called for reaction at stopping attack at no attackers or targets + virtual void EnterEvadeMode() {} // Called at reaching home after evade virtual void JustReachedHome() {} @@ -59,13 +58,9 @@ class MANGOS_DLL_SPEC CreatureAI virtual void DamageDeal(Unit * /*done_to*/, uint32 & /*damage*/) {} // Called at any Damage from any attacker (before damage apply) - virtual void DamageTaken(Unit *done_by, uint32 & /*damage*/) { AttackedBy(done_by); } - - // Is unit visible for MoveInLineOfSight - virtual bool IsVisible(Unit *) const = 0; - - // Called at World update tick - virtual void UpdateAI(const uint32 diff ) = 0; + // 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 *done_by, uint32 & /*damage*/) {} // Called when the creature is killed virtual void JustDied(Unit *) {} @@ -84,11 +79,8 @@ class MANGOS_DLL_SPEC CreatureAI // Called when spell hits creature's target virtual void SpellHitTarget(Unit*, const SpellEntry*) {} - // Called when vitim entered water and creature can not enter water - virtual bool canReachByRangeAttack(Unit*) { return false; } - - // Called when the creature is attacked - virtual void AttackedBy(Unit * /*attacker*/) {} + // Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc) + virtual void AttackedBy(Unit* attacker); // Called when creature is spawned or respawned (for reseting variables) virtual void JustRespawned() {} @@ -96,6 +88,26 @@ class MANGOS_DLL_SPEC CreatureAI // Called at waypoint reached or point movement finished virtual void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) {} + ///== 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 + virtual void UpdateAI(const uint32 diff ) {} + + ///== State checks ================================= + + // Is unit visible for MoveInLineOfSight + virtual bool IsVisible(Unit *) const { return false; } + + // Called when victim entered water and creature can not enter water + virtual bool canReachByRangeAttack(Unit*) { return false; } + + ///== Fields ======================================= + + // Pointer to controlled by AI creature Creature* const m_creature; }; diff --git a/src/game/NullCreatureAI.h b/src/game/NullCreatureAI.h index 9683f01dc..c56c968c1 100644 --- a/src/game/NullCreatureAI.h +++ b/src/game/NullCreatureAI.h @@ -30,6 +30,7 @@ class MANGOS_DLL_DECL NullCreatureAI : public CreatureAI void MoveInLineOfSight(Unit *) {} void AttackStart(Unit *) {} + void AttackedBy( Unit *) {} void EnterEvadeMode() {} bool IsVisible(Unit *) const { return false; } diff --git a/src/game/PetAI.h b/src/game/PetAI.h index 60c5c5113..02a412934 100644 --- a/src/game/PetAI.h +++ b/src/game/PetAI.h @@ -34,7 +34,6 @@ class MANGOS_DLL_DECL PetAI : public CreatureAI void MoveInLineOfSight(Unit *); void AttackStart(Unit *); void EnterEvadeMode(); - void DamageTaken(Unit *done_by, uint32& /*damage*/) { AttackedBy(done_by); } void AttackedBy(Unit*); bool IsVisible(Unit *) const; void JustDied(Unit* /*who*/) { _stopAttack(); } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 3ec1f0088..d9c972297 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1140,7 +1140,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) unit->SetStandState(UNIT_STAND_STATE_STAND); if(!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI()) - ((Creature*)unit)->AI()->AttackStart(m_caster); + ((Creature*)unit)->AI()->AttackedBy(m_caster); unit->SetInCombatWith(m_caster); m_caster->SetInCombatWith(unit); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index fba21e746..55a08c912 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3116,7 +3116,7 @@ void Aura::HandleModPossess(bool apply, bool Real) ((Creature*)m_target)->AIM_Initialize(); if (((Creature*)m_target)->AI()) - ((Creature*)m_target)->AI()->AttackStart(caster); + ((Creature*)m_target)->AI()->AttackedBy(caster); } } } @@ -3269,7 +3269,7 @@ void Aura::HandleModCharm(bool apply, bool Real) { ((Creature*)m_target)->AIM_Initialize(); if (((Creature*)m_target)->AI()) - ((Creature*)m_target)->AI()->AttackStart(caster); + ((Creature*)m_target)->AI()->AttackedBy(caster); } } } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 04d36d3fc..74ed51043 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -3508,7 +3508,7 @@ void Spell::EffectPickPocket(uint32 /*i*/) // Reveal action + get attack m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); if (((Creature*)unitTarget)->AI()) - ((Creature*)unitTarget)->AI()->AttackStart(m_caster); + ((Creature*)unitTarget)->AI()->AttackedBy(m_caster); } } } diff --git a/src/game/TotemAI.cpp b/src/game/TotemAI.cpp index 5b161ccbd..8b1f6bd3c 100644 --- a/src/game/TotemAI.cpp +++ b/src/game/TotemAI.cpp @@ -123,4 +123,4 @@ TotemAI::AttackStart(Unit *) Totem& TotemAI::getTotem() { return static_cast(*m_creature); -} \ No newline at end of file +} diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index fca037f6d..a063c5dc1 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -419,28 +419,22 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa if (!spellProto || !(spellProto->Mechanic == MECHANIC_ROOT || IsAuraAddedBySpell(SPELL_AURA_MOD_ROOT, spellProto->Id))) pVictim->RemoveSpellbyDamageTaken(SPELL_AURA_MOD_ROOT, damage); - if(pVictim->GetTypeId() != TYPEID_PLAYER) + // no xp,health if type 8 /critters/ + if(pVictim->GetTypeId() != TYPEID_PLAYER && pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER) { - // no xp,health if type 8 /critters/ - if ( pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER) - { - pVictim->setDeathState(JUST_DIED); - pVictim->SetHealth(0); + pVictim->setDeathState(JUST_DIED); + pVictim->SetHealth(0); - // allow loot only if has loot_id in creature_template - CreatureInfo const* cInfo = ((Creature*)pVictim)->GetCreatureInfo(); - if(cInfo && cInfo->lootid) - pVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + // allow loot only if has loot_id in creature_template + CreatureInfo const* cInfo = ((Creature*)pVictim)->GetCreatureInfo(); + if(cInfo && cInfo->lootid) + pVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - // some critters required for quests - if(GetTypeId() == TYPEID_PLAYER) - ((Player*)this)->KilledMonster(pVictim->GetEntry(),pVictim->GetGUID()); + // some critters required for quests + if(GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->KilledMonster(pVictim->GetEntry(),pVictim->GetGUID()); - return damage; - } - - if(!pVictim->isInCombat() && ((Creature*)pVictim)->AI()) - ((Creature*)pVictim)->AI()->AttackStart(this); + return damage; } DEBUG_LOG("DealDamageStart"); @@ -689,18 +683,16 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa if(damagetype != DOT) { - if(getVictim()) - { - // if have target and damage pVictim just call AI reaction - if(pVictim != getVictim() && pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI()) - ((Creature*)pVictim)->AI()->AttackedBy(this); - } - else + if(!getVictim()) { // if not have main target then attack state with target (including AI call) //start melee attacks only after melee hit Attack(pVictim,(damagetype == DIRECT_DAMAGE)); } + + // if damage pVictim call AI reaction + if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI()) + ((Creature*)pVictim)->AI()->AttackedBy(this); } // polymorphed and other negative transformed cases @@ -1962,6 +1954,10 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex } } + // if damage pVictim call AI reaction + if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI()) + ((Creature*)pVictim)->AI()->AttackedBy(this); + return; } @@ -1989,6 +1985,10 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex --m_extraAttacks; } } + + // if damage pVictim call AI reaction + if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI()) + ((Creature*)pVictim)->AI()->AttackedBy(this); } MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit *pVictim, WeaponAttackType attType) const @@ -7165,9 +7165,6 @@ bool Unit::Attack(Unit *victim, bool meleeAttack) m_attacking = victim; m_attacking->_addAttacker(this); - if(m_attacking->GetTypeId()==TYPEID_UNIT && ((Creature*)m_attacking)->AI()) - ((Creature*)m_attacking)->AI()->AttackedBy(this); - if(GetTypeId()==TYPEID_UNIT) { WorldPacket data(SMSG_AI_REACTION, 12); @@ -10738,8 +10735,8 @@ void Unit::SetFeared(bool apply, uint64 casterGUID, uint32 spellID) // attack caster if can Unit* caster = ObjectAccessor::GetObjectInWorld(casterGUID, (Unit*)NULL); - if(caster && caster != getVictim() && ((Creature*)this)->AI()) - ((Creature*)this)->AI()->AttackStart(caster); + if(caster && ((Creature*)this)->AI()) + ((Creature*)this)->AI()->AttackedBy(caster); } } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index fe876d9ab..54ec963b2 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7667" + #define REVISION_NR "7668" #endif // __REVISION_NR_H__