[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.
This commit is contained in:
VladimirMangos 2009-04-14 07:21:04 +04:00
parent 69fb9736cc
commit d85e95295d
11 changed files with 72 additions and 82 deletions

View file

@ -78,29 +78,15 @@ struct Script
#define VISIBLE_RANGE (50.0f) #define VISIBLE_RANGE (50.0f)
// Read function descriptions in CreatureAI
struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI
{ {
explicit ScriptedAI(Creature* creature) : CreatureAI(creature) {} explicit ScriptedAI(Creature* creature) : CreatureAI(creature) {}
~ScriptedAI() {} ~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 // Called at stopping attack by any attacker
void EnterEvadeMode(); 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 // Is unit visible for MoveInLineOfSight
bool IsVisible(Unit* who) const bool IsVisible(Unit* who) const
{ {
@ -110,18 +96,6 @@ struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI
// Called at World update tick // Called at World update tick
void UpdateAI(const uint32); 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 ========================= //= Some useful helpers =========================
// Start attack of victim and go to him // Start attack of victim and go to him

View file

@ -17,7 +17,14 @@
*/ */
#include "CreatureAI.h" #include "CreatureAI.h"
#include "Creature.h"
CreatureAI::~CreatureAI() CreatureAI::~CreatureAI()
{ {
} }
void CreatureAI::AttackedBy( Unit* attacker )
{
if(!m_creature->getVictim())
AttackStart(attacker);
}

View file

@ -40,14 +40,13 @@ class MANGOS_DLL_SPEC CreatureAI
virtual ~CreatureAI(); virtual ~CreatureAI();
// Called if IsVisible(Unit *who) is true at each *who move ///== Reactions At =================================
virtual void MoveInLineOfSight(Unit *) = 0;
// Called at each attack of m_creature by any victim // Called if IsVisible(Unit *who) is true at each *who move, reaction at visibility zone enter
virtual void AttackStart(Unit *) = 0; virtual void MoveInLineOfSight(Unit *) {}
// Called at stopping attack by any attacker // Called for reaction at stopping attack at no attackers or targets
virtual void EnterEvadeMode() = 0; virtual void EnterEvadeMode() {}
// Called at reaching home after evade // Called at reaching home after evade
virtual void JustReachedHome() {} virtual void JustReachedHome() {}
@ -59,13 +58,9 @@ class MANGOS_DLL_SPEC CreatureAI
virtual void DamageDeal(Unit * /*done_to*/, uint32 & /*damage*/) {} virtual void DamageDeal(Unit * /*done_to*/, uint32 & /*damage*/) {}
// Called at any Damage from any attacker (before damage apply) // Called at any Damage from any attacker (before damage apply)
virtual void DamageTaken(Unit *done_by, uint32 & /*damage*/) { AttackedBy(done_by); } // Note: it for recalculation damage or special reaction at damage
// for attack reaction use AttackedBy called for not DOT damage in Unit::DealDamage also
// Is unit visible for MoveInLineOfSight virtual void DamageTaken(Unit *done_by, uint32 & /*damage*/) {}
virtual bool IsVisible(Unit *) const = 0;
// Called at World update tick
virtual void UpdateAI(const uint32 diff ) = 0;
// Called when the creature is killed // Called when the creature is killed
virtual void JustDied(Unit *) {} virtual void JustDied(Unit *) {}
@ -84,11 +79,8 @@ class MANGOS_DLL_SPEC CreatureAI
// Called when spell hits creature's target // Called when spell hits creature's target
virtual void SpellHitTarget(Unit*, const SpellEntry*) {} virtual void SpellHitTarget(Unit*, const SpellEntry*) {}
// Called when vitim entered water and creature can not enter water // Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc)
virtual bool canReachByRangeAttack(Unit*) { return false; } virtual void AttackedBy(Unit* attacker);
// Called when the creature is attacked
virtual void AttackedBy(Unit * /*attacker*/) {}
// Called when creature is spawned or respawned (for reseting variables) // Called when creature is spawned or respawned (for reseting variables)
virtual void JustRespawned() {} virtual void JustRespawned() {}
@ -96,6 +88,26 @@ class MANGOS_DLL_SPEC CreatureAI
// Called at waypoint reached or point movement finished // Called at waypoint reached or point movement finished
virtual void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) {} 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; Creature* const m_creature;
}; };

View file

@ -30,6 +30,7 @@ class MANGOS_DLL_DECL NullCreatureAI : public CreatureAI
void MoveInLineOfSight(Unit *) {} void MoveInLineOfSight(Unit *) {}
void AttackStart(Unit *) {} void AttackStart(Unit *) {}
void AttackedBy( Unit *) {}
void EnterEvadeMode() {} void EnterEvadeMode() {}
bool IsVisible(Unit *) const { return false; } bool IsVisible(Unit *) const { return false; }

View file

@ -34,7 +34,6 @@ class MANGOS_DLL_DECL PetAI : public CreatureAI
void MoveInLineOfSight(Unit *); void MoveInLineOfSight(Unit *);
void AttackStart(Unit *); void AttackStart(Unit *);
void EnterEvadeMode(); void EnterEvadeMode();
void DamageTaken(Unit *done_by, uint32& /*damage*/) { AttackedBy(done_by); }
void AttackedBy(Unit*); void AttackedBy(Unit*);
bool IsVisible(Unit *) const; bool IsVisible(Unit *) const;
void JustDied(Unit* /*who*/) { _stopAttack(); } void JustDied(Unit* /*who*/) { _stopAttack(); }

View file

@ -1140,7 +1140,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
unit->SetStandState(UNIT_STAND_STATE_STAND); unit->SetStandState(UNIT_STAND_STATE_STAND);
if(!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI()) 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); unit->SetInCombatWith(m_caster);
m_caster->SetInCombatWith(unit); m_caster->SetInCombatWith(unit);

View file

@ -3116,7 +3116,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
((Creature*)m_target)->AIM_Initialize(); ((Creature*)m_target)->AIM_Initialize();
if (((Creature*)m_target)->AI()) 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(); ((Creature*)m_target)->AIM_Initialize();
if (((Creature*)m_target)->AI()) if (((Creature*)m_target)->AI())
((Creature*)m_target)->AI()->AttackStart(caster); ((Creature*)m_target)->AI()->AttackedBy(caster);
} }
} }
} }

View file

@ -3508,7 +3508,7 @@ void Spell::EffectPickPocket(uint32 /*i*/)
// Reveal action + get attack // Reveal action + get attack
m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
if (((Creature*)unitTarget)->AI()) if (((Creature*)unitTarget)->AI())
((Creature*)unitTarget)->AI()->AttackStart(m_caster); ((Creature*)unitTarget)->AI()->AttackedBy(m_caster);
} }
} }
} }

View file

@ -419,10 +419,8 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
if (!spellProto || !(spellProto->Mechanic == MECHANIC_ROOT || IsAuraAddedBySpell(SPELL_AURA_MOD_ROOT, spellProto->Id))) if (!spellProto || !(spellProto->Mechanic == MECHANIC_ROOT || IsAuraAddedBySpell(SPELL_AURA_MOD_ROOT, spellProto->Id)))
pVictim->RemoveSpellbyDamageTaken(SPELL_AURA_MOD_ROOT, damage); pVictim->RemoveSpellbyDamageTaken(SPELL_AURA_MOD_ROOT, damage);
if(pVictim->GetTypeId() != TYPEID_PLAYER)
{
// no xp,health if type 8 /critters/ // no xp,health if type 8 /critters/
if ( pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER) if(pVictim->GetTypeId() != TYPEID_PLAYER && pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER)
{ {
pVictim->setDeathState(JUST_DIED); pVictim->setDeathState(JUST_DIED);
pVictim->SetHealth(0); pVictim->SetHealth(0);
@ -439,10 +437,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
return damage; return damage;
} }
if(!pVictim->isInCombat() && ((Creature*)pVictim)->AI())
((Creature*)pVictim)->AI()->AttackStart(this);
}
DEBUG_LOG("DealDamageStart"); DEBUG_LOG("DealDamageStart");
uint32 health = pVictim->GetHealth(); uint32 health = pVictim->GetHealth();
@ -689,18 +683,16 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
if(damagetype != DOT) if(damagetype != DOT)
{ {
if(getVictim()) 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 not have main target then attack state with target (including AI call) // if not have main target then attack state with target (including AI call)
//start melee attacks only after melee hit //start melee attacks only after melee hit
Attack(pVictim,(damagetype == DIRECT_DAMAGE)); 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 // 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; return;
} }
@ -1989,6 +1985,10 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex
--m_extraAttacks; --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 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 = victim;
m_attacking->_addAttacker(this); m_attacking->_addAttacker(this);
if(m_attacking->GetTypeId()==TYPEID_UNIT && ((Creature*)m_attacking)->AI())
((Creature*)m_attacking)->AI()->AttackedBy(this);
if(GetTypeId()==TYPEID_UNIT) if(GetTypeId()==TYPEID_UNIT)
{ {
WorldPacket data(SMSG_AI_REACTION, 12); WorldPacket data(SMSG_AI_REACTION, 12);
@ -10738,8 +10735,8 @@ void Unit::SetFeared(bool apply, uint64 casterGUID, uint32 spellID)
// attack caster if can // attack caster if can
Unit* caster = ObjectAccessor::GetObjectInWorld(casterGUID, (Unit*)NULL); Unit* caster = ObjectAccessor::GetObjectInWorld(casterGUID, (Unit*)NULL);
if(caster && caster != getVictim() && ((Creature*)this)->AI()) if(caster && ((Creature*)this)->AI())
((Creature*)this)->AI()->AttackStart(caster); ((Creature*)this)->AI()->AttackedBy(caster);
} }
} }

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "7667" #define REVISION_NR "7668"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__