www.pudn.com > ScriptDev.rar > npc_escortAI.cpp
#include "npc_escortAI.h"
#define WP_LAST_POINT -1
#define MAX_PLAYER_DISTANCE 50
bool npc_escortAI::IsVisible(Unit* who) const
{
if (!who)
return false;
return m_creature->IsWithinDistInMap(who, VISIBLE_RANGE) && who->isVisibleForOrDetect(m_creature,true);
}
void npc_escortAI::AttackStart(Unit *who)
{
if (!who)
return;
if (IsBeingEscorted && !Defend)
return;
if (who->isTargetableForAttack())
{
//Begin attack
if ( m_creature->Attack(who, true) )
{
m_creature->GetMotionMaster()->MovementExpired();
m_creature->GetMotionMaster()->MoveChase(who);
m_creature->AddThreat(who, 0.0f);
m_creature->resetAttackTimer();
if (who->GetTypeId() == TYPEID_PLAYER)
m_creature->SetLootRecipient((Player*)who);
}
if (!InCombat)
{
InCombat = true;
//Store last position
m_creature->GetPosition(LastPos.x, LastPos.y, LastPos.z);
debug_log("SD2: EscortAI has entered combat via Attack and stored last location");
Aggro(who);
}
}
}
void npc_escortAI::MoveInLineOfSight(Unit *who)
{
if (IsBeingEscorted && !Attack)
return;
if( !m_creature->getVictim() && who->isTargetableForAttack() && ( m_creature->IsHostileTo( who )) && who->isInAccessablePlaceFor(m_creature) )
{
if (m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
return;
float attackRadius = m_creature->GetAttackDistance(who);
if( m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who) )
{
who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
//Begin attack
if ( m_creature->Attack(who, true) )
{
m_creature->GetMotionMaster()->MovementExpired();
m_creature->GetMotionMaster()->MoveChase(who);
m_creature->AddThreat(who, 0.0f);
m_creature->resetAttackTimer();
if (who->GetTypeId() == TYPEID_PLAYER)
m_creature->SetLootRecipient((Player*)who);
}
if (!InCombat)
{
InCombat = true;
//Store last position
m_creature->GetPosition(LastPos.x, LastPos.y, LastPos.z);
debug_log("SD2: EscortAI has entered combat via LOS and stored last location");
Aggro(who);
}
}
}
}
void npc_escortAI::JustRespawned()
{
InCombat = false;
IsBeingEscorted = false;
IsOnHold = false;
//Re-Enable gossip
m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
Reset();
}
void npc_escortAI::EnterEvadeMode()
{
InCombat = false;
m_creature->RemoveAllAuras();
m_creature->DeleteThreatList();
m_creature->CombatStop();
if (IsBeingEscorted)
{
debug_log("SD2: EscortAI has left combat and is now returning to last point");
Returning = true;
m_creature->GetMotionMaster()->MovementExpired();
m_creature->GetMotionMaster()->MovePoint(WP_LAST_POINT, LastPos.x, LastPos.y, LastPos.z);
}else
{
m_creature->GetMotionMaster()->MovementExpired();
m_creature->GetMotionMaster()->MoveTargetedHome();
}
Reset();
}
void npc_escortAI::UpdateAI(const uint32 diff)
{
//Waypoint Updating
if (IsBeingEscorted && !InCombat && WaitTimer && !Returning)
if (WaitTimer <= diff)
{
if (ReconnectWP)
{
//Correct movement speed
if (Run)
m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
else m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
//Continue with waypoints
if( !IsOnHold )
{
m_creature->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z );
debug_log("SD2: EscortAI Reconnect WP is: %d, %f, %f, %f", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z);
WaitTimer = 0;
ReconnectWP = false;
return;
}
}
//End of the line, Despawn self then immediatly respawn
if (CurrentWP == WaypointList.end())
{
debug_log("SD2: EscortAI reached end of waypoints");
m_creature->setDeathState(JUST_DIED);
m_creature->SetHealth(0);
m_creature->CombatStop();
m_creature->DeleteThreatList();
m_creature->Respawn();
m_creature->GetMotionMaster()->Clear(true);
//Re-Enable gossip
m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
IsBeingEscorted = false;
WaitTimer = 0;
return;
}
if( !IsOnHold )
{
m_creature->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z );
debug_log("SD2: EscortAI Next WP is: %d, %f, %f, %f", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z);
WaitTimer = 0;
}
}else WaitTimer -= diff;
//Check if player is within range
if (IsBeingEscorted && !InCombat && PlayerGUID)
if (PlayerTimer < diff)
{
Unit* p = Unit::GetUnit(*m_creature, PlayerGUID);
if (!p || m_creature->GetDistance(p) > MAX_PLAYER_DISTANCE)
{
JustDied(m_creature);
IsBeingEscorted = false;
debug_log("SD2: EscortAI Evaded back to spawn point because player was to far away or not found");
m_creature->setDeathState(JUST_DIED);
m_creature->SetHealth(0);
m_creature->CombatStop();
m_creature->DeleteThreatList();
m_creature->Respawn();
m_creature->GetMotionMaster()->Clear(true);
//Re-Enable gossip
m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
PlayerTimer = 1000;
}else PlayerTimer -= diff;
//Check if we have a current target
if( m_creature->isAlive() && m_creature->SelectHostilTarget() && m_creature->getVictim())
{
//If we are within range melee the target
if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
{
if( m_creature->isAttackReady() )
{
m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer();
}
}
}
}
void npc_escortAI::MovementInform(uint32 type, uint32 id)
{
if (type != POINT_MOTION_TYPE || !IsBeingEscorted)
return;
//Original position reached, continue waypoint movement
if (id == WP_LAST_POINT)
{
debug_log("SD2: EscortAI has returned to original position before combat");
ReconnectWP = true;
Returning = false;
WaitTimer = 1;
}else
{
//Make sure that we are still on the right waypoint
if (CurrentWP->id != id)
{
debug_log("SD2 ERROR: EscortAI reached waypoint out of order %d, expected %d", id, CurrentWP->id);
return;
}
debug_log("SD2: EscortAI Waypoint %d reached", CurrentWP->id);
//Call WP function
WaypointReached(CurrentWP->id);
WaitTimer = CurrentWP->WaitTimeMs + 1;
++CurrentWP;
}
}
void npc_escortAI::AddWaypoint(uint32 id, float x, float y, float z, uint32 WaitTimeMs)
{
Escort_Waypoint t(id, x, y, z, WaitTimeMs);
WaypointList.push_back(t);
}
void npc_escortAI::Start(bool bAttack, bool bDefend, bool bRun, uint64 pGUID)
{
if (InCombat)
{
debug_log("SD2 ERROR: EscortAI attempt to Start while in combat");
return;
}
if (WaypointList.empty())
{
debug_log("SD2 ERROR: Call to escortAI::Start with 0 waypoints");
return;
}
Attack = bAttack;
Defend = bDefend;
Run = bRun;
PlayerGUID = pGUID;
debug_log("SD2: EscortAI started with %d waypoints. Attack = %d, Defend = %d, Run = %d, PlayerGUID = %d", WaypointList.size(), Attack, Defend, Run, PlayerGUID);
CurrentWP = WaypointList.begin();
//Set initial speed
if (Run)
m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
else m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
//Start WP
m_creature->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z );
debug_log("SD2: EscortAI Next WP is: %d, %f, %f, %f", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z);
IsBeingEscorted = true;
ReconnectWP = false;
Returning = false;
//Disable gossip
m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}