*Fix critter AI.

*Some AI structure change.

--HG--
branch : trunk
This commit is contained in:
megamage
2009-01-28 20:16:11 -06:00
parent 3a229014dc
commit 30c5bff102
21 changed files with 97 additions and 53 deletions
@@ -149,7 +149,6 @@ struct TRINITY_DLL_DECL npc_dashel_stonefistAI : public ScriptedAI
//m_creature->CombatStop(); //m_creature->CombatStop();
EnterEvadeMode(); EnterEvadeMode();
} }
AttackedBy(done_by);
} }
void Aggro(Unit *who) {} void Aggro(Unit *who) {}
+1 -1
View File
@@ -38,7 +38,7 @@ AggressorAI::Permissible(const Creature *creature)
return PERMIT_BASE_NO; return PERMIT_BASE_NO;
} }
AggressorAI::AggressorAI(Creature &c) : i_creature(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) AggressorAI::AggressorAI(Creature *c) : i_creature(*c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK)
{ {
} }
+1 -1
View File
@@ -36,7 +36,7 @@ class TRINITY_DLL_DECL AggressorAI : public CreatureAI
public: public:
AggressorAI(Creature &c); AggressorAI(Creature *c);
void MoveInLineOfSight(Unit *); void MoveInLineOfSight(Unit *);
void AttackStart(Unit *); void AttackStart(Unit *);
+18 -8
View File
@@ -27,37 +27,47 @@ CreatureAI::~CreatureAI()
{ {
} }
SimpleCharmedAI::SimpleCharmedAI(Unit &u) : me(u) void CreatureAI::EnterEvadeMode()
{ {
if(!me) return;
me->RemoveAllAuras();
me->DeleteThreatList();
me->CombatStop();
me->LoadCreaturesAddon();
me->SetLootRecipient(NULL);
if(me->isAlive())
me->GetMotionMaster()->MoveTargetedHome();
} }
void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/) void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/)
{ {
Creature *charmer = (Creature*)me.GetCharmer(); Creature *charmer = (Creature*)me->GetCharmer();
//kill self if charm aura has infinite duration //kill self if charm aura has infinite duration
if(charmer->IsInEvadeMode()) if(charmer->IsInEvadeMode())
{ {
Unit::AuraList const& auras = me.GetAurasByType(SPELL_AURA_MOD_CHARM); Unit::AuraList const& auras = me->GetAurasByType(SPELL_AURA_MOD_CHARM);
for(Unit::AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter) for(Unit::AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
if((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->IsPermanent()) if((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->IsPermanent())
{ {
charmer->Kill(&me); charmer->Kill(me);
return; return;
} }
} }
if(!charmer->isInCombat()) if(!charmer->isInCombat())
me.GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
Unit *target = me.getVictim(); Unit *target = me->getVictim();
if(!target || !charmer->canAttack(target)) if(!target || !charmer->canAttack(target))
{ {
target = charmer->SelectNearestTarget(); target = charmer->SelectNearestTarget();
if(!target) if(!target)
return; return;
me.GetMotionMaster()->MoveChase(target); me->GetMotionMaster()->MoveChase(target);
me.Attack(target, true); me->Attack(target, true);
} }
} }
+10 -9
View File
@@ -72,21 +72,25 @@ enum SelectAggroTarget
class TRINITY_DLL_SPEC UnitAI class TRINITY_DLL_SPEC UnitAI
{ {
public: public:
UnitAI(Unit *u) : me(u) {}
virtual void UpdateAI(const uint32 diff) = 0; virtual void UpdateAI(const uint32 diff) = 0;
protected:
Unit *me;
}; };
class TRINITY_DLL_SPEC SimpleCharmedAI class TRINITY_DLL_SPEC SimpleCharmedAI : public UnitAI
{ {
public: public:
SimpleCharmedAI(Unit &u);
virtual void UpdateAI(const uint32 diff); virtual void UpdateAI(const uint32 diff);
private:
Unit &me;
}; };
class TRINITY_DLL_SPEC CreatureAI : public UnitAI class TRINITY_DLL_SPEC CreatureAI : public UnitAI
{ {
protected:
Creature *me;
public: public:
CreatureAI() : UnitAI(NULL), me(NULL) {}
CreatureAI(Creature *c) : UnitAI((Unit*)c), me(c) {}
virtual ~CreatureAI(); virtual ~CreatureAI();
@@ -97,10 +101,10 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI
virtual void AttackStart(Unit *) = 0; virtual void AttackStart(Unit *) = 0;
// Called at stopping attack by any attacker // Called at stopping attack by any attacker
virtual void EnterEvadeMode() = 0; virtual void EnterEvadeMode();
// 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); } virtual void DamageTaken(Unit *done_by, uint32 & /*damage*/) {}
// Is unit visible for MoveInLineOfSight // Is unit visible for MoveInLineOfSight
virtual bool IsVisible(Unit *) const = 0; virtual bool IsVisible(Unit *) const = 0;
@@ -128,9 +132,6 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI
// Called when vitim entered water and creature can not enter water // Called when vitim entered water and creature can not enter water
virtual bool canReachByRangeAttack(Unit*) { return false; } virtual bool canReachByRangeAttack(Unit*) { return false; }
// 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() {}
+1 -1
View File
@@ -27,6 +27,6 @@ inline CreatureAI*
CreatureAIFactory<REAL_AI>::Create(void *data) const CreatureAIFactory<REAL_AI>::Create(void *data) const
{ {
Creature* creature = reinterpret_cast<Creature *>(data); Creature* creature = reinterpret_cast<Creature *>(data);
return (new REAL_AI(*creature)); return (new REAL_AI(creature));
} }
#endif #endif
+2
View File
@@ -41,6 +41,8 @@ namespace AIRegistry
(new CreatureAIFactory<NullCreatureAI>("NullCreatureAI"))->RegisterSelf(); (new CreatureAIFactory<NullCreatureAI>("NullCreatureAI"))->RegisterSelf();
(new CreatureAIFactory<AggressorAI>("AggressorAI"))->RegisterSelf(); (new CreatureAIFactory<AggressorAI>("AggressorAI"))->RegisterSelf();
(new CreatureAIFactory<ReactorAI>("ReactorAI"))->RegisterSelf(); (new CreatureAIFactory<ReactorAI>("ReactorAI"))->RegisterSelf();
(new CreatureAIFactory<PassiveAI>("PassiveAI"))->RegisterSelf();
(new CreatureAIFactory<CritterAI>("CritterAI"))->RegisterSelf();
(new CreatureAIFactory<GuardAI>("GuardAI"))->RegisterSelf(); (new CreatureAIFactory<GuardAI>("GuardAI"))->RegisterSelf();
(new CreatureAIFactory<PetAI>("PetAI"))->RegisterSelf(); (new CreatureAIFactory<PetAI>("PetAI"))->RegisterSelf();
(new CreatureAIFactory<TotemAI>("TotemAI"))->RegisterSelf(); (new CreatureAIFactory<TotemAI>("TotemAI"))->RegisterSelf();
+3 -1
View File
@@ -65,6 +65,8 @@ namespace FactorySelector
ai_factory = ai_registry.GetRegistryItem("TotemAI"); ai_factory = ai_registry.GetRegistryItem("TotemAI");
else if(creature->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER) else if(creature->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
ai_factory = ai_registry.GetRegistryItem("NullCreatureAI"); ai_factory = ai_registry.GetRegistryItem("NullCreatureAI");
else if(creature->GetCreatureType() == CREATURE_TYPE_CRITTER)
ai_factory = ai_registry.GetRegistryItem("CritterAI");
} }
// select by permit check // select by permit check
@@ -91,7 +93,7 @@ namespace FactorySelector
ainame = (ai_factory == NULL) ? "NullCreatureAI" : ai_factory->key(); ainame = (ai_factory == NULL) ? "NullCreatureAI" : ai_factory->key();
DEBUG_LOG("Creature %u used AI is %s.", creature->GetGUIDLow(), ainame.c_str() ); DEBUG_LOG("Creature %u used AI is %s.", creature->GetGUIDLow(), ainame.c_str() );
return ( ai_factory == NULL ? new NullCreatureAI : ai_factory->Create(creature) ); return ( ai_factory == NULL ? new NullCreatureAI(creature) : ai_factory->Create(creature) );
} }
MovementGenerator* selectMovementGenerator(Creature *creature) MovementGenerator* selectMovementGenerator(Creature *creature)
+1 -1
View File
@@ -33,7 +33,7 @@ int GuardAI::Permissible(const Creature *creature)
return PERMIT_BASE_NO; return PERMIT_BASE_NO;
} }
GuardAI::GuardAI(Creature &c) : i_creature(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) GuardAI::GuardAI(Creature *c) : i_creature(*c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK)
{ {
} }
+1 -1
View File
@@ -36,7 +36,7 @@ class TRINITY_DLL_DECL GuardAI : public CreatureAI
public: public:
GuardAI(Creature &c); GuardAI(Creature *c);
void MoveInLineOfSight(Unit *); void MoveInLineOfSight(Unit *);
void AttackStart(Unit *); void AttackStart(Unit *);
+14
View File
@@ -19,7 +19,21 @@
*/ */
#include "NullCreatureAI.h" #include "NullCreatureAI.h"
#include "Creature.h"
NullCreatureAI::~NullCreatureAI() NullCreatureAI::~NullCreatureAI()
{ {
} }
void CritterAI::DamageTaken(Unit *done_by, uint32 &)
{
if(!me->hasUnitState(UNIT_STAT_FLEEING))
me->SetControlled(true, UNIT_STAT_FLEEING);
}
void CritterAI::EnterEvadeMode()
{
if(me->hasUnitState(UNIT_STAT_FLEEING))
me->SetControlled(false, UNIT_STAT_FLEEING);
CreatureAI::EnterEvadeMode();
}
+23 -7
View File
@@ -23,22 +23,38 @@
#include "CreatureAI.h" #include "CreatureAI.h"
class TRINITY_DLL_DECL NullCreatureAI : public CreatureAI class TRINITY_DLL_DECL PassiveAI : public CreatureAI
{ {
public: public:
PassiveAI(Creature *c) : CreatureAI(c) {}
NullCreatureAI(Creature &) {} ~PassiveAI() {}
NullCreatureAI() {}
~NullCreatureAI();
void MoveInLineOfSight(Unit *) {} void MoveInLineOfSight(Unit *) {}
void AttackStart(Unit *) {} void AttackStart(Unit *) {}
void EnterEvadeMode() {}
bool IsVisible(Unit *) const { return false; } bool IsVisible(Unit *) const { return false; }
void UpdateAI(const uint32) {} void UpdateAI(const uint32) {}
static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; } static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; }
}; };
class TRINITY_DLL_DECL NullCreatureAI : public PassiveAI
{
public:
NullCreatureAI(Creature *c) : PassiveAI(c) {}
~NullCreatureAI();
void EnterEvadeMode() {}
};
class TRINITY_DLL_DECL CritterAI : public PassiveAI
{
public:
CritterAI(Creature *c) : PassiveAI(c) {}
~CritterAI();
void DamageTaken(Unit *done_by, uint32 & /*damage*/);
void EnterEvadeMode();
};
#endif #endif
+1 -1
View File
@@ -25,7 +25,7 @@
#define MAX_OUTDOOR_PVP_DISTANCE 200 // the max value in capture point type go data0 is 100 currently, so use twice that much to handle leaving as well #define MAX_OUTDOOR_PVP_DISTANCE 200 // the max value in capture point type go data0 is 100 currently, so use twice that much to handle leaving as well
OutdoorPvPObjectiveAI::OutdoorPvPObjectiveAI(Creature &c) : i_creature(c) OutdoorPvPObjectiveAI::OutdoorPvPObjectiveAI(Creature *c) : i_creature(*c)
{ {
sLog.outDebug("OutdoorPvP objective AI assigned to creature guid %u", c.GetGUIDLow()); sLog.outDebug("OutdoorPvP objective AI assigned to creature guid %u", c.GetGUIDLow());
c.SetReactState(REACT_AGGRESSIVE); c.SetReactState(REACT_AGGRESSIVE);
+1 -1
View File
@@ -27,7 +27,7 @@ class TRINITY_DLL_DECL OutdoorPvPObjectiveAI : public CreatureAI
{ {
public: public:
OutdoorPvPObjectiveAI(Creature &c); OutdoorPvPObjectiveAI(Creature *c);
void MoveInLineOfSight(Unit *); void MoveInLineOfSight(Unit *);
bool IsVisible(Unit *) const; bool IsVisible(Unit *) const;
+3 -3
View File
@@ -38,7 +38,7 @@ int PetAI::Permissible(const Creature *creature)
return PERMIT_BASE_NO; return PERMIT_BASE_NO;
} }
PetAI::PetAI(Creature &c) : i_pet(c), i_tracker(TIME_INTERVAL_LOOK), inCombat(false) PetAI::PetAI(Creature *c) : i_pet(*c), i_tracker(TIME_INTERVAL_LOOK), inCombat(false)
{ {
m_AllySet.clear(); m_AllySet.clear();
UpdateAllies(); UpdateAllies();
@@ -339,10 +339,10 @@ void PetAI::UpdateAllies()
m_AllySet.insert(owner->GetGUID()); m_AllySet.insert(owner->GetGUID());
} }
void PetAI::AttackedBy(Unit *attacker) /*void PetAI::AttackedBy(Unit *attacker)
{ {
//when attacked, fight back in case 1)no victim already AND 2)not set to passive AND 3)not set to stay, unless can it can reach attacker with melee attack anyway //when attacked, fight back in case 1)no victim already AND 2)not set to passive AND 3)not set to stay, unless can it can reach attacker with melee attack anyway
if(!i_pet.getVictim() && i_pet.GetCharmInfo() && !i_pet.GetCharmInfo()->HasReactState(REACT_PASSIVE) && if(!i_pet.getVictim() && i_pet.GetCharmInfo() && !i_pet.GetCharmInfo()->HasReactState(REACT_PASSIVE) &&
(!i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY) || i_pet.IsWithinMeleeRange(attacker))) (!i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY) || i_pet.IsWithinMeleeRange(attacker)))
AttackStart(attacker); AttackStart(attacker);
} }*/
+1 -3
View File
@@ -31,13 +31,11 @@ class TRINITY_DLL_DECL PetAI : public CreatureAI
{ {
public: public:
PetAI(Creature &c); PetAI(Creature *c);
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*);
bool IsVisible(Unit *) const; bool IsVisible(Unit *) const;
void JustDied(Unit* who) { _stopAttack(); } void JustDied(Unit* who) { _stopAttack(); }
+1 -2
View File
@@ -28,7 +28,7 @@ class Creature;
class TRINITY_DLL_DECL PossessedAI : public CreatureAI class TRINITY_DLL_DECL PossessedAI : public CreatureAI
{ {
public: public:
PossessedAI(Creature &c) : i_pet(c), i_victimGuid(0) {} PossessedAI(Creature *c) : i_pet(*c), i_victimGuid(0) {}
// Possessed creatures shouldn't aggro by themselves // Possessed creatures shouldn't aggro by themselves
void MoveInLineOfSight(Unit *) {} void MoveInLineOfSight(Unit *) {}
@@ -36,7 +36,6 @@ class TRINITY_DLL_DECL PossessedAI : public CreatureAI
void EnterEvadeMode() {} void EnterEvadeMode() {}
void JustDied(Unit*); void JustDied(Unit*);
void KilledUnit(Unit* victim); void KilledUnit(Unit* victim);
void AttackedBy(Unit*) {}
bool IsVisible(Unit * u) const { return _isVisible(u); } bool IsVisible(Unit * u) const { return _isVisible(u); }
void UpdateAI(const uint32); void UpdateAI(const uint32);
+1 -1
View File
@@ -29,7 +29,7 @@ class TRINITY_DLL_DECL ReactorAI : public CreatureAI
{ {
public: public:
ReactorAI(Creature &c) : i_creature(c), i_victimGuid(0) {} ReactorAI(Creature *c) : i_creature(*c), i_victimGuid(0) {}
void MoveInLineOfSight(Unit *); void MoveInLineOfSight(Unit *);
void AttackStart(Unit *); void AttackStart(Unit *);
+1 -1
View File
@@ -40,7 +40,7 @@ TotemAI::Permissible(const Creature *creature)
return PERMIT_BASE_NO; return PERMIT_BASE_NO;
} }
TotemAI::TotemAI(Creature &c) : i_totem(static_cast<Totem&>(c)), i_victimGuid(0) TotemAI::TotemAI(Creature *c) : i_totem(static_cast<Totem&>(*c)), i_victimGuid(0)
{ {
} }
+1 -1
View File
@@ -31,7 +31,7 @@ class TRINITY_DLL_DECL TotemAI : public CreatureAI
{ {
public: public:
TotemAI(Creature &c); TotemAI(Creature *c);
void MoveInLineOfSight(Unit *); void MoveInLineOfSight(Unit *);
void AttackStart(Unit *); void AttackStart(Unit *);
+12 -9
View File
@@ -650,9 +650,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
// no xp,health if type 8 /critters/ // no xp,health if type 8 /critters/
if ( pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER) if ( pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER)
{ {
// critters run away when hit
pVictim->GetMotionMaster()->MoveFleeing(this);
// allow loot only if has loot_id in creature_template // allow loot only if has loot_id in creature_template
if(damage >= pVictim->GetHealth()) if(damage >= pVictim->GetHealth())
{ {
@@ -750,13 +747,13 @@ 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 have target and damage pVictim just call AI reaction
if(pVictim != getVictim() && pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI()) if(pVictim != getVictim() && pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI())
((Creature*)pVictim)->AI()->AttackedBy(this); ((Creature*)pVictim)->AI()->AttackedBy(this);
} }
else 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
@@ -8195,8 +8192,8 @@ 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()) //if(m_attacking->GetTypeId()==TYPEID_UNIT && ((Creature*)m_attacking)->AI())
((Creature*)m_attacking)->AI()->AttackedBy(this); // ((Creature*)m_attacking)->AI()->AttackedBy(this);
if(GetTypeId()==TYPEID_UNIT) if(GetTypeId()==TYPEID_UNIT)
{ {
@@ -12904,7 +12901,13 @@ void Unit::SetFeared(bool apply)
Unit::AuraList const& fearAuras = GetAurasByType(SPELL_AURA_MOD_FEAR); Unit::AuraList const& fearAuras = GetAurasByType(SPELL_AURA_MOD_FEAR);
if(!fearAuras.empty()) if(!fearAuras.empty())
caster = ObjectAccessor::GetUnit(*this, fearAuras.front()->GetCasterGUID()); caster = ObjectAccessor::GetUnit(*this, fearAuras.front()->GetCasterGUID());
if(!caster) caster = getVictim(); if(!caster)
{
if(getVictim())
caster = getVictim();
else if(m_attackers.size())
caster = *m_attackers.begin();
}
GetMotionMaster()->MoveFleeing(caster); // caster==NULL processed in MoveFleeing GetMotionMaster()->MoveFleeing(caster); // caster==NULL processed in MoveFleeing
} }
else else