1. From 6728f202a64d0b352d16474283607166be52e04b Mon Sep 17 00:00:00 2001
  2. From: Riztazz <[email protected]>
  3. Date: Sun, 5 Jun 2016 17:43:48 +0200
  4. Subject: [PATCH] smooth waypoint movement
  5. 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
  6. ---
  7. src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp | 298 ++++++++++-----------
  8. src/server/game/AI/ScriptedAI/ScriptedEscortAI.h | 35 +--
  9. src/server/game/Movement/MotionMaster.cpp | 4 +-
  10. src/server/game/Movement/MotionMaster.h | 2 +-
  11. .../WaypointMovementGenerator.cpp | 127 ++++++---
  12. .../MovementGenerators/WaypointMovementGenerator.h | 18 +-
  13. .../game/Movement/Waypoints/WaypointManager.h | 8 +-
  14. 7 files changed, 261 insertions(+), 231 deletions(-)
  15. diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
  16. index 1b8b472..7681575 100644
  17. --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
  18. +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
  19. @@ -37,6 +37,7 @@ enum Points
  20. npc_escortAI::npc_escortAI(Creature* creature) : ScriptedAI(creature),
  21. m_uiWPWaitTimer(2500),
  22. m_uiPlayerCheckTimer(1000),
  23. + LastWP(0),
  24. m_uiEscortState(STATE_ESCORT_NONE),
  25. MaxPlayerDistance(DEFAULT_MAX_PLAYER_DISTANCE),
  26. m_pQuestForEscort(NULL),
  27. @@ -56,13 +57,8 @@ void npc_escortAI::AttackStart(Unit* who)
  28. return;
  29. if (me->Attack(who, true))
  30. - {
  31. - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
  32. - me->GetMotionMaster()->MovementExpired();
  33. -
  34. if (IsCombatMovementAllowed())
  35. me->GetMotionMaster()->MoveChase(who);
  36. - }
  37. }
  38. //see followerAI
  39. @@ -228,60 +224,25 @@ void npc_escortAI::UpdateAI(uint32 diff)
  40. {
  41. //Waypoint Updating
  42. if (HasEscortState(STATE_ESCORT_ESCORTING) && !me->GetVictim() && m_uiWPWaitTimer && !HasEscortState(STATE_ESCORT_RETURNING))
  43. - {
  44. if (m_uiWPWaitTimer <= diff)
  45. {
  46. - //End of the line
  47. - if (CurrentWP == WaypointList.end())
  48. + if (!HasEscortState(STATE_ESCORT_PAUSED))
  49. {
  50. - if (DespawnAtEnd)
  51. + if (!m_bStarted)
  52. {
  53. - TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints");
  54. -
  55. - if (m_bCanReturnToStart)
  56. - {
  57. - float fRetX, fRetY, fRetZ;
  58. - me->GetRespawnPosition(fRetX, fRetY, fRetZ);
  59. -
  60. - me->GetMotionMaster()->MovePoint(POINT_HOME, fRetX, fRetY, fRetZ);
  61. -
  62. - m_uiWPWaitTimer = 0;
  63. -
  64. - TC_LOG_DEBUG("scripts", "EscortAI are returning home to spawn location: %u, %f, %f, %f", POINT_HOME, fRetX, fRetY, fRetZ);
  65. - return;
  66. - }
  67. -
  68. - if (m_bCanInstantRespawn)
  69. - {
  70. - me->setDeathState(JUST_DIED);
  71. - me->Respawn();
  72. - }
  73. - else
  74. - me->DespawnOrUnsummon();
  75. -
  76. - return;
  77. + m_bStarted = true;
  78. + me->GetMotionMaster()->MovePath(-int32(me->GetEntry()), false, false);
  79. + m_uiWPWaitTimer = 0;
  80. }
  81. else
  82. {
  83. - TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints with Despawn off");
  84. -
  85. - return;
  86. + WaypointStart((*CurrentWP)->id);
  87. + m_uiWPWaitTimer = 0;
  88. }
  89. }
  90. -
  91. - if (!HasEscortState(STATE_ESCORT_PAUSED))
  92. - {
  93. - me->GetMotionMaster()->MovePoint(CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z);
  94. - TC_LOG_DEBUG("scripts", "EscortAI start waypoint %u (%f, %f, %f).", CurrentWP->id, CurrentWP->x, CurrentWP->y, CurrentWP->z);
  95. -
  96. - WaypointStart(CurrentWP->id);
  97. -
  98. - m_uiWPWaitTimer = 0;
  99. - }
  100. }
  101. else
  102. m_uiWPWaitTimer -= diff;
  103. - }
  104. //Check if player or any member of his group is within range
  105. if (HasEscortState(STATE_ESCORT_ESCORTING) && m_uiPlayerGUID && !me->GetVictim() && !HasEscortState(STATE_ESCORT_RETURNING))
  106. @@ -322,7 +283,7 @@ void npc_escortAI::UpdateEscortAI(uint32 /*diff*/)
  107. void npc_escortAI::MovementInform(uint32 moveType, uint32 pointId)
  108. {
  109. - if (moveType != POINT_MOTION_TYPE || !HasEscortState(STATE_ESCORT_ESCORTING))
  110. + if ((moveType != POINT_MOTION_TYPE && moveType != WAYPOINT_MOTION_TYPE) || !HasEscortState(STATE_ESCORT_ESCORTING))
  111. return;
  112. //Combat start position reached, continue waypoint movement
  113. @@ -332,34 +293,75 @@ void npc_escortAI::MovementInform(uint32 moveType, uint32 pointId)
  114. me->SetWalk(!m_bIsRunning);
  115. RemoveEscortState(STATE_ESCORT_RETURNING);
  116. -
  117. - if (!m_uiWPWaitTimer)
  118. - m_uiWPWaitTimer = 1;
  119. }
  120. else if (pointId == POINT_HOME)
  121. {
  122. TC_LOG_DEBUG("scripts", "EscortAI has returned to original home location and will continue from beginning of waypoint list.");
  123. -
  124. - CurrentWP = WaypointList.begin();
  125. m_uiWPWaitTimer = 1;
  126. }
  127. - else
  128. + else if (moveType == WAYPOINT_MOTION_TYPE)
  129. {
  130. - //Make sure that we are still on the right waypoint
  131. - if (CurrentWP->id != pointId)
  132. + uint32 point = (*CurrentWP)->id;
  133. +
  134. + //End of the line
  135. + if (LastWP && LastWP == point)
  136. {
  137. - TC_LOG_ERROR("misc", "TSCR ERROR: EscortAI reached waypoint out of order %u, expected %u, creature entry %u", pointId, CurrentWP->id, me->GetEntry());
  138. - return;
  139. - }
  140. + m_bStarted = false;
  141. + me->GetMotionMaster()->MovementExpired();
  142. + me->GetMotionMaster()->MoveIdle();
  143. - TC_LOG_DEBUG("scripts", "EscortAI Waypoint %u reached", CurrentWP->id);
  144. + //Call WP function (after movement expiration)
  145. + WaypointReached(point);
  146. +
  147. + if (DespawnAtEnd)
  148. + {
  149. + TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints");
  150. +
  151. + if (m_bCanReturnToStart)
  152. + {
  153. + float fRetX, fRetY, fRetZ;
  154. + me->GetRespawnPosition(fRetX, fRetY, fRetZ);
  155. +
  156. + me->GetMotionMaster()->MovePoint(POINT_HOME, fRetX, fRetY, fRetZ);
  157. +
  158. + m_uiWPWaitTimer = 0;
  159. +
  160. + TC_LOG_DEBUG("scripts", "EscortAI are returning home to spawn location: %u, %f, %f, %f", POINT_HOME, fRetX, fRetY, fRetZ);
  161. + return;
  162. + }
  163. +
  164. + if (m_bCanInstantRespawn)
  165. + {
  166. + me->setDeathState(JUST_DIED);
  167. + me->Respawn();
  168. + }
  169. + else
  170. + me->DespawnOrUnsummon();
  171. +
  172. + return;
  173. + }
  174. + else
  175. + {
  176. + TC_LOG_DEBUG("scripts", "EscortAI reached end of waypoints with Despawn off");
  177. + return;
  178. + }
  179. + }
  180. //Call WP function
  181. - WaypointReached(CurrentWP->id);
  182. + WaypointReached(point);
  183. + TC_LOG_DEBUG("scripts", "EscortAI Waypoint %u reached", point);
  184. - m_uiWPWaitTimer = CurrentWP->WaitTimeMs + 1;
  185. + m_uiWPWaitTimer = (*CurrentWP)->delay;
  186. ++CurrentWP;
  187. +
  188. + if (!m_uiWPWaitTimer && !HasEscortState(STATE_ESCORT_PAUSED))
  189. + WaypointStart((*CurrentWP)->id);
  190. +
  191. + if (m_bIsRunning)
  192. + me->SetWalk(false);
  193. + else
  194. + me->SetWalk(true);
  195. }
  196. }
  197. @@ -384,9 +386,42 @@ void npc_escortAI::OnPossess(bool apply)
  198. void npc_escortAI::AddWaypoint(uint32 id, float x, float y, float z, uint32 waitTime)
  199. {
  200. - Escort_Waypoint t(id, x, y, z, waitTime);
  201. + int32 entry = -int32(me->GetEntry());
  202. - WaypointList.push_back(t);
  203. + WaypointPathContainer::iterator itr = sWaypointMgr->_waypointStore.find(entry);
  204. + if (itr != sWaypointMgr->_waypointStore.end())
  205. + {
  206. + for (WaypointPath::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
  207. + {
  208. + if ((*it)->id == id)
  209. + {
  210. + itr->second.erase(it);
  211. + break;
  212. + }
  213. + }
  214. + }
  215. +
  216. + WaypointPath& path = sWaypointMgr->_waypointStore[entry];
  217. + WaypointData* wp = new WaypointData();
  218. +
  219. + Trinity::NormalizeMapCoord(x);
  220. + Trinity::NormalizeMapCoord(y);
  221. +
  222. + wp->id = id;
  223. + wp->x = x;
  224. + wp->y = y;
  225. + wp->z = z;
  226. + wp->orientation = me->GetOrientation();
  227. + wp->move_type = 0;
  228. + wp->delay = waitTime;
  229. + wp->event_id = 0;
  230. + wp->event_chance = 100;
  231. +
  232. + path.push_back(wp);
  233. +
  234. + CurrentWP = path.begin();
  235. +
  236. + LastWP = id;
  237. // i think SD2 no longer uses this function
  238. ScriptWP = true;
  239. @@ -406,12 +441,47 @@ void npc_escortAI::FillPointMovementListForCreature()
  240. if (movePoints.empty())
  241. return;
  242. - ScriptPointVector::const_iterator itrEnd = movePoints.end();
  243. - for (ScriptPointVector::const_iterator itr = movePoints.begin(); itr != itrEnd; ++itr)
  244. + int32 entry = -int32(me->GetEntry());
  245. +
  246. + WaypointPathContainer::iterator itr = sWaypointMgr->_waypointStore.find(entry);
  247. + if (itr != sWaypointMgr->_waypointStore.end())
  248. {
  249. - Escort_Waypoint point(itr->uiPointId, itr->fX, itr->fY, itr->fZ, itr->uiWaitTime);
  250. - WaypointList.push_back(point);
  251. + for (WaypointPath::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
  252. + delete *it;
  253. +
  254. + sWaypointMgr->_waypointStore.erase(itr);
  255. + }
  256. +
  257. + WaypointPath& path = sWaypointMgr->_waypointStore[entry];
  258. +
  259. + ScriptPointVector::const_iterator itrEnd = movePoints.end() - 1;
  260. + LastWP = itrEnd->uiPointId;
  261. +
  262. + for (ScriptPointVector::const_iterator itr = movePoints.begin(); itr != movePoints.end(); ++itr)
  263. + {
  264. + WaypointData* wp = new WaypointData();
  265. +
  266. + float x = itr->fX;
  267. + float y = itr->fY;
  268. + float z = itr->fZ;
  269. +
  270. + Trinity::NormalizeMapCoord(x);
  271. + Trinity::NormalizeMapCoord(y);
  272. +
  273. + wp->id = itr->uiPointId;
  274. + wp->x = x;
  275. + wp->y = y;
  276. + wp->z = z;
  277. + wp->orientation = me->GetOrientation();
  278. + wp->move_type = 0;
  279. + wp->delay = itr->uiWaitTime;
  280. + wp->event_id = 0;
  281. + wp->event_chance = 100;
  282. +
  283. + path.push_back(wp);
  284. }
  285. +
  286. + CurrentWP = path.begin();
  287. }
  288. void npc_escortAI::SetRun(bool on)
  289. @@ -449,20 +519,6 @@ void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false
  290. return;
  291. }
  292. - if (!ScriptWP && resetWaypoints) // sd2 never adds wp in script, but tc does
  293. - {
  294. - if (!WaypointList.empty())
  295. - WaypointList.clear();
  296. - FillPointMovementListForCreature();
  297. - }
  298. -
  299. - if (WaypointList.empty())
  300. - {
  301. - TC_LOG_ERROR("scripts", "EscortAI (script: %s, creature entry: %u) starts with 0 waypoints (possible missing entry in script_waypoint. Quest: %u).",
  302. - me->GetScriptName().c_str(), me->GetEntry(), quest ? quest->GetQuestId() : 0);
  303. - return;
  304. - }
  305. -
  306. //set variables
  307. m_bIsActiveAttacker = isActiveAttacker;
  308. m_bIsRunning = run;
  309. @@ -473,6 +529,9 @@ void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false
  310. m_bCanInstantRespawn = instantRespawn;
  311. m_bCanReturnToStart = canLoopPath;
  312. + if (!ScriptWP && resetWaypoints) // sd2 never adds wp in script, but tc does
  313. + FillPointMovementListForCreature();
  314. +
  315. if (m_bCanReturnToStart && m_bCanInstantRespawn)
  316. TC_LOG_DEBUG("scripts", "EscortAI is set to return home after waypoint end and instant respawn at waypoint end. Creature will never despawn.");
  317. @@ -491,9 +550,7 @@ void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false
  318. me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
  319. }
  320. - 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());
  321. -
  322. - CurrentWP = WaypointList.begin();
  323. + TC_LOG_DEBUG("scripts", "EscortAI started waypoints. ActiveAttacker = %d, Run = %d.", m_bIsActiveAttacker, m_bIsRunning);
  324. //Set initial speed
  325. if (m_bIsRunning)
  326. @@ -510,73 +567,14 @@ void npc_escortAI::SetEscortPaused(bool on)
  327. return;
  328. if (on)
  329. - AddEscortState(STATE_ESCORT_PAUSED);
  330. - else
  331. - RemoveEscortState(STATE_ESCORT_PAUSED);
  332. -}
  333. -
  334. -bool npc_escortAI::SetNextWaypoint(uint32 pointId, float x, float y, float z, float orientation)
  335. -{
  336. - me->UpdatePosition(x, y, z, orientation);
  337. - return SetNextWaypoint(pointId, false, true);
  338. -}
  339. -
  340. -bool npc_escortAI::SetNextWaypoint(uint32 pointId, bool setPosition, bool resetWaypointsOnFail)
  341. -{
  342. - if (!WaypointList.empty())
  343. - WaypointList.clear();
  344. -
  345. - FillPointMovementListForCreature();
  346. -
  347. - if (WaypointList.empty())
  348. - return false;
  349. -
  350. - size_t const size = WaypointList.size();
  351. - Escort_Waypoint waypoint(0, 0, 0, 0, 0);
  352. - do
  353. {
  354. - waypoint = WaypointList.front();
  355. - WaypointList.pop_front();
  356. - if (waypoint.id == pointId)
  357. - {
  358. - if (setPosition)
  359. - me->UpdatePosition(waypoint.x, waypoint.y, waypoint.z, me->GetOrientation());
  360. -
  361. - CurrentWP = WaypointList.begin();
  362. - return true;
  363. - }
  364. - }
  365. - while (!WaypointList.empty());
  366. -
  367. - // we failed.
  368. - // we reset the waypoints in the start; if we pulled any, reset it again
  369. - if (resetWaypointsOnFail && size != WaypointList.size())
  370. - {
  371. - if (!WaypointList.empty())
  372. - WaypointList.clear();
  373. -
  374. - FillPointMovementListForCreature();
  375. + AddEscortState(STATE_ESCORT_PAUSED);
  376. + me->StopMoving();
  377. }
  378. -
  379. - return false;
  380. -}
  381. -
  382. -bool npc_escortAI::GetWaypointPosition(uint32 pointId, float& x, float& y, float& z)
  383. -{
  384. - ScriptPointVector const& waypoints = sScriptSystemMgr->GetPointMoveList(me->GetEntry());
  385. - if (waypoints.empty())
  386. - return false;
  387. -
  388. - for (ScriptPointVector::const_iterator itr = waypoints.begin(); itr != waypoints.end(); ++itr)
  389. + else
  390. {
  391. - if (itr->uiPointId == pointId)
  392. - {
  393. - x = itr->fX;
  394. - y = itr->fY;
  395. - z = itr->fZ;
  396. - return true;
  397. - }
  398. + RemoveEscortState(STATE_ESCORT_PAUSED);
  399. + if (WaypointMovementGenerator<Creature>* move = (WaypointMovementGenerator<Creature>*)(me->GetMotionMaster()->top()))
  400. + move->GetTrackerTimer().Reset(1);
  401. }
  402. -
  403. - return false;
  404. }
  405. diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
  406. index 37a1464..92ca5fb 100644
  407. --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
  408. +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
  409. @@ -20,27 +20,11 @@
  410. #define SC_ESCORTAI_H
  411. #include "ScriptSystem.h"
  412. +#include "WaypointMovementGenerator.h"
  413. +#include "WaypointManager.h"
  414. #define DEFAULT_MAX_PLAYER_DISTANCE 50
  415. -struct Escort_Waypoint
  416. -{
  417. - Escort_Waypoint(uint32 _id, float _x, float _y, float _z, uint32 _w)
  418. - {
  419. - id = _id;
  420. - x = _x;
  421. - y = _y;
  422. - z = _z;
  423. - WaitTimeMs = _w;
  424. - }
  425. -
  426. - uint32 id;
  427. - float x;
  428. - float y;
  429. - float z;
  430. - uint32 WaitTimeMs;
  431. -};
  432. -
  433. enum eEscortState
  434. {
  435. STATE_ESCORT_NONE = 0x000, //nothing in progress
  436. @@ -76,15 +60,6 @@ struct TC_GAME_API npc_escortAI : public ScriptedAI
  437. // EscortAI functions
  438. void AddWaypoint(uint32 id, float x, float y, float z, uint32 waitTime = 0); // waitTime is in ms
  439. - //this will set the current position to x/y/z/o, and the current WP to pointId.
  440. - bool SetNextWaypoint(uint32 pointId, float x, float y, float z, float orientation);
  441. -
  442. - //this will set the current position to WP start position (if setPosition == true),
  443. - //and the current WP to pointId
  444. - bool SetNextWaypoint(uint32 pointId, bool setPosition = true, bool resetWaypointsOnFail = true);
  445. -
  446. - bool GetWaypointPosition(uint32 pointId, float& x, float& y, float& z);
  447. -
  448. virtual void WaypointReached(uint32 pointId) = 0;
  449. virtual void WaypointStart(uint32 /*pointId*/) { }
  450. @@ -120,17 +95,17 @@ struct TC_GAME_API npc_escortAI : public ScriptedAI
  451. uint32 m_uiWPWaitTimer;
  452. uint32 m_uiPlayerCheckTimer;
  453. uint32 m_uiEscortState;
  454. + uint32 LastWP;
  455. float MaxPlayerDistance;
  456. + WaypointPath::const_iterator CurrentWP;
  457. Quest const* m_pQuestForEscort; //generally passed in Start() when regular escort script.
  458. - std::list<Escort_Waypoint> WaypointList;
  459. - std::list<Escort_Waypoint>::iterator CurrentWP;
  460. -
  461. bool m_bIsActiveAttacker; //obsolete, determined by faction.
  462. bool m_bIsRunning; //all creatures are walking by default (has flag MOVEMENTFLAG_WALK)
  463. bool m_bCanInstantRespawn; //if creature should respawn instantly after escort over (if not, database respawntime are used)
  464. bool m_bCanReturnToStart; //if creature can walk same path (loop) without despawn. Not for regular escort quests.
  465. + bool m_bStarted;
  466. bool DespawnAtEnd;
  467. bool DespawnAtFar;
  468. bool ScriptWP;
  469. diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
  470. index 6f7dae1..3da90e8 100644
  471. --- a/src/server/game/Movement/MotionMaster.cpp
  472. +++ b/src/server/game/Movement/MotionMaster.cpp
  473. @@ -647,7 +647,7 @@ void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot)
  474. }
  475. }
  476. -void MotionMaster::MovePath(uint32 path_id, bool repeatable)
  477. +void MotionMaster::MovePath(int32 path_id, bool repeatable, bool loadFromDB /* = false*/)
  478. {
  479. if (!path_id)
  480. return;
  481. @@ -664,7 +664,7 @@ void MotionMaster::MovePath(uint32 path_id, bool repeatable)
  482. //_owner->GetTypeId() == TYPEID_PLAYER ?
  483. //Mutate(new WaypointMovementGenerator<Player>(path_id, repeatable)):
  484. - Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable), MOTION_SLOT_IDLE);
  485. + Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable, loadFromDB), MOTION_SLOT_IDLE);
  486. TC_LOG_DEBUG("misc", "%s (GUID: %u) starts moving over path(Id:%u, repeatable: %s).",
  487. _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature",
  488. diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
  489. index 005f10b..0bfb9c1 100644
  490. --- a/src/server/game/Movement/MotionMaster.h
  491. +++ b/src/server/game/Movement/MotionMaster.h
  492. @@ -200,7 +200,7 @@ class TC_GAME_API MotionMaster //: private std::stack<MovementGenerator *>
  493. void MoveSeekAssistanceDistract(uint32 timer);
  494. void MoveTaxiFlight(uint32 path, uint32 pathnode);
  495. void MoveDistract(uint32 time);
  496. - void MovePath(uint32 path_id, bool repeatable);
  497. + void MovePath(int32 path_id, bool repeatable, bool loadFromDB = true);
  498. void MoveRotate(uint32 time, RotateDirection direction);
  499. MovementGeneratorType GetCurrentMovementGeneratorType() const;
  500. diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
  501. index 2ffa1a6..de9cd1d 100755
  502. --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
  503. +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
  504. @@ -45,13 +45,13 @@ void WaypointMovementGenerator<Creature>::LoadPath(Creature* creature)
  505. return;
  506. }
  507. - StartMoveNow(creature);
  508. + if (!Stopped())
  509. + StartMoveNow(creature);
  510. }
  511. void WaypointMovementGenerator<Creature>::DoInitialize(Creature* creature)
  512. {
  513. LoadPath(creature);
  514. - creature->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
  515. }
  516. void WaypointMovementGenerator<Creature>::DoFinalize(Creature* creature)
  517. @@ -62,18 +62,14 @@ void WaypointMovementGenerator<Creature>::DoFinalize(Creature* creature)
  518. void WaypointMovementGenerator<Creature>::DoReset(Creature* creature)
  519. {
  520. - creature->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
  521. - StartMoveNow(creature);
  522. + if (!Stopped())
  523. + StartMoveNow(creature);
  524. }
  525. void WaypointMovementGenerator<Creature>::OnArrived(Creature* creature)
  526. {
  527. if (!i_path || i_path->empty())
  528. return;
  529. - if (m_isArrivalDone)
  530. - return;
  531. -
  532. - m_isArrivalDone = true;
  533. if (i_path->at(i_currentNode)->event_id && urand(0, 99) < i_path->at(i_currentNode)->event_chance)
  534. {
  535. @@ -82,14 +78,46 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature* creature)
  536. creature->GetMap()->ScriptsStart(sWaypointScripts, i_path->at(i_currentNode)->event_id, creature, NULL);
  537. }
  538. + if (i_path->at(i_currentNode)->delay)
  539. + {
  540. + creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
  541. + Stop(i_path->at(i_currentNode)->delay);
  542. + creature->StopMoving();
  543. + }
  544. +
  545. // Inform script
  546. MovementInform(creature);
  547. creature->UpdateWaypointID(i_currentNode);
  548. +}
  549. - if (i_path->at(i_currentNode)->delay)
  550. +void WaypointMovementGenerator<Creature>::FormationMove(Creature* creature)
  551. +{
  552. + bool transportPath = creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && creature->GetTransGUID();
  553. +
  554. + WaypointData const* node = i_path->at(i_currentNode);
  555. +
  556. + Movement::Location formationDest(node->x, node->y, node->z, 0.0f);
  557. +
  558. + //! If creature is on transport, we assume waypoints set in DB are already transport offsets
  559. + if (transportPath)
  560. + if (TransportBase* trans = creature->GetDirectTransport())
  561. + trans->CalculatePassengerPosition(formationDest.x, formationDest.y, formationDest.z, &formationDest.orientation);
  562. +
  563. + if (loadFromDB)
  564. {
  565. - creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
  566. - Stop(i_path->at(i_currentNode)->delay);
  567. + Movement::MoveSplineInit init(creature);
  568. + //! Accepts angles such as 0.00001 and -0.00001, 0 must be ignored, default value in waypoint table
  569. + if (node->orientation && node->delay)
  570. + init.SetFacing(node->orientation);
  571. + init.SetWalk(node->move_type == WAYPOINT_MOVE_TYPE_RUN ? true : false);
  572. + }
  573. +
  574. + //Call for creature group update
  575. + if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature)
  576. + {
  577. + if (loadFromDB)
  578. + creature->SetWalk(node->move_type == WAYPOINT_MOVE_TYPE_RUN ? true : false);
  579. + creature->GetFormation()->LeaderMoveTo(formationDest.x, formationDest.y, formationDest.z);
  580. }
  581. }
  582. @@ -98,8 +126,7 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
  583. if (!i_path || i_path->empty())
  584. return false;
  585. - if (Stopped())
  586. - return true;
  587. + next_currentNode = i_currentNode;
  588. bool transportPath = creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && creature->GetTransGUID();
  589. @@ -133,13 +160,14 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
  590. }
  591. i_currentNode = (i_currentNode+1) % i_path->size();
  592. + next_currentNode = 0;
  593. }
  594. WaypointData const* node = i_path->at(i_currentNode);
  595. m_isArrivalDone = false;
  596. - creature->AddUnitState(UNIT_STATE_ROAMING_MOVE);
  597. + creature->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
  598. Movement::Location formationDest(node->x, node->y, node->z, 0.0f);
  599. Movement::MoveSplineInit init(creature);
  600. @@ -152,30 +180,41 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
  601. trans->CalculatePassengerPosition(formationDest.x, formationDest.y, formationDest.z, &formationDest.orientation);
  602. }
  603. - //! Do not use formationDest here, MoveTo requires transport offsets due to DisableTransportPathTransformations() call
  604. - //! but formationDest contains global coordinates
  605. - init.MoveTo(node->x, node->y, node->z);
  606. + if (loadFromDB)
  607. + {
  608. + //! Accepts angles such as 0.00001 and -0.00001, 0 must be ignored, default value in waypoint table
  609. + if (node->orientation && node->delay)
  610. + init.SetFacing(node->orientation);
  611. - //! Accepts angles such as 0.00001 and -0.00001, 0 must be ignored, default value in waypoint table
  612. - if (node->orientation && node->delay)
  613. - init.SetFacing(node->orientation);
  614. + switch (node->move_type)
  615. + {
  616. + case WAYPOINT_MOVE_TYPE_LAND:
  617. + init.SetAnimation(Movement::ToGround);
  618. + break;
  619. + case WAYPOINT_MOVE_TYPE_TAKEOFF:
  620. + init.SetAnimation(Movement::ToFly);
  621. + break;
  622. + case WAYPOINT_MOVE_TYPE_RUN:
  623. + init.SetWalk(false);
  624. + break;
  625. + case WAYPOINT_MOVE_TYPE_WALK:
  626. + init.SetWalk(true);
  627. + break;
  628. + }
  629. + }
  630. - switch (node->move_type)
  631. + auto end = i_path->size();
  632. + Movement::PointsArray pathing;
  633. + pathing.push_back(G3D::Vector3(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ()));
  634. + for (auto i = i_currentNode; i < end; ++i)
  635. {
  636. - case WAYPOINT_MOVE_TYPE_LAND:
  637. - init.SetAnimation(Movement::ToGround);
  638. - break;
  639. - case WAYPOINT_MOVE_TYPE_TAKEOFF:
  640. - init.SetAnimation(Movement::ToFly);
  641. - break;
  642. - case WAYPOINT_MOVE_TYPE_RUN:
  643. - init.SetWalk(false);
  644. - break;
  645. - case WAYPOINT_MOVE_TYPE_WALK:
  646. - init.SetWalk(true);
  647. - break;
  648. + node = i_path->at(i);
  649. + pathing.push_back(G3D::Vector3(node->x, node->y, node->z));
  650. }
  651. + (creature->CanFly() || creature->IsFlying()) ? init.SetFly() : init.SetSmooth();
  652. + init.MovebyPath(pathing);
  653. +
  654. init.Launch();
  655. //Call for creature group update
  656. @@ -204,7 +243,7 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di
  657. if (Stopped())
  658. {
  659. if (CanMove(diff))
  660. - return StartMove(creature);
  661. + return StartMoveNow(creature);
  662. }
  663. else
  664. {
  665. @@ -213,15 +252,27 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di
  666. creature->SetHomePosition(creature->GetPosition());
  667. if (creature->IsStopped())
  668. - Stop(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER));
  669. + Stop(loadFromDB ? sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER) : 2 * HOUR * IN_MILLISECONDS);
  670. else if (creature->movespline->Finalized())
  671. {
  672. + m_isArrivalDone = true;
  673. OnArrived(creature);
  674. - return StartMove(creature);
  675. + return loadFromDB ? StartMove(creature) : true;
  676. + }
  677. + else
  678. + {
  679. + auto pointId = uint32(creature->movespline->currentPathIdx()) + next_currentNode;
  680. + if (pointId > i_currentNode)
  681. + {
  682. + OnArrived(creature);
  683. + i_currentNode = pointId;
  684. + FormationMove(creature);
  685. + return i_currentNode < (i_path->size() - 1);
  686. + }
  687. }
  688. }
  689. - return true;
  690. - }
  691. + return true;
  692. +}
  693. void WaypointMovementGenerator<Creature>::MovementInform(Creature* creature)
  694. {
  695. diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
  696. index 7230982..ddd45ae 100755
  697. --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
  698. +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
  699. @@ -37,7 +37,7 @@ template<class T, class P>
  700. class PathMovementBase
  701. {
  702. public:
  703. - PathMovementBase() : i_path(), i_currentNode(0) { }
  704. + PathMovementBase() : i_path(), i_currentNode(0), next_currentNode(0) { }
  705. virtual ~PathMovementBase() { };
  706. uint32 GetCurrentNode() const { return i_currentNode; }
  707. @@ -45,6 +45,7 @@ class PathMovementBase
  708. protected:
  709. P i_path;
  710. uint32 i_currentNode;
  711. + uint32 next_currentNode;
  712. };
  713. template<class T>
  714. @@ -55,8 +56,8 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Crea
  715. public PathMovementBase<Creature, WaypointPath const*>
  716. {
  717. public:
  718. - WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true)
  719. - : i_nextMoveTime(0), m_isArrivalDone(false), path_id(_path_id), repeating(_repeating) { }
  720. + WaypointMovementGenerator(int32 _path_id = 0, bool _repeating = true, bool _loadFromDB = true)
  721. + : i_nextMoveTime(0), m_isArrivalDone(false), path_id(_path_id), repeating(_repeating), loadFromDB(_loadFromDB) { }
  722. ~WaypointMovementGenerator() { i_path = NULL; }
  723. void DoInitialize(Creature*);
  724. void DoFinalize(Creature*);
  725. @@ -72,6 +73,8 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Crea
  726. bool GetResetPos(Creature*, float& x, float& y, float& z);
  727. + TimeTrackerSmall & GetTrackerTimer() { return i_nextMoveTime; }
  728. +
  729. private:
  730. void Stop(int32 time) { i_nextMoveTime.Reset(time);}
  731. @@ -87,16 +90,19 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Crea
  732. void OnArrived(Creature*);
  733. bool StartMove(Creature*);
  734. - void StartMoveNow(Creature* creature)
  735. + void FormationMove(Creature*);
  736. +
  737. + bool StartMoveNow(Creature* creature)
  738. {
  739. i_nextMoveTime.Reset(0);
  740. - StartMove(creature);
  741. + return StartMove(creature);
  742. }
  743. TimeTrackerSmall i_nextMoveTime;
  744. bool m_isArrivalDone;
  745. - uint32 path_id;
  746. + int32 path_id;
  747. bool repeating;
  748. + bool loadFromDB;
  749. };
  750. /** FlightPathMovementGenerator generates movement of the player for the paths
  751. diff --git a/src/server/game/Movement/Waypoints/WaypointManager.h b/src/server/game/Movement/Waypoints/WaypointManager.h
  752. index 63dc418..bd14f4f 100644
  753. --- a/src/server/game/Movement/Waypoints/WaypointManager.h
  754. +++ b/src/server/game/Movement/Waypoints/WaypointManager.h
  755. @@ -42,7 +42,7 @@ struct WaypointData
  756. };
  757. typedef std::vector<WaypointData*> WaypointPath;
  758. -typedef std::unordered_map<uint32, WaypointPath> WaypointPathContainer;
  759. +typedef std::unordered_map<int32, WaypointPath> WaypointPathContainer;
  760. class TC_GAME_API WaypointMgr
  761. {
  762. @@ -56,7 +56,7 @@ class TC_GAME_API WaypointMgr
  763. void Load();
  764. // Returns the path from a given id
  765. - WaypointPath const* GetPath(uint32 id) const
  766. + WaypointPath const* GetPath(int32 id) const
  767. {
  768. WaypointPathContainer::const_iterator itr = _waypointStore.find(id);
  769. if (itr != _waypointStore.end())
  770. @@ -65,11 +65,11 @@ class TC_GAME_API WaypointMgr
  771. return NULL;
  772. }
  773. + WaypointPathContainer _waypointStore;
  774. +
  775. private:
  776. WaypointMgr();
  777. ~WaypointMgr();
  778. -
  779. - WaypointPathContainer _waypointStore;
  780. };
  781. #define sWaypointMgr WaypointMgr::instance()
  782. --
  783. 1.9.5.msysgit.0