aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/AI/ScriptedAI
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/AI/ScriptedAI')
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp350
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.h38
2 files changed, 157 insertions, 231 deletions
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
index 09545c3b394..7619446bfd0 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
@@ -31,6 +31,8 @@ EndScriptData */
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "Player.h"
+#include "WaypointDefines.h"
+#include "WaypointMovementGenerator.h"
enum Points
{
@@ -39,10 +41,11 @@ enum Points
};
npc_escortAI::npc_escortAI(Creature* creature) : ScriptedAI(creature),
- m_uiWPWaitTimer(2500),
- m_uiPlayerCheckTimer(1000),
+ m_uiWPWaitTimer(1000),
+ m_uiPlayerCheckTimer(0),
m_uiEscortState(STATE_ESCORT_NONE),
MaxPlayerDistance(DEFAULT_MAX_PLAYER_DISTANCE),
+ LastWP(0),
m_pQuestForEscort(NULL),
m_bIsActiveAttacker(true),
m_bIsRunning(false),
@@ -51,24 +54,11 @@ npc_escortAI::npc_escortAI(Creature* creature) : ScriptedAI(creature),
DespawnAtEnd(true),
DespawnAtFar(true),
ScriptWP(false),
- HasImmuneToNPCFlags(false)
+ HasImmuneToNPCFlags(false),
+ m_bStarted(false),
+ m_bEnded(false)
{ }
-void npc_escortAI::AttackStart(Unit* who)
-{
- if (!who)
- return;
-
- if (me->Attack(who, true))
- {
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
- me->GetMotionMaster()->MovementExpired();
-
- if (IsCombatMovementAllowed())
- me->GetMotionMaster()->MoveChase(who);
- }
-}
-
Player* npc_escortAI::GetPlayerForEscort()
{
return ObjectAccessor::GetPlayer(*me, m_uiPlayerGUID);
@@ -114,38 +104,15 @@ bool npc_escortAI::AssistPlayerInCombatAgainst(Unit* who)
void npc_escortAI::MoveInLineOfSight(Unit* who)
{
+ if (me->GetVictim())
+ return;
+
if (me->HasReactState(REACT_AGGRESSIVE) && !me->HasUnitState(UNIT_STATE_STUNNED) && who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me))
- {
if (HasEscortState(STATE_ESCORT_ESCORTING) && AssistPlayerInCombatAgainst(who))
return;
- if (!me->CanFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
- return;
-
- if (me->IsHostileTo(who))
- {
- float fAttackRadius = me->GetAttackDistance(who);
- if (me->IsWithinDistInMap(who, fAttackRadius) && me->IsWithinLOSInMap(who))
- {
- if (!me->GetVictim())
- {
- // Clear distracted state on combat
- if (me->HasUnitState(UNIT_STATE_DISTRACTED))
- {
- me->ClearUnitState(UNIT_STATE_DISTRACTED);
- me->GetMotionMaster()->Clear();
- }
-
- AttackStart(who);
- }
- else if (me->GetMap()->IsDungeon())
- {
- who->SetInCombatWith(me);
- me->AddThreat(who, 0.0f);
- }
- }
- }
- }
+ if (me->CanStartAttack(who, false))
+ AttackStart(who);
}
void npc_escortAI::JustDied(Unit* /*killer*/)
@@ -168,13 +135,13 @@ void npc_escortAI::JustDied(Unit* /*killer*/)
void npc_escortAI::JustRespawned()
{
- m_uiEscortState = STATE_ESCORT_NONE;
+ RemoveEscortState(STATE_ESCORT_ESCORTING | STATE_ESCORT_RETURNING | STATE_ESCORT_PAUSED);
if (!IsCombatMovementAllowed())
SetCombatMovement(true);
//add a small delay before going to first waypoint, normal in near all cases
- m_uiWPWaitTimer = 2500;
+ m_uiWPWaitTimer = 1000;
if (me->getFaction() != me->GetCreatureTemplate()->faction)
me->RestoreFaction();
@@ -184,6 +151,7 @@ void npc_escortAI::JustRespawned()
void npc_escortAI::ReturnToLastPoint()
{
+ me->SetWalk(false);
float x, y, z, o;
me->GetHomePosition(x, y, z, o);
me->GetMotionMaster()->MovePoint(POINT_LAST_POINT, x, y, z);
@@ -231,57 +199,57 @@ bool npc_escortAI::IsPlayerOrGroupInRange()
void npc_escortAI::UpdateAI(uint32 diff)
{
- //Waypoint Updating
if (HasEscortState(STATE_ESCORT_ESCORTING) && !me->GetVictim() && m_uiWPWaitTimer && !HasEscortState(STATE_ESCORT_RETURNING))
{
if (m_uiWPWaitTimer <= diff)
{
- //End of the line
- if (CurrentWP == WaypointList.end())
+ if (!HasEscortState(STATE_ESCORT_PAUSED))
{
- if (DespawnAtEnd)
- {
- TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints");
-
- if (m_bCanReturnToStart)
- {
- float fRetX, fRetY, fRetZ;
- me->GetRespawnPosition(fRetX, fRetY, fRetZ);
-
- me->GetMotionMaster()->MovePoint(POINT_HOME, fRetX, fRetY, fRetZ);
+ m_uiWPWaitTimer = 0;
- m_uiWPWaitTimer = 0;
+ if (m_bEnded)
+ {
+ me->StopMoving();
+ me->GetMotionMaster()->Clear(false);
+ me->GetMotionMaster()->MoveIdle();
- TC_LOG_DEBUG("scripts", "EscortAI are returning home to spawn location: %u, %f, %f, %f", POINT_HOME, fRetX, fRetY, fRetZ);
- return;
- }
+ m_bEnded = false;
- if (m_bCanInstantRespawn)
+ if (DespawnAtEnd)
{
- me->setDeathState(JUST_DIED);
- me->Respawn();
+ TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints");
+
+ if (m_bCanReturnToStart)
+ {
+ float fRetX, fRetY, fRetZ;
+ me->GetRespawnPosition(fRetX, fRetY, fRetZ);
+
+ me->GetMotionMaster()->MovePoint(POINT_HOME, fRetX, fRetY, fRetZ);
+
+ TC_LOG_DEBUG("scripts", "EscortAI are returning home to spawn location: %u, %f, %f, %f", POINT_HOME, fRetX, fRetY, fRetZ);
+ }
+ else if (m_bCanInstantRespawn)
+ {
+ me->setDeathState(JUST_DIED);
+ me->Respawn();
+ }
+ else
+ me->DespawnOrUnsummon();
}
else
- me->DespawnOrUnsummon();
+ TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints with Despawn off");
+ RemoveEscortState(STATE_ESCORT_ESCORTING);
return;
}
- else
- {
- TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints with Despawn off");
- return;
+ if (!m_bStarted)
+ {
+ m_bStarted = true;
+ me->GetMotionMaster()->MovePath(_path, false);
}
- }
-
- if (!HasEscortState(STATE_ESCORT_PAUSED))
- {
- me->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z);
- TC_LOG_DEBUG("scripts", "EscortAI start waypoint %u (%f, %f, %f).", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z);
-
- WaypointStart(CurrentWP->id);
-
- m_uiWPWaitTimer = 0;
+ else if (WaypointMovementGenerator<Creature>* move = dynamic_cast<WaypointMovementGenerator<Creature>*>(me->GetMotionMaster()->top()))
+ WaypointStart(move->GetCurrentNode());
}
}
else
@@ -291,12 +259,11 @@ void npc_escortAI::UpdateAI(uint32 diff)
//Check if player or any member of his group is within range
if (HasEscortState(STATE_ESCORT_ESCORTING) && !m_uiPlayerGUID.IsEmpty() && !me->GetVictim() && !HasEscortState(STATE_ESCORT_RETURNING))
{
- if (m_uiPlayerCheckTimer <= diff)
+ m_uiPlayerCheckTimer += diff;
+ if (m_uiPlayerCheckTimer > 1000)
{
if (DespawnAtFar && !IsPlayerOrGroupInRange())
{
- TC_LOG_DEBUG("scripts", "EscortAI failed because player/group was to far away or not found");
-
if (m_bCanInstantRespawn)
{
me->setDeathState(JUST_DIED);
@@ -308,10 +275,8 @@ void npc_escortAI::UpdateAI(uint32 diff)
return;
}
- m_uiPlayerCheckTimer = 1000;
+ m_uiPlayerCheckTimer = 0;
}
- else
- m_uiPlayerCheckTimer -= diff;
}
UpdateEscortAI(diff);
@@ -327,44 +292,63 @@ void npc_escortAI::UpdateEscortAI(uint32 /*diff*/)
void npc_escortAI::MovementInform(uint32 moveType, uint32 pointId)
{
- if (moveType != POINT_MOTION_TYPE || !HasEscortState(STATE_ESCORT_ESCORTING))
+ // no action allowed if there is no escort
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
return;
- //Combat start position reached, continue waypoint movement
- if (pointId == POINT_LAST_POINT)
+ if (moveType == POINT_MOTION_TYPE)
{
- TC_LOG_DEBUG("scripts", "EscortAI has returned to original position before combat");
-
- me->SetWalk(!m_bIsRunning);
- RemoveEscortState(STATE_ESCORT_RETURNING);
-
if (!m_uiWPWaitTimer)
m_uiWPWaitTimer = 1;
- }
- else if (pointId == POINT_HOME)
- {
- TC_LOG_DEBUG("scripts", "EscortAI has returned to original home location and will continue from beginning of waypoint list.");
- CurrentWP = WaypointList.begin();
- m_uiWPWaitTimer = 1;
+ //Combat start position reached, continue waypoint movement
+ if (pointId == POINT_LAST_POINT)
+ {
+ TC_LOG_DEBUG("scripts", "EscortAI has returned to original position before combat");
+
+ me->SetWalk(!m_bIsRunning);
+ RemoveEscortState(STATE_ESCORT_RETURNING);
+ }
+ else if (pointId == POINT_HOME)
+ {
+ TC_LOG_DEBUG("scripts", "EscortAI has returned to original home location and will continue from beginning of waypoint list.");
+
+ m_bStarted = false;
+ }
}
- else
+ else if (moveType == WAYPOINT_MOTION_TYPE)
{
- //Make sure that we are still on the right waypoint
- if (CurrentWP->id != pointId)
+ //Call WP function
+ WaypointReached(pointId);
+
+ //End of the line
+ if (LastWP && LastWP == pointId)
{
- TC_LOG_ERROR("misc", "TSCR ERROR: EscortAI reached waypoint out of order %u, expected %u, creature entry %u", pointId, CurrentWP->id, me->GetEntry());
+ LastWP = 0;
+
+ m_bStarted = false;
+ m_bEnded = true;
+
+ m_uiWPWaitTimer = 50;
+
return;
}
- TC_LOG_DEBUG("scripts", "EscortAI Waypoint %u reached", CurrentWP->id);
+ TC_LOG_DEBUG("scripts", "EscortAI Waypoint %u reached", pointId);
- //Call WP function
- WaypointReached(CurrentWP->id);
+ WaypointMovementGenerator<Creature>* move = dynamic_cast<WaypointMovementGenerator<Creature>*>(me->GetMotionMaster()->top());
+
+ if (move)
+ m_uiWPWaitTimer = move->GetTrackerTimer().GetExpiry();
- m_uiWPWaitTimer = CurrentWP->WaitTimeMs + 1;
+ //Call WP start function
+ if (!m_uiWPWaitTimer && !HasEscortState(STATE_ESCORT_PAUSED) && move)
+ WaypointStart(move->GetCurrentNode());
- ++CurrentWP;
+ if (m_bIsRunning)
+ me->SetWalk(false);
+ else
+ me->SetWalk(true);
}
}
@@ -389,9 +373,24 @@ void npc_escortAI::OnPossess(bool apply)
void npc_escortAI::AddWaypoint(uint32 id, float x, float y, float z, uint32 waitTime)
{
- Escort_Waypoint t(id, x, y, z, waitTime);
+ Trinity::NormalizeMapCoord(x);
+ Trinity::NormalizeMapCoord(y);
- WaypointList.push_back(t);
+ WaypointNode wp;
+
+ wp.id = id;
+ wp.x = x;
+ wp.y = y;
+ wp.z = z;
+ wp.orientation = 0.f;
+ wp.moveType = m_bIsRunning ? WAYPOINT_MOVE_TYPE_RUN : WAYPOINT_MOVE_TYPE_WALK;
+ wp.delay = waitTime;
+ wp.eventId = 0;
+ wp.eventChance = 100;
+
+ _path.nodes.push_back(std::move(wp));
+
+ LastWP = id;
// i think SD2 no longer uses this function
ScriptWP = true;
@@ -411,10 +410,30 @@ void npc_escortAI::FillPointMovementListForCreature()
if (!movePoints)
return;
- for (ScriptPointVector::const_iterator itr = movePoints->begin(); itr != movePoints->end(); ++itr)
+ LastWP = movePoints->back().uiPointId;
+
+ for (const ScriptPointMove &point : *movePoints)
{
- Escort_Waypoint point(itr->uiPointId, itr->fX, itr->fY, itr->fZ, itr->uiWaitTime);
- WaypointList.push_back(point);
+ WaypointNode wp;
+
+ float x = point.fX;
+ float y = point.fY;
+ float z = point.fZ;
+
+ Trinity::NormalizeMapCoord(x);
+ Trinity::NormalizeMapCoord(y);
+
+ wp.id = point.uiPointId;
+ wp.x = x;
+ wp.y = y;
+ wp.z = z;
+ wp.orientation = 0.f;
+ wp.moveType = m_bIsRunning ? WAYPOINT_MOVE_TYPE_RUN : WAYPOINT_MOVE_TYPE_WALK;
+ wp.delay = point.uiWaitTime;
+ wp.eventId = 0;
+ wp.eventChance = 100;
+
+ _path.nodes.push_back(std::move(wp));
}
}
@@ -453,20 +472,6 @@ void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false
return;
}
- if (!ScriptWP && resetWaypoints) // sd2 never adds wp in script, but tc does
- {
- if (!WaypointList.empty())
- WaypointList.clear();
- FillPointMovementListForCreature();
- }
-
- if (WaypointList.empty())
- {
- TC_LOG_ERROR("scripts", "EscortAI (script: %s, creature entry: %u) starts with 0 waypoints (possible missing entry in script_waypoint. Quest: %u).",
- me->GetScriptName().c_str(), me->GetEntry(), quest ? quest->GetQuestId() : 0);
- return;
- }
-
//set variables
m_bIsActiveAttacker = isActiveAttacker;
m_bIsRunning = run;
@@ -477,12 +482,16 @@ void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false
m_bCanInstantRespawn = instantRespawn;
m_bCanReturnToStart = canLoopPath;
+ if (!ScriptWP && resetWaypoints) // sd2 never adds wp in script, but tc does
+ FillPointMovementListForCreature();
+
if (m_bCanReturnToStart && m_bCanInstantRespawn)
TC_LOG_DEBUG("scripts", "EscortAI is set to return home after waypoint end and instant respawn at waypoint end. Creature will never despawn.");
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
{
- me->GetMotionMaster()->MovementExpired();
+ me->StopMoving();
+ me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveIdle();
TC_LOG_DEBUG("scripts", "EscortAI start with WAYPOINT_MOTION_TYPE, changed to MoveIdle.");
}
@@ -495,9 +504,7 @@ void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
}
- TC_LOG_DEBUG("scripts", "EscortAI started with " UI64FMTD " waypoints. ActiveAttacker = %d, Run = %d, %s", uint64(WaypointList.size()), m_bIsActiveAttacker, m_bIsRunning, m_uiPlayerGUID.ToString().c_str());
-
- CurrentWP = WaypointList.begin();
+ TC_LOG_DEBUG("scripts", "EscortAI started. ActiveAttacker = %d, Run = %d, PlayerGUID = %s", uint32(m_bIsActiveAttacker), uint32(m_bIsRunning), m_uiPlayerGUID.ToString().c_str());
//Set initial speed
if (m_bIsRunning)
@@ -505,6 +512,8 @@ void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false
else
me->SetWalk(true);
+ m_bStarted = false;
+
AddEscortState(STATE_ESCORT_ESCORTING);
}
@@ -514,73 +523,14 @@ void npc_escortAI::SetEscortPaused(bool on)
return;
if (on)
- AddEscortState(STATE_ESCORT_PAUSED);
- else
- RemoveEscortState(STATE_ESCORT_PAUSED);
-}
-
-bool npc_escortAI::SetNextWaypoint(uint32 pointId, float x, float y, float z, float orientation)
-{
- me->UpdatePosition(x, y, z, orientation);
- return SetNextWaypoint(pointId, false, true);
-}
-
-bool npc_escortAI::SetNextWaypoint(uint32 pointId, bool setPosition, bool resetWaypointsOnFail)
-{
- if (!WaypointList.empty())
- WaypointList.clear();
-
- FillPointMovementListForCreature();
-
- if (WaypointList.empty())
- return false;
-
- size_t const size = WaypointList.size();
- Escort_Waypoint waypoint(0, 0, 0, 0, 0);
- do
- {
- waypoint = WaypointList.front();
- WaypointList.pop_front();
- if (waypoint.id == pointId)
- {
- if (setPosition)
- me->UpdatePosition(waypoint.x, waypoint.y, waypoint.z, me->GetOrientation());
-
- CurrentWP = WaypointList.begin();
- return true;
- }
- }
- while (!WaypointList.empty());
-
- // we failed.
- // we reset the waypoints in the start; if we pulled any, reset it again
- if (resetWaypointsOnFail && size != WaypointList.size())
{
- if (!WaypointList.empty())
- WaypointList.clear();
-
- FillPointMovementListForCreature();
+ AddEscortState(STATE_ESCORT_PAUSED);
+ me->StopMoving();
}
-
- return false;
-}
-
-bool npc_escortAI::GetWaypointPosition(uint32 pointId, float& x, float& y, float& z)
-{
- ScriptPointVector const* waypoints = sScriptSystemMgr->GetPointMoveList(me->GetEntry());
- if (!waypoints)
- return false;
-
- for (ScriptPointVector::const_iterator itr = waypoints->begin(); itr != waypoints->end(); ++itr)
+ else
{
- if (itr->uiPointId == pointId)
- {
- x = itr->fX;
- y = itr->fY;
- z = itr->fZ;
- return true;
- }
+ RemoveEscortState(STATE_ESCORT_PAUSED);
+ if (WaypointMovementGenerator<Creature>* move = dynamic_cast<WaypointMovementGenerator<Creature>*>(me->GetMotionMaster()->top()))
+ move->GetTrackerTimer().Reset(1);
}
-
- return false;
}
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
index bc3be71af68..91646c53270 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
@@ -21,29 +21,12 @@
#include "ScriptedCreature.h"
#include "ScriptSystem.h"
+#include "WaypointDefines.h"
class Quest;
#define DEFAULT_MAX_PLAYER_DISTANCE 50
-struct Escort_Waypoint
-{
- Escort_Waypoint(uint32 _id, float _x, float _y, float _z, uint32 _w)
- {
- id = _id;
- x = _x;
- y = _y;
- z = _z;
- WaitTimeMs = _w;
- }
-
- uint32 id;
- float x;
- float y;
- float z;
- uint32 WaitTimeMs;
-};
-
enum eEscortState
{
STATE_ESCORT_NONE = 0x000, //nothing in progress
@@ -59,7 +42,6 @@ struct TC_GAME_API npc_escortAI : public ScriptedAI
~npc_escortAI() { }
// CreatureAI functions
- void AttackStart(Unit* who) override;
void MoveInLineOfSight(Unit* who) override;
@@ -79,15 +61,6 @@ struct TC_GAME_API npc_escortAI : public ScriptedAI
// EscortAI functions
void AddWaypoint(uint32 id, float x, float y, float z, uint32 waitTime = 0); // waitTime is in ms
- //this will set the current position to x/y/z/o, and the current WP to pointId.
- bool SetNextWaypoint(uint32 pointId, float x, float y, float z, float orientation);
-
- //this will set the current position to WP start position (if setPosition == true),
- //and the current WP to pointId
- bool SetNextWaypoint(uint32 pointId, bool setPosition = true, bool resetWaypointsOnFail = true);
-
- bool GetWaypointPosition(uint32 pointId, float& x, float& y, float& z);
-
virtual void WaypointReached(uint32 pointId) = 0;
virtual void WaypointStart(uint32 /*pointId*/) { }
@@ -107,6 +80,7 @@ struct TC_GAME_API npc_escortAI : public ScriptedAI
bool GetAttack() const { return m_bIsActiveAttacker; }//used in EnterEvadeMode override
void SetCanAttack(bool attack) { m_bIsActiveAttacker = attack; }
ObjectGuid GetEventStarterGUID() const { return m_uiPlayerGUID; }
+ void SetWaitTimer(uint32 Timer) { m_uiWPWaitTimer = Timer; }
protected:
Player* GetPlayerForEscort();
@@ -124,11 +98,11 @@ struct TC_GAME_API npc_escortAI : public ScriptedAI
uint32 m_uiPlayerCheckTimer;
uint32 m_uiEscortState;
float MaxPlayerDistance;
+ uint32 LastWP;
- Quest const* m_pQuestForEscort; //generally passed in Start() when regular escort script.
+ WaypointPath _path;
- std::list<Escort_Waypoint> WaypointList;
- std::list<Escort_Waypoint>::iterator CurrentWP;
+ Quest const* m_pQuestForEscort; //generally passed in Start() when regular escort script.
bool m_bIsActiveAttacker; //obsolete, determined by faction.
bool m_bIsRunning; //all creatures are walking by default (has flag MOVEMENTFLAG_WALK)
@@ -138,5 +112,7 @@ struct TC_GAME_API npc_escortAI : public ScriptedAI
bool DespawnAtFar;
bool ScriptWP;
bool HasImmuneToNPCFlags;
+ bool m_bStarted;
+ bool m_bEnded;
};
#endif