*Assign possessed AI and pet AI to charmed creatures.
--HG-- branch : trunk
This commit is contained in:
@@ -169,30 +169,6 @@ void ScriptedAI::DoStartNoMovement(Unit* victim)
|
|||||||
m_creature->StopMoving();
|
m_creature->StopMoving();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ScriptedAI::DoMeleeAttackIfReady()
|
|
||||||
{
|
|
||||||
//Make sure our attack is ready and we aren't currently casting before checking distance
|
|
||||||
if (m_creature->isAttackReady() && !m_creature->hasUnitState(UNIT_STAT_CASTING))
|
|
||||||
{
|
|
||||||
//If we are within range melee the target
|
|
||||||
if (m_creature->IsWithinMeleeRange(m_creature->getVictim()))
|
|
||||||
{
|
|
||||||
m_creature->AttackerStateUpdate(m_creature->getVictim());
|
|
||||||
m_creature->resetAttackTimer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (m_creature->haveOffhandWeapon() && m_creature->isAttackReady(OFF_ATTACK) && !m_creature->hasUnitState(UNIT_STAT_CASTING))
|
|
||||||
{
|
|
||||||
//If we are within range melee the target
|
|
||||||
if (m_creature->IsWithinMeleeRange(m_creature->getVictim()))
|
|
||||||
{
|
|
||||||
m_creature->AttackerStateUpdate(m_creature->getVictim(), OFF_ATTACK);
|
|
||||||
m_creature->resetAttackTimer(OFF_ATTACK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptedAI::DoStopAttack()
|
void ScriptedAI::DoStopAttack()
|
||||||
{
|
{
|
||||||
if (m_creature->getVictim() != NULL)
|
if (m_creature->getVictim() != NULL)
|
||||||
|
|||||||
@@ -113,9 +113,6 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI
|
|||||||
//Start no movement on victim
|
//Start no movement on victim
|
||||||
void DoStartNoMovement(Unit* victim);
|
void DoStartNoMovement(Unit* victim);
|
||||||
|
|
||||||
//Do melee swing of current victim if in rnage and ready and not casting
|
|
||||||
void DoMeleeAttackIfReady();
|
|
||||||
|
|
||||||
//Stop attack of current victim
|
//Stop attack of current victim
|
||||||
void DoStopAttack();
|
void DoStopAttack();
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,6 @@
|
|||||||
#include "CellImpl.h"
|
#include "CellImpl.h"
|
||||||
#include "OutdoorPvPMgr.h"
|
#include "OutdoorPvPMgr.h"
|
||||||
#include "GameEvent.h"
|
#include "GameEvent.h"
|
||||||
#include "PossessedAI.h"
|
|
||||||
#include "CreatureGroups.h"
|
#include "CreatureGroups.h"
|
||||||
// apply implementation of the singletons
|
// apply implementation of the singletons
|
||||||
#include "Policies/SingletonImp.h"
|
#include "Policies/SingletonImp.h"
|
||||||
@@ -141,7 +140,7 @@ bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Creature::Creature() :
|
Creature::Creature() :
|
||||||
Unit(), i_AI(NULL),
|
Unit(),
|
||||||
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0),
|
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0),
|
||||||
m_lootMoney(0), m_lootRecipient(0),
|
m_lootMoney(0), m_lootRecipient(0),
|
||||||
m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
|
m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
|
||||||
@@ -424,7 +423,7 @@ void Creature::Update(uint32 diff)
|
|||||||
setDeathState( JUST_ALIVED );
|
setDeathState( JUST_ALIVED );
|
||||||
|
|
||||||
//Call AI respawn virtual function
|
//Call AI respawn virtual function
|
||||||
i_AI->JustRespawned();
|
AI()->JustRespawned();
|
||||||
|
|
||||||
GetMap()->Add(this);
|
GetMap()->Add(this);
|
||||||
}
|
}
|
||||||
@@ -484,6 +483,9 @@ void Creature::Update(uint32 diff)
|
|||||||
if(!isAlive())
|
if(!isAlive())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// if creature is charmed, switch to charmed AI
|
||||||
|
UpdateCharmAI();
|
||||||
|
|
||||||
if(!IsInEvadeMode() && IsAIEnabled)
|
if(!IsInEvadeMode() && IsAIEnabled)
|
||||||
{
|
{
|
||||||
// do not allow the AI to be changed during update
|
// do not allow the AI to be changed during update
|
||||||
@@ -596,11 +598,9 @@ bool Creature::AIM_Initialize(CreatureAI* ai)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CreatureAI * oldAI = i_AI;
|
if(i_AI) delete i_AI;
|
||||||
i_motionMaster.Initialize();
|
|
||||||
i_AI = ai ? ai : FactorySelector::selectAI(this);
|
i_AI = ai ? ai : FactorySelector::selectAI(this);
|
||||||
if (oldAI)
|
i_motionMaster.Initialize();
|
||||||
delete oldAI;
|
|
||||||
IsAIEnabled = true;
|
IsAIEnabled = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -401,8 +401,6 @@ typedef std::map<uint32,time_t> CreatureSpellCooldowns;
|
|||||||
|
|
||||||
class TRINITY_DLL_SPEC Creature : public Unit
|
class TRINITY_DLL_SPEC Creature : public Unit
|
||||||
{
|
{
|
||||||
CreatureAI *i_AI;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit Creature();
|
explicit Creature();
|
||||||
@@ -468,7 +466,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
|
|||||||
bool AIM_Initialize(CreatureAI* ai = NULL);
|
bool AIM_Initialize(CreatureAI* ai = NULL);
|
||||||
|
|
||||||
void AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type);
|
void AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type);
|
||||||
CreatureAI* AI() { return i_AI; }
|
CreatureAI* AI() { return (CreatureAI*)i_AI; }
|
||||||
|
|
||||||
uint32 GetShieldBlockValue() const //dunno mob block value
|
uint32 GetShieldBlockValue() const //dunno mob block value
|
||||||
{
|
{
|
||||||
|
|||||||
+24
-1
@@ -36,11 +36,34 @@ void UnitAI::AttackStart(Unit *victim)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnitAI::DoMeleeAttackIfReady()
|
||||||
|
{
|
||||||
|
//Make sure our attack is ready and we aren't currently casting before checking distance
|
||||||
|
if (me->isAttackReady() && !me->hasUnitState(UNIT_STAT_CASTING))
|
||||||
|
{
|
||||||
|
//If we are within range melee the target
|
||||||
|
if (me->IsWithinMeleeRange(me->getVictim()))
|
||||||
|
{
|
||||||
|
me->AttackerStateUpdate(me->getVictim());
|
||||||
|
me->resetAttackTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK) && !me->hasUnitState(UNIT_STAT_CASTING))
|
||||||
|
{
|
||||||
|
//If we are within range melee the target
|
||||||
|
if (me->IsWithinMeleeRange(me->getVictim()))
|
||||||
|
{
|
||||||
|
me->AttackerStateUpdate(me->getVictim(), OFF_ATTACK);
|
||||||
|
me->resetAttackTimer(OFF_ATTACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Enable PlayerAI when charmed
|
//Enable PlayerAI when charmed
|
||||||
void PlayerAI::OnCharmed(bool apply) { me->IsAIEnabled = apply; }
|
void PlayerAI::OnCharmed(bool apply) { me->IsAIEnabled = apply; }
|
||||||
|
|
||||||
//Disable CreatureAI when charmed
|
//Disable CreatureAI when charmed
|
||||||
void CreatureAI::OnCharmed(bool apply) { me->IsAIEnabled = !apply; }
|
void CreatureAI::OnCharmed(bool apply) { /*me->IsAIEnabled = !apply;*/ }
|
||||||
|
|
||||||
void CreatureAI::MoveInLineOfSight(Unit *who)
|
void CreatureAI::MoveInLineOfSight(Unit *who)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -81,6 +81,9 @@ class TRINITY_DLL_SPEC UnitAI
|
|||||||
|
|
||||||
// Called when unit is charmed
|
// Called when unit is charmed
|
||||||
virtual void OnCharmed(bool apply) = 0;
|
virtual void OnCharmed(bool apply) = 0;
|
||||||
|
|
||||||
|
//Do melee swing of current victim if in rnage and ready and not casting
|
||||||
|
void DoMeleeAttackIfReady();
|
||||||
};
|
};
|
||||||
|
|
||||||
class TRINITY_DLL_SPEC PlayerAI : public UnitAI
|
class TRINITY_DLL_SPEC PlayerAI : public UnitAI
|
||||||
|
|||||||
@@ -27,6 +27,30 @@ void PassiveAI::UpdateAI(const uint32)
|
|||||||
EnterEvadeMode();
|
EnterEvadeMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PossessedAI::UpdateAI(const uint32 diff)
|
||||||
|
{
|
||||||
|
if(me->getVictim())
|
||||||
|
{
|
||||||
|
if(!me->canAttack(me->getVictim()))
|
||||||
|
me->AttackStop();
|
||||||
|
else
|
||||||
|
DoMeleeAttackIfReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PossessedAI::JustDied(Unit *u)
|
||||||
|
{
|
||||||
|
// We died while possessed, disable our loot
|
||||||
|
me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PossessedAI::KilledUnit(Unit* victim)
|
||||||
|
{
|
||||||
|
// We killed a creature, disable victim's loot
|
||||||
|
if (victim->GetTypeId() == TYPEID_UNIT)
|
||||||
|
victim->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
||||||
|
}
|
||||||
|
|
||||||
void CritterAI::DamageTaken(Unit *done_by, uint32 &)
|
void CritterAI::DamageTaken(Unit *done_by, uint32 &)
|
||||||
{
|
{
|
||||||
if(!me->hasUnitState(UNIT_STAT_FLEEING))
|
if(!me->hasUnitState(UNIT_STAT_FLEEING))
|
||||||
@@ -39,4 +63,3 @@ void CritterAI::EnterEvadeMode()
|
|||||||
me->SetControlled(false, UNIT_STAT_FLEEING);
|
me->SetControlled(false, UNIT_STAT_FLEEING);
|
||||||
CreatureAI::EnterEvadeMode();
|
CreatureAI::EnterEvadeMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,18 @@ class TRINITY_DLL_DECL PassiveAI : public CreatureAI
|
|||||||
static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; }
|
static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TRINITY_DLL_DECL PossessedAI : public PassiveAI
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PossessedAI(Creature *c) : PassiveAI(c) {}
|
||||||
|
|
||||||
|
void UpdateAI(const uint32);
|
||||||
|
void EnterEvadeMode() {}
|
||||||
|
|
||||||
|
void JustDied(Unit*);
|
||||||
|
void KilledUnit(Unit* victim);
|
||||||
|
};
|
||||||
|
|
||||||
class TRINITY_DLL_DECL NullCreatureAI : public PassiveAI
|
class TRINITY_DLL_DECL NullCreatureAI : public PassiveAI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
+8
-85
@@ -44,44 +44,6 @@ PetAI::PetAI(Creature *c) : CreatureAI(c), i_pet(*c), i_tracker(TIME_INTERVAL_LO
|
|||||||
UpdateAllies();
|
UpdateAllies();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PetAI::MoveInLineOfSight(Unit *u)
|
|
||||||
{
|
|
||||||
if( !i_pet.getVictim() && i_pet.GetCharmInfo() &&
|
|
||||||
i_pet.IsHostileTo( u ) && i_pet.canAttack(u) &&
|
|
||||||
u->isInAccessiblePlaceFor(&i_pet))
|
|
||||||
{
|
|
||||||
float attackRadius = i_pet.GetAttackDistance(u);
|
|
||||||
if(i_pet.IsWithinDistInMap(u, attackRadius) && i_pet.GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE)
|
|
||||||
{
|
|
||||||
if(i_pet.IsWithinLOSInMap(u))
|
|
||||||
{
|
|
||||||
AttackStart(u);
|
|
||||||
//u->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PetAI::AttackStart(Unit *u)
|
|
||||||
{
|
|
||||||
if( !u || (i_pet.isPet() && ((Pet&)i_pet).getPetType() == MINI_PET) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (inCombat && i_pet.getVictim() && u != i_pet.getVictim())
|
|
||||||
i_pet.AttackStop();
|
|
||||||
|
|
||||||
if(i_pet.Attack(u,true))
|
|
||||||
{
|
|
||||||
i_pet.clearUnitState(UNIT_STAT_FOLLOW);
|
|
||||||
// TMGs call CreatureRelocation which via MoveInLineOfSight can call this function
|
|
||||||
// thus with the following clear the original TMG gets invalidated and crash, doh
|
|
||||||
// hope it doesn't start to leak memory without this :-/
|
|
||||||
//i_pet->Clear();
|
|
||||||
i_pet.GetMotionMaster()->MoveChase(u);
|
|
||||||
inCombat = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PetAI::EnterEvadeMode()
|
void PetAI::EnterEvadeMode()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -138,11 +100,8 @@ void PetAI::UpdateAI(const uint32 diff)
|
|||||||
else
|
else
|
||||||
m_updateAlliesTimer -= diff;
|
m_updateAlliesTimer -= diff;
|
||||||
|
|
||||||
if (inCombat && i_pet.getVictim() == NULL)
|
|
||||||
_stopAttack();
|
|
||||||
|
|
||||||
// i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
|
// i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
|
||||||
if( i_pet.getVictim() != NULL )
|
if( i_pet.getVictim() )
|
||||||
{
|
{
|
||||||
if( _needToStop() )
|
if( _needToStop() )
|
||||||
{
|
{
|
||||||
@@ -150,50 +109,23 @@ void PetAI::UpdateAI(const uint32 diff)
|
|||||||
_stopAttack();
|
_stopAttack();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if( i_pet.IsStopped() || i_pet.IsWithinMeleeRange(i_pet.getVictim()))
|
|
||||||
{
|
DoMeleeAttackIfReady();
|
||||||
// required to be stopped cases
|
}
|
||||||
if ( i_pet.IsStopped() && i_pet.IsNonMeleeSpellCasted(false) )
|
|
||||||
{
|
|
||||||
if( i_pet.hasUnitState(UNIT_STAT_FOLLOW) )
|
|
||||||
i_pet.InterruptNonMeleeSpells(false);
|
|
||||||
else
|
else
|
||||||
return;
|
|
||||||
}
|
|
||||||
// not required to be stopped case
|
|
||||||
else if( i_pet.isAttackReady() && i_pet.IsWithinMeleeRange(i_pet.getVictim()) )
|
|
||||||
{
|
{
|
||||||
i_pet.AttackerStateUpdate(i_pet.getVictim());
|
if(me->isInCombat())
|
||||||
|
|
||||||
i_pet.resetAttackTimer();
|
|
||||||
|
|
||||||
if ( !i_pet.getVictim() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
//if pet misses its target, it will also be the first in threat list
|
|
||||||
i_pet.getVictim()->AddThreat(&i_pet,0.0f);
|
|
||||||
|
|
||||||
if( _needToStop() )
|
|
||||||
_stopAttack();
|
_stopAttack();
|
||||||
}
|
else if(owner && i_pet.GetCharmInfo()) //no victim
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(owner && i_pet.GetCharmInfo())
|
|
||||||
{
|
{
|
||||||
if(owner->isInCombat() && !(i_pet.HasReactState(REACT_PASSIVE) || i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY)))
|
if(owner->isInCombat() && !(i_pet.HasReactState(REACT_PASSIVE) || i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY)))
|
||||||
{
|
|
||||||
AttackStart(owner->getAttackerForHelper());
|
AttackStart(owner->getAttackerForHelper());
|
||||||
}
|
else if(i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW) && !i_pet.hasUnitState(UNIT_STAT_FOLLOW))
|
||||||
else if(i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
|
|
||||||
{
|
|
||||||
if (!i_pet.hasUnitState(UNIT_STAT_FOLLOW) )
|
|
||||||
{
|
|
||||||
i_pet.GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
|
i_pet.GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (i_pet.GetGlobalCooldown() == 0 && !i_pet.IsNonMeleeSpellCasted(false))
|
if (i_pet.GetGlobalCooldown() == 0 && !i_pet.hasUnitState(UNIT_STAT_CASTING))
|
||||||
{
|
{
|
||||||
//Autocast
|
//Autocast
|
||||||
for (uint8 i = 0; i < i_pet.GetPetAutoSpellSize(); i++)
|
for (uint8 i = 0; i < i_pet.GetPetAutoSpellSize(); i++)
|
||||||
@@ -323,12 +255,3 @@ void PetAI::UpdateAllies()
|
|||||||
else //remove group
|
else //remove group
|
||||||
m_AllySet.insert(owner->GetGUID());
|
m_AllySet.insert(owner->GetGUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*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
|
|
||||||
if(!i_pet.getVictim() && i_pet.GetCharmInfo() && !i_pet.GetCharmInfo()->HasReactState(REACT_PASSIVE) &&
|
|
||||||
(!i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY) || i_pet.IsWithinMeleeRange(attacker)))
|
|
||||||
AttackStart(attacker);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ class TRINITY_DLL_DECL PetAI : public CreatureAI
|
|||||||
|
|
||||||
PetAI(Creature *c);
|
PetAI(Creature *c);
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit *);
|
|
||||||
void AttackStart(Unit *);
|
|
||||||
void EnterEvadeMode();
|
void EnterEvadeMode();
|
||||||
void JustDied(Unit* who) { _stopAttack(); }
|
void JustDied(Unit* who) { _stopAttack(); }
|
||||||
|
|
||||||
|
|||||||
@@ -85,13 +85,15 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
|
|||||||
switch(spellid)
|
switch(spellid)
|
||||||
{
|
{
|
||||||
case COMMAND_STAY: //flat=1792 //STAY
|
case COMMAND_STAY: //flat=1792 //STAY
|
||||||
|
pet->AttackStop();
|
||||||
|
pet->InterruptNonMeleeSpells(false);
|
||||||
pet->StopMoving();
|
pet->StopMoving();
|
||||||
pet->GetMotionMaster()->Clear();
|
|
||||||
pet->GetMotionMaster()->MoveIdle();
|
pet->GetMotionMaster()->MoveIdle();
|
||||||
charmInfo->SetCommandState( COMMAND_STAY );
|
charmInfo->SetCommandState( COMMAND_STAY );
|
||||||
break;
|
break;
|
||||||
case COMMAND_FOLLOW: //spellid=1792 //FOLLOW
|
case COMMAND_FOLLOW: //spellid=1792 //FOLLOW
|
||||||
pet->AttackStop();
|
pet->AttackStop();
|
||||||
|
pet->InterruptNonMeleeSpells(false);
|
||||||
pet->GetMotionMaster()->MoveFollow(_player,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
|
pet->GetMotionMaster()->MoveFollow(_player,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
|
||||||
charmInfo->SetCommandState( COMMAND_FOLLOW );
|
charmInfo->SetCommandState( COMMAND_FOLLOW );
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -18,105 +18,3 @@
|
|||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "PossessedAI.h"
|
|
||||||
#include "Creature.h"
|
|
||||||
#include "World.h"
|
|
||||||
|
|
||||||
void PossessedAI::AttackStart(Unit *u)
|
|
||||||
{
|
|
||||||
if( !u || i_pet.GetCharmer()->HasAuraType(SPELL_AURA_MOD_PACIFY))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (i_pet.getVictim() && u != i_pet.getVictim())
|
|
||||||
i_pet.AttackStop();
|
|
||||||
|
|
||||||
if(i_pet.Attack(u, true))
|
|
||||||
i_victimGuid = u->GetGUID();
|
|
||||||
|
|
||||||
// Do not autochase our target, and also make sure our current movement generator
|
|
||||||
// is removed since the motion master is reset before this function is called
|
|
||||||
i_pet.GetMotionMaster()->Clear(false);
|
|
||||||
i_pet.GetMotionMaster()->MoveIdle();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PossessedAI::_needToStop() const
|
|
||||||
{
|
|
||||||
if(!i_pet.getVictim() || !i_pet.isAlive())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// This is needed for charmed creatures, as once their target was reset other effects can trigger threat
|
|
||||||
if(i_pet.getVictim() == i_pet.GetCharmer())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return !i_pet.canAttack(i_pet.getVictim());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PossessedAI::_stopAttack()
|
|
||||||
{
|
|
||||||
if( !i_victimGuid )
|
|
||||||
return;
|
|
||||||
|
|
||||||
Unit* victim = Unit::GetUnit(i_pet, i_victimGuid );
|
|
||||||
|
|
||||||
if ( !victim )
|
|
||||||
return;
|
|
||||||
|
|
||||||
assert(!i_pet.getVictim() || i_pet.getVictim() == victim);
|
|
||||||
|
|
||||||
if( !i_pet.isAlive() )
|
|
||||||
{
|
|
||||||
i_pet.StopMoving();
|
|
||||||
i_pet.GetMotionMaster()->Clear(false);
|
|
||||||
i_pet.GetMotionMaster()->MoveIdle();
|
|
||||||
i_victimGuid = 0;
|
|
||||||
i_pet.CombatStop();
|
|
||||||
i_pet.getHostilRefManager().deleteReferences();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
i_pet.GetMotionMaster()->Clear(false);
|
|
||||||
i_pet.GetMotionMaster()->MoveIdle();
|
|
||||||
i_victimGuid = 0;
|
|
||||||
i_pet.AttackStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PossessedAI::UpdateAI(const uint32 diff)
|
|
||||||
{
|
|
||||||
// update i_victimGuid if i_pet.getVictim() !=0 and changed
|
|
||||||
if(i_pet.getVictim())
|
|
||||||
i_victimGuid = i_pet.getVictim()->GetGUID();
|
|
||||||
|
|
||||||
// i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
|
|
||||||
if( i_victimGuid )
|
|
||||||
{
|
|
||||||
if( _needToStop() )
|
|
||||||
{
|
|
||||||
_stopAttack(); // i_victimGuid == 0 && i_pet.getVictim() == NULL now
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if(i_pet.IsWithinMeleeRange(i_pet.getVictim()) && i_pet.isAttackReady() && !i_pet.GetCharmer()->HasAuraType(SPELL_AURA_MOD_PACIFY))
|
|
||||||
{
|
|
||||||
i_pet.AttackerStateUpdate(i_pet.getVictim());
|
|
||||||
|
|
||||||
i_pet.resetAttackTimer();
|
|
||||||
|
|
||||||
if( _needToStop() )
|
|
||||||
_stopAttack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PossessedAI::JustDied(Unit *u)
|
|
||||||
{
|
|
||||||
// We died while possessed, disable our loot
|
|
||||||
i_pet.RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PossessedAI::KilledUnit(Unit* victim)
|
|
||||||
{
|
|
||||||
// We killed a creature, disable victim's loot
|
|
||||||
if (victim->GetTypeId() == TYPEID_UNIT)
|
|
||||||
victim->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,33 +21,5 @@
|
|||||||
#ifndef MANGOS_POSSESSEDAI_H
|
#ifndef MANGOS_POSSESSEDAI_H
|
||||||
#define MANGOS_POSSESSEDAI_H
|
#define MANGOS_POSSESSEDAI_H
|
||||||
|
|
||||||
#include "CreatureAI.h"
|
|
||||||
|
|
||||||
class Creature;
|
|
||||||
|
|
||||||
class TRINITY_DLL_DECL PossessedAI : public CreatureAI
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PossessedAI(Creature *c) : CreatureAI(c), i_pet(*c), i_victimGuid(0) {}
|
|
||||||
|
|
||||||
// Possessed creatures shouldn't aggro by themselves
|
|
||||||
void MoveInLineOfSight(Unit *) {}
|
|
||||||
void AttackStart(Unit *);
|
|
||||||
void EnterEvadeMode() {}
|
|
||||||
void JustDied(Unit*);
|
|
||||||
void KilledUnit(Unit* victim);
|
|
||||||
|
|
||||||
void UpdateAI(const uint32);
|
|
||||||
// Never permit this to be used, it must always be initialized with Creature::InitPossessedAI()
|
|
||||||
static int Permissible(const Creature *) { return PERMIT_BASE_NO; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool _isVisible(Unit *) const;
|
|
||||||
bool _needToStop(void) const;
|
|
||||||
void _stopAttack(void);
|
|
||||||
|
|
||||||
Creature &i_pet;
|
|
||||||
uint64 i_victimGuid;
|
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,8 @@
|
|||||||
#include "CellImpl.h"
|
#include "CellImpl.h"
|
||||||
#include "Path.h"
|
#include "Path.h"
|
||||||
#include "CreatureGroups.h"
|
#include "CreatureGroups.h"
|
||||||
|
#include "PetAI.h"
|
||||||
|
#include "NullCreatureAI.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
@@ -150,6 +152,7 @@ bool IsPassiveStackableSpell( uint32 spellId )
|
|||||||
Unit::Unit()
|
Unit::Unit()
|
||||||
: WorldObject(), i_motionMaster(this), m_ThreatManager(this), m_HostilRefManager(this)
|
: WorldObject(), i_motionMaster(this), m_ThreatManager(this), m_HostilRefManager(this)
|
||||||
, m_IsInNotifyList(false), m_Notified(false), IsAIEnabled(false)
|
, m_IsInNotifyList(false), m_Notified(false), IsAIEnabled(false)
|
||||||
|
, i_AI(NULL), i_disabledAI(NULL)
|
||||||
{
|
{
|
||||||
m_objectType |= TYPEMASK_UNIT;
|
m_objectType |= TYPEMASK_UNIT;
|
||||||
m_objectTypeId = TYPEID_UNIT;
|
m_objectTypeId = TYPEID_UNIT;
|
||||||
@@ -11250,10 +11253,38 @@ void Unit::CleanupsBeforeDelete()
|
|||||||
RemoveFromWorld();
|
RemoveFromWorld();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Unit::UpdateCharmAI()
|
||||||
|
{
|
||||||
|
if(GetTypeId() == TYPEID_PLAYER)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(i_disabledAI) // disabled AI must be primary AI
|
||||||
|
{
|
||||||
|
if(!isCharmed())
|
||||||
|
{
|
||||||
|
if(i_AI) delete i_AI;
|
||||||
|
i_AI = i_disabledAI;
|
||||||
|
i_disabledAI = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(isCharmed())
|
||||||
|
{
|
||||||
|
i_disabledAI = i_AI;
|
||||||
|
if(isPossessed())
|
||||||
|
i_AI = new PossessedAI((Creature*)this);
|
||||||
|
else
|
||||||
|
i_AI = new PetAI((Creature*)this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CharmInfo* Unit::InitCharmInfo()
|
CharmInfo* Unit::InitCharmInfo()
|
||||||
{
|
{
|
||||||
if(!m_charmInfo)
|
if(!m_charmInfo)
|
||||||
m_charmInfo = new CharmInfo(this);
|
m_charmInfo = new CharmInfo(this);
|
||||||
|
|
||||||
return m_charmInfo;
|
return m_charmInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1109,6 +1109,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
|
|||||||
CharmInfo* GetCharmInfo() { return m_charmInfo; }
|
CharmInfo* GetCharmInfo() { return m_charmInfo; }
|
||||||
CharmInfo* InitCharmInfo();
|
CharmInfo* InitCharmInfo();
|
||||||
void DeleteCharmInfo();
|
void DeleteCharmInfo();
|
||||||
|
void UpdateCharmAI();
|
||||||
SharedVisionList const& GetSharedVisionList() { return m_sharedVision; }
|
SharedVisionList const& GetSharedVisionList() { return m_sharedVision; }
|
||||||
void AddPlayerToVision(Player* plr);
|
void AddPlayerToVision(Player* plr);
|
||||||
void RemovePlayerFromVision(Player* plr);
|
void RemovePlayerFromVision(Player* plr);
|
||||||
@@ -1424,6 +1425,8 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
|
|||||||
protected:
|
protected:
|
||||||
explicit Unit ();
|
explicit Unit ();
|
||||||
|
|
||||||
|
UnitAI *i_AI, *i_disabledAI;
|
||||||
|
|
||||||
void _UpdateSpells(uint32 time);
|
void _UpdateSpells(uint32 time);
|
||||||
|
|
||||||
void _UpdateAutoRepeatSpell();
|
void _UpdateAutoRepeatSpell();
|
||||||
|
|||||||
Reference in New Issue
Block a user