mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 07:37:01 +00:00
[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:
parent
69fb9736cc
commit
d85e95295d
11 changed files with 72 additions and 82 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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; }
|
||||||
|
|
|
||||||
|
|
@ -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(); }
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)))
|
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/
|
||||||
|
if(pVictim->GetTypeId() != TYPEID_PLAYER && pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER)
|
||||||
{
|
{
|
||||||
// no xp,health if type 8 /critters/
|
pVictim->setDeathState(JUST_DIED);
|
||||||
if ( pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER)
|
pVictim->SetHealth(0);
|
||||||
{
|
|
||||||
pVictim->setDeathState(JUST_DIED);
|
|
||||||
pVictim->SetHealth(0);
|
|
||||||
|
|
||||||
// allow loot only if has loot_id in creature_template
|
// allow loot only if has loot_id in creature_template
|
||||||
CreatureInfo const* cInfo = ((Creature*)pVictim)->GetCreatureInfo();
|
CreatureInfo const* cInfo = ((Creature*)pVictim)->GetCreatureInfo();
|
||||||
if(cInfo && cInfo->lootid)
|
if(cInfo && cInfo->lootid)
|
||||||
pVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
pVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
||||||
|
|
||||||
// some critters required for quests
|
// some critters required for quests
|
||||||
if(GetTypeId() == TYPEID_PLAYER)
|
if(GetTypeId() == TYPEID_PLAYER)
|
||||||
((Player*)this)->KilledMonster(pVictim->GetEntry(),pVictim->GetGUID());
|
((Player*)this)->KilledMonster(pVictim->GetEntry(),pVictim->GetGUID());
|
||||||
|
|
||||||
return damage;
|
return damage;
|
||||||
}
|
|
||||||
|
|
||||||
if(!pVictim->isInCombat() && ((Creature*)pVictim)->AI())
|
|
||||||
((Creature*)pVictim)->AI()->AttackStart(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_LOG("DealDamageStart");
|
DEBUG_LOG("DealDamageStart");
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue