From 6728f202a64d0b352d16474283607166be52e04b Mon Sep 17 00:00:00 2001
Date: Sun, 5 Jun 2016 17:43:48 +0200
Subject: [PATCH] smooth waypoint movement
excluding smartAI waypoint movement and gotta refactor old shitty quests done via movementInform n shit and move them to escortAI so they use smooth as well
---
src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp | 298 ++++++++++-----------
src/server/game/AI/ScriptedAI/ScriptedEscortAI.h | 35 +--
src/server/game/Movement/MotionMaster.cpp | 4 +-
src/server/game/Movement/MotionMaster.h | 2 +-
.../WaypointMovementGenerator.cpp | 127 ++++++---
.../MovementGenerators/WaypointMovementGenerator.h | 18 +-
.../game/Movement/Waypoints/WaypointManager.h | 8 +-
7 files changed, 261 insertions(+), 231 deletions(-)
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
index 1b8b472..7681575 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
@@ -37,6 +37,7 @@ enum Points
npc_escortAI::npc_escortAI(Creature* creature) : ScriptedAI(creature),
m_uiWPWaitTimer(2500),
m_uiPlayerCheckTimer(1000),
+ LastWP(0),
m_uiEscortState(STATE_ESCORT_NONE),
MaxPlayerDistance(DEFAULT_MAX_PLAYER_DISTANCE),
m_pQuestForEscort(NULL),
@@ -56,13 +57,8 @@ void npc_escortAI::AttackStart(Unit* who)
return;
if (me->Attack(who, true))
- {
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
- me->GetMotionMaster()->MovementExpired();
-
if (IsCombatMovementAllowed())
me->GetMotionMaster()->MoveChase(who);
- }
}
//see followerAI
@@ -228,60 +224,25 @@ 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)
+ if (!m_bStarted)
{
- 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;
-
- TC_LOG_DEBUG("scripts", "EscortAI are returning home to spawn location: %u, %f, %f, %f", POINT_HOME, fRetX, fRetY, fRetZ);
- return;
- }
-
- if (m_bCanInstantRespawn)
- {
- me->setDeathState(JUST_DIED);
- me->Respawn();
- }
- else
- me->DespawnOrUnsummon();
-
- return;
+ m_bStarted = true;
+ me->GetMotionMaster()->MovePath(-int32(me->GetEntry()), false, false);
+ m_uiWPWaitTimer = 0;
}
else
{
- TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints with Despawn off");
-
- return;
+ WaypointStart((*CurrentWP)->id);
+ m_uiWPWaitTimer = 0;
}
}
-
- 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
m_uiWPWaitTimer -= diff;
- }
//Check if player or any member of his group is within range
if (HasEscortState(STATE_ESCORT_ESCORTING) && m_uiPlayerGUID && !me->GetVictim() && !HasEscortState(STATE_ESCORT_RETURNING))
@@ -322,7 +283,7 @@ void npc_escortAI::UpdateEscortAI(uint32 /*diff*/)
void npc_escortAI::MovementInform(uint32 moveType, uint32 pointId)
{
- if (moveType != POINT_MOTION_TYPE || !HasEscortState(STATE_ESCORT_ESCORTING))
+ if ((moveType != POINT_MOTION_TYPE && moveType != WAYPOINT_MOTION_TYPE) || !HasEscortState(STATE_ESCORT_ESCORTING))
return;
//Combat start position reached, continue waypoint movement
@@ -332,34 +293,75 @@ void npc_escortAI::MovementInform(uint32 moveType, uint32 pointId)
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;
}
- else
+ else if (moveType == WAYPOINT_MOTION_TYPE)
{
- //Make sure that we are still on the right waypoint
- if (CurrentWP->id != pointId)
+ uint32 point = (*CurrentWP)->id;
+
+ //End of the line
+ if (LastWP && LastWP == point)
{
- TC_LOG_ERROR("misc", "TSCR ERROR: EscortAI reached waypoint out of order %u, expected %u, creature entry %u", pointId, CurrentWP->id, me->GetEntry());
- return;
- }
+ m_bStarted = false;
+ me->GetMotionMaster()->MovementExpired();
+ me->GetMotionMaster()->MoveIdle();
- TC_LOG_DEBUG("scripts", "EscortAI Waypoint %u reached", CurrentWP->id);
+ //Call WP function (after movement expiration)
+ WaypointReached(point);
+
+ 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;
+
+ TC_LOG_DEBUG("scripts", "EscortAI are returning home to spawn location: %u, %f, %f, %f", POINT_HOME, fRetX, fRetY, fRetZ);
+ return;
+ }
+
+ if (m_bCanInstantRespawn)
+ {
+ me->setDeathState(JUST_DIED);
+ me->Respawn();
+ }
+ else
+ me->DespawnOrUnsummon();
+
+ return;
+ }
+ else
+ {
+ TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints with Despawn off");
+ return;
+ }
+ }
//Call WP function
- WaypointReached(CurrentWP->id);
+ WaypointReached(point);
+ TC_LOG_DEBUG("scripts", "EscortAI Waypoint %u reached", point);
- m_uiWPWaitTimer = CurrentWP->WaitTimeMs + 1;
+ m_uiWPWaitTimer = (*CurrentWP)->delay;
++CurrentWP;
+
+ if (!m_uiWPWaitTimer && !HasEscortState(STATE_ESCORT_PAUSED))
+ WaypointStart((*CurrentWP)->id);
+
+ if (m_bIsRunning)
+ me->SetWalk(false);
+ else
+ me->SetWalk(true);
}
}
@@ -384,9 +386,42 @@ 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);
+ int32 entry = -int32(me->GetEntry());
- WaypointList.push_back(t);
+ WaypointPathContainer::iterator itr = sWaypointMgr->_waypointStore.find(entry);
+ if (itr != sWaypointMgr->_waypointStore.end())
+ {
+ for (WaypointPath::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
+ {
+ if ((*it)->id == id)
+ {
+ itr->second.erase(it);
+ break;
+ }
+ }
+ }
+
+ WaypointPath& path = sWaypointMgr->_waypointStore[entry];
+ WaypointData* wp = new WaypointData();
+
+ Trinity::NormalizeMapCoord(x);
+ Trinity::NormalizeMapCoord(y);
+
+ wp->id = id;
+ wp->x = x;
+ wp->y = y;
+ wp->z = z;
+ wp->orientation = me->GetOrientation();
+ wp->move_type = 0;
+ wp->delay = waitTime;
+ wp->event_id = 0;
+ wp->event_chance = 100;
+
+ path.push_back(wp);
+
+ CurrentWP = path.begin();
+
+ LastWP = id;
// i think SD2 no longer uses this function
ScriptWP = true;
@@ -406,12 +441,47 @@ void npc_escortAI::FillPointMovementListForCreature()
if (movePoints.empty())
return;
- ScriptPointVector::const_iterator itrEnd = movePoints.end();
- for (ScriptPointVector::const_iterator itr = movePoints.begin(); itr != itrEnd; ++itr)
+ int32 entry = -int32(me->GetEntry());
+
+ WaypointPathContainer::iterator itr = sWaypointMgr->_waypointStore.find(entry);
+ if (itr != sWaypointMgr->_waypointStore.end())
{
- Escort_Waypoint point(itr->uiPointId, itr->fX, itr->fY, itr->fZ, itr->uiWaitTime);
- WaypointList.push_back(point);
+ for (WaypointPath::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
+ delete *it;
+
+ sWaypointMgr->_waypointStore.erase(itr);
+ }
+
+ WaypointPath& path = sWaypointMgr->_waypointStore[entry];
+
+ ScriptPointVector::const_iterator itrEnd = movePoints.end() - 1;
+ LastWP = itrEnd->uiPointId;
+
+ for (ScriptPointVector::const_iterator itr = movePoints.begin(); itr != movePoints.end(); ++itr)
+ {
+ WaypointData* wp = new WaypointData();
+
+ float x = itr->fX;
+ float y = itr->fY;
+ float z = itr->fZ;
+
+ Trinity::NormalizeMapCoord(x);
+ Trinity::NormalizeMapCoord(y);
+
+ wp->id = itr->uiPointId;
+ wp->x = x;
+ wp->y = y;
+ wp->z = z;
+ wp->orientation = me->GetOrientation();
+ wp->move_type = 0;
+ wp->delay = itr->uiWaitTime;
+ wp->event_id = 0;
+ wp->event_chance = 100;
+
+ path.push_back(wp);
}
+
+ CurrentWP = path.begin();
}
void npc_escortAI::SetRun(bool on)
@@ -449,20 +519,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;
@@ -473,6 +529,9 @@ 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.");
@@ -491,9 +550,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 waypoints. ActiveAttacker = %d, Run = %d.", m_bIsActiveAttacker, m_bIsRunning);
//Set initial speed
if (m_bIsRunning)
@@ -510,73 +567,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.empty())
- 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 = (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 37a1464..92ca5fb 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
@@ -20,27 +20,11 @@
#define SC_ESCORTAI_H
#include "ScriptSystem.h"
+#include "WaypointMovementGenerator.h"
+#include "WaypointManager.h"
#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
@@ -76,15 +60,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*/) { }
@@ -120,17 +95,17 @@ struct TC_GAME_API npc_escortAI : public ScriptedAI
uint32 m_uiWPWaitTimer;
uint32 m_uiPlayerCheckTimer;
uint32 m_uiEscortState;
+ uint32 LastWP;
float MaxPlayerDistance;
+ WaypointPath::const_iterator CurrentWP;
Quest const* m_pQuestForEscort; //generally passed in Start() when regular escort script.
- std::list<Escort_Waypoint> WaypointList;
- std::list<Escort_Waypoint>::iterator CurrentWP;
-
bool m_bIsActiveAttacker; //obsolete, determined by faction.
bool m_bIsRunning; //all creatures are walking by default (has flag MOVEMENTFLAG_WALK)
bool m_bCanInstantRespawn; //if creature should respawn instantly after escort over (if not, database respawntime are used)
bool m_bCanReturnToStart; //if creature can walk same path (loop) without despawn. Not for regular escort quests.
+ bool m_bStarted;
bool DespawnAtEnd;
bool DespawnAtFar;
bool ScriptWP;
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index 6f7dae1..3da90e8 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -647,7 +647,7 @@ void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot)
}
}
-void MotionMaster::MovePath(uint32 path_id, bool repeatable)
+void MotionMaster::MovePath(int32 path_id, bool repeatable, bool loadFromDB /* = false*/)
{
if (!path_id)
return;
@@ -664,7 +664,7 @@ void MotionMaster::MovePath(uint32 path_id, bool repeatable)
//_owner->GetTypeId() == TYPEID_PLAYER ?
//Mutate(new WaypointMovementGenerator<Player>(path_id, repeatable)):
- Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable), MOTION_SLOT_IDLE);
+ Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable, loadFromDB), MOTION_SLOT_IDLE);
TC_LOG_DEBUG("misc", "%s (GUID: %u) starts moving over path(Id:%u, repeatable: %s).",
_owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature",
diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
index 005f10b..0bfb9c1 100644
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -200,7 +200,7 @@ class TC_GAME_API MotionMaster //: private std::stack<MovementGenerator *>
void MoveSeekAssistanceDistract(uint32 timer);
void MoveTaxiFlight(uint32 path, uint32 pathnode);
void MoveDistract(uint32 time);
- void MovePath(uint32 path_id, bool repeatable);
+ void MovePath(int32 path_id, bool repeatable, bool loadFromDB = true);
void MoveRotate(uint32 time, RotateDirection direction);
MovementGeneratorType GetCurrentMovementGeneratorType() const;
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index 2ffa1a6..de9cd1d 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -45,13 +45,13 @@ void WaypointMovementGenerator<Creature>::LoadPath(Creature* creature)
return;
}
- StartMoveNow(creature);
+ if (!Stopped())
+ StartMoveNow(creature);
}
void WaypointMovementGenerator<Creature>::DoInitialize(Creature* creature)
{
LoadPath(creature);
- creature->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
}
void WaypointMovementGenerator<Creature>::DoFinalize(Creature* creature)
@@ -62,18 +62,14 @@ void WaypointMovementGenerator<Creature>::DoFinalize(Creature* creature)
void WaypointMovementGenerator<Creature>::DoReset(Creature* creature)
{
- creature->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
- StartMoveNow(creature);
+ if (!Stopped())
+ StartMoveNow(creature);
}
void WaypointMovementGenerator<Creature>::OnArrived(Creature* creature)
{
if (!i_path || i_path->empty())
return;
- if (m_isArrivalDone)
- return;
-
- m_isArrivalDone = true;
if (i_path->at(i_currentNode)->event_id && urand(0, 99) < i_path->at(i_currentNode)->event_chance)
{
@@ -82,14 +78,46 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature* creature)
creature->GetMap()->ScriptsStart(sWaypointScripts, i_path->at(i_currentNode)->event_id, creature, NULL);
}
+ if (i_path->at(i_currentNode)->delay)
+ {
+ creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
+ Stop(i_path->at(i_currentNode)->delay);
+ creature->StopMoving();
+ }
+
// Inform script
MovementInform(creature);
creature->UpdateWaypointID(i_currentNode);
+}
- if (i_path->at(i_currentNode)->delay)
+void WaypointMovementGenerator<Creature>::FormationMove(Creature* creature)
+{
+ bool transportPath = creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && creature->GetTransGUID();
+
+ WaypointData const* node = i_path->at(i_currentNode);
+
+ Movement::Location formationDest(node->x, node->y, node->z, 0.0f);
+
+ //! If creature is on transport, we assume waypoints set in DB are already transport offsets
+ if (transportPath)
+ if (TransportBase* trans = creature->GetDirectTransport())
+ trans->CalculatePassengerPosition(formationDest.x, formationDest.y, formationDest.z, &formationDest.orientation);
+
+ if (loadFromDB)
{
- creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
- Stop(i_path->at(i_currentNode)->delay);
+ Movement::MoveSplineInit init(creature);
+ //! Accepts angles such as 0.00001 and -0.00001, 0 must be ignored, default value in waypoint table
+ if (node->orientation && node->delay)
+ init.SetFacing(node->orientation);
+ init.SetWalk(node->move_type == WAYPOINT_MOVE_TYPE_RUN ? true : false);
+ }
+
+ //Call for creature group update
+ if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature)
+ {
+ if (loadFromDB)
+ creature->SetWalk(node->move_type == WAYPOINT_MOVE_TYPE_RUN ? true : false);
+ creature->GetFormation()->LeaderMoveTo(formationDest.x, formationDest.y, formationDest.z);
}
}
@@ -98,8 +126,7 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
if (!i_path || i_path->empty())
return false;
- if (Stopped())
- return true;
+ next_currentNode = i_currentNode;
bool transportPath = creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && creature->GetTransGUID();
@@ -133,13 +160,14 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
}
i_currentNode = (i_currentNode+1) % i_path->size();
+ next_currentNode = 0;
}
WaypointData const* node = i_path->at(i_currentNode);
m_isArrivalDone = false;
- creature->AddUnitState(UNIT_STATE_ROAMING_MOVE);
+ creature->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
Movement::Location formationDest(node->x, node->y, node->z, 0.0f);
Movement::MoveSplineInit init(creature);
@@ -152,30 +180,41 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
trans->CalculatePassengerPosition(formationDest.x, formationDest.y, formationDest.z, &formationDest.orientation);
}
- //! Do not use formationDest here, MoveTo requires transport offsets due to DisableTransportPathTransformations() call
- //! but formationDest contains global coordinates
- init.MoveTo(node->x, node->y, node->z);
+ if (loadFromDB)
+ {
+ //! Accepts angles such as 0.00001 and -0.00001, 0 must be ignored, default value in waypoint table
+ if (node->orientation && node->delay)
+ init.SetFacing(node->orientation);
- //! Accepts angles such as 0.00001 and -0.00001, 0 must be ignored, default value in waypoint table
- if (node->orientation && node->delay)
- init.SetFacing(node->orientation);
+ switch (node->move_type)
+ {
+ case WAYPOINT_MOVE_TYPE_LAND:
+ init.SetAnimation(Movement::ToGround);
+ break;
+ case WAYPOINT_MOVE_TYPE_TAKEOFF:
+ init.SetAnimation(Movement::ToFly);
+ break;
+ case WAYPOINT_MOVE_TYPE_RUN:
+ init.SetWalk(false);
+ break;
+ case WAYPOINT_MOVE_TYPE_WALK:
+ init.SetWalk(true);
+ break;
+ }
+ }
- switch (node->move_type)
+ auto end = i_path->size();
+ Movement::PointsArray pathing;
+ pathing.push_back(G3D::Vector3(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ()));
+ for (auto i = i_currentNode; i < end; ++i)
{
- case WAYPOINT_MOVE_TYPE_LAND:
- init.SetAnimation(Movement::ToGround);
- break;
- case WAYPOINT_MOVE_TYPE_TAKEOFF:
- init.SetAnimation(Movement::ToFly);
- break;
- case WAYPOINT_MOVE_TYPE_RUN:
- init.SetWalk(false);
- break;
- case WAYPOINT_MOVE_TYPE_WALK:
- init.SetWalk(true);
- break;
+ node = i_path->at(i);
+ pathing.push_back(G3D::Vector3(node->x, node->y, node->z));
}
+ (creature->CanFly() || creature->IsFlying()) ? init.SetFly() : init.SetSmooth();
+ init.MovebyPath(pathing);
+
init.Launch();
//Call for creature group update
@@ -204,7 +243,7 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di
if (Stopped())
{
if (CanMove(diff))
- return StartMove(creature);
+ return StartMoveNow(creature);
}
else
{
@@ -213,15 +252,27 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di
creature->SetHomePosition(creature->GetPosition());
if (creature->IsStopped())
- Stop(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER));
+ Stop(loadFromDB ? sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER) : 2 * HOUR * IN_MILLISECONDS);
else if (creature->movespline->Finalized())
{
+ m_isArrivalDone = true;
OnArrived(creature);
- return StartMove(creature);
+ return loadFromDB ? StartMove(creature) : true;
+ }
+ else
+ {
+ auto pointId = uint32(creature->movespline->currentPathIdx()) + next_currentNode;
+ if (pointId > i_currentNode)
+ {
+ OnArrived(creature);
+ i_currentNode = pointId;
+ FormationMove(creature);
+ return i_currentNode < (i_path->size() - 1);
+ }
}
}
- return true;
- }
+ return true;
+}
void WaypointMovementGenerator<Creature>::MovementInform(Creature* creature)
{
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
index 7230982..ddd45ae 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
@@ -37,7 +37,7 @@ template<class T, class P>
class PathMovementBase
{
public:
- PathMovementBase() : i_path(), i_currentNode(0) { }
+ PathMovementBase() : i_path(), i_currentNode(0), next_currentNode(0) { }
virtual ~PathMovementBase() { };
uint32 GetCurrentNode() const { return i_currentNode; }
@@ -45,6 +45,7 @@ class PathMovementBase
protected:
P i_path;
uint32 i_currentNode;
+ uint32 next_currentNode;
};
template<class T>
@@ -55,8 +56,8 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Crea
public PathMovementBase<Creature, WaypointPath const*>
{
public:
- WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true)
- : i_nextMoveTime(0), m_isArrivalDone(false), path_id(_path_id), repeating(_repeating) { }
+ WaypointMovementGenerator(int32 _path_id = 0, bool _repeating = true, bool _loadFromDB = true)
+ : i_nextMoveTime(0), m_isArrivalDone(false), path_id(_path_id), repeating(_repeating), loadFromDB(_loadFromDB) { }
~WaypointMovementGenerator() { i_path = NULL; }
void DoInitialize(Creature*);
void DoFinalize(Creature*);
@@ -72,6 +73,8 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Crea
bool GetResetPos(Creature*, float& x, float& y, float& z);
+ TimeTrackerSmall & GetTrackerTimer() { return i_nextMoveTime; }
+
private:
void Stop(int32 time) { i_nextMoveTime.Reset(time);}
@@ -87,16 +90,19 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Crea
void OnArrived(Creature*);
bool StartMove(Creature*);
- void StartMoveNow(Creature* creature)
+ void FormationMove(Creature*);
+
+ bool StartMoveNow(Creature* creature)
{
i_nextMoveTime.Reset(0);
- StartMove(creature);
+ return StartMove(creature);
}
TimeTrackerSmall i_nextMoveTime;
bool m_isArrivalDone;
- uint32 path_id;
+ int32 path_id;
bool repeating;
+ bool loadFromDB;
};
/** FlightPathMovementGenerator generates movement of the player for the paths
diff --git a/src/server/game/Movement/Waypoints/WaypointManager.h b/src/server/game/Movement/Waypoints/WaypointManager.h
index 63dc418..bd14f4f 100644
--- a/src/server/game/Movement/Waypoints/WaypointManager.h
+++ b/src/server/game/Movement/Waypoints/WaypointManager.h
@@ -42,7 +42,7 @@ struct WaypointData
};
typedef std::vector<WaypointData*> WaypointPath;
-typedef std::unordered_map<uint32, WaypointPath> WaypointPathContainer;
+typedef std::unordered_map<int32, WaypointPath> WaypointPathContainer;
class TC_GAME_API WaypointMgr
{
@@ -56,7 +56,7 @@ class TC_GAME_API WaypointMgr
void Load();
// Returns the path from a given id
- WaypointPath const* GetPath(uint32 id) const
+ WaypointPath const* GetPath(int32 id) const
{
WaypointPathContainer::const_iterator itr = _waypointStore.find(id);
if (itr != _waypointStore.end())
@@ -65,11 +65,11 @@ class TC_GAME_API WaypointMgr
return NULL;
}
+ WaypointPathContainer _waypointStore;
+
private:
WaypointMgr();
~WaypointMgr();
-
- WaypointPathContainer _waypointStore;
};
#define sWaypointMgr WaypointMgr::instance()
--
1.9.5.msysgit.0