diff options
| author | ccrs <ccrs@users.noreply.github.com> | 2017-08-12 01:40:25 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-08-12 01:40:25 +0200 |
| commit | 7fff83d67526efff63867d41b9e036a19a9287b3 (patch) | |
| tree | 0462cb16ac0099318ab9ce07dc6cc099e141375e /src/server/game/Movement | |
| parent | 00329fe9a505c437af0b7591d8321bf3b77ad7fb (diff) | |
Core/Movement: waypoint movement (#20121)
Following the work done in #19361 this is the cleanup and improvement of the related logic of waypoint management.
Ref 28050f3 #18020
(taking the good parts and ignoring the incomplete work)
Diffstat (limited to 'src/server/game/Movement')
10 files changed, 356 insertions, 266 deletions
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 003c9708628..c0450f97563 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -17,25 +17,28 @@ */ #include "MotionMaster.h" +#include "ConfusedMovementGenerator.h" #include "Creature.h" #include "CreatureAISelector.h" #include "DBCStores.h" -#include "Log.h" -#include "Map.h" -#include "PathGenerator.h" -#include "ScriptSystem.h" -#include "ConfusedMovementGenerator.h" #include "FleeingMovementGenerator.h" +#include "FormationMovementGenerator.h" #include "HomeMovementGenerator.h" #include "IdleMovementGenerator.h" +#include "Log.h" +#include "Map.h" +#include "MoveSpline.h" +#include "MoveSplineInit.h" +#include "PathGenerator.h" +#include "Player.h" #include "PointMovementGenerator.h" -#include "TargetedMovementGenerator.h" -#include "WaypointMovementGenerator.h" #include "RandomMovementGenerator.h" +#include "ScriptSystem.h" #include "SplineChainMovementGenerator.h" -#include "FormationMovementGenerator.h" -#include "MoveSpline.h" -#include "MoveSplineInit.h" +#include "TargetedMovementGenerator.h" +#include "Unit.h" +#include "WaypointDefines.h" +#include "WaypointMovementGenerator.h" inline MovementGenerator* GetIdleMovementGenerator() { @@ -672,16 +675,21 @@ void MotionMaster::MoveDistract(uint32 timer) Mutate(mgen, MOTION_SLOT_CONTROLLED); } -void MotionMaster::MovePath(uint32 path_id, bool repeatable) +void MotionMaster::MovePath(uint32 pathId, bool repeatable) { - if (!path_id) + if (!pathId) return; - Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable), MOTION_SLOT_IDLE); + Mutate(new WaypointMovementGenerator<Creature>(pathId, repeatable), MOTION_SLOT_IDLE); + + TC_LOG_DEBUG("misc", "%s (GUID: %u) starts moving over path(Id:%u, repeatable: %s).", _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature", _owner->GetGUID().GetCounter(), pathId, repeatable ? "YES" : "NO"); +} + +void MotionMaster::MovePath(WaypointPath& path, bool repeatable) +{ + Mutate(new WaypointMovementGenerator<Creature>(path, repeatable), MOTION_SLOT_IDLE); - TC_LOG_DEBUG("misc", "%s (GUID: %u) starts moving over path(Id:%u, repeatable: %s).", - _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature", - _owner->GetGUID().GetCounter(), path_id, repeatable ? "YES" : "NO"); + TC_LOG_DEBUG("misc", "%s (GUID: %u) start moving over path(repeatable: %s)", _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature", _owner->GetGUID().GetCounter(), repeatable ? "YES" : "NO"); } void MotionMaster::MoveRotate(uint32 time, RotateDirection direction) diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index d33739781b2..dcee98cdaaa 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -31,6 +31,7 @@ class Unit; class PathGenerator; struct SplineChainLink; struct SplineChainResumeInfo; +struct WaypointPath; // Creature Entry ID used for waypoints show, visible only for GMs #define VISUAL_WAYPOINT 1 @@ -61,9 +62,9 @@ enum MovementGeneratorType : uint8 MAX_MOTION_TYPE // limit }; -enum MovementSlot +enum MovementSlot : uint8 { - MOTION_SLOT_IDLE, + MOTION_SLOT_IDLE = 0, MOTION_SLOT_ACTIVE, MOTION_SLOT_CONTROLLED, MAX_MOTION_SLOT @@ -160,7 +161,8 @@ class TC_GAME_API MotionMaster void MoveSeekAssistanceDistract(uint32 timer); void MoveTaxiFlight(uint32 path, uint32 pathnode); void MoveDistract(uint32 time); - void MovePath(uint32 path_id, bool repeatable); + void MovePath(uint32 pathId, bool repeatable); + void MovePath(WaypointPath& path, bool repeatable); void MoveRotate(uint32 time, RotateDirection direction); void MoveFormation(uint32 id, Position destination, uint32 moveType, bool forceRun = false, bool forceOrientation = false); diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h index 8f75e3a2361..39b2a16cc8b 100755 --- a/src/server/game/Movement/MovementGenerator.h +++ b/src/server/game/Movement/MovementGenerator.h @@ -36,10 +36,11 @@ class TC_GAME_API MovementGenerator virtual void Finalize(Unit*) = 0; virtual void Reset(Unit*) = 0; virtual bool Update(Unit*, uint32 diff) = 0; - virtual MovementGeneratorType GetMovementGeneratorType() const = 0; virtual void UnitSpeedChanged() { } + virtual void Pause(uint32/* timer = 0*/) { } // timer in ms + virtual void Resume(uint32/* overrideTimer = 0*/) { } // timer in ms // used by Evade code for select point to evade with expected restart default movement virtual bool GetResetPosition(Unit*, float& /*x*/, float& /*y*/, float& /*z*/) { return false; } diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index a952421833d..7da90e2d515 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -18,7 +18,6 @@ #include "CreatureAI.h" #include "Creature.h" -#include "CreatureGroups.h" #include "Player.h" #include "MoveSplineInit.h" #include "MoveSpline.h" @@ -55,8 +54,7 @@ void PointMovementGenerator<T>::DoInitialize(T* owner) // Call for creature group update if (Creature* creature = owner->ToCreature()) - if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature) - creature->GetFormation()->LeaderMoveTo(Position(_x, _y, _z), _movementId); + creature->SignalFormationMovement(Position(_x, _y, _z), _movementId); } template<class T> @@ -90,8 +88,7 @@ bool PointMovementGenerator<T>::DoUpdate(T* owner, uint32 /*diff*/) // Call for creature group update if (Creature* creature = owner->ToCreature()) - if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature) - creature->GetFormation()->LeaderMoveTo(Position(_x, _y, _z), _movementId); + creature->SignalFormationMovement(Position(_x, _y, _z), _movementId); } return !owner->movespline->Finalized(); diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index 0a1972c0972..b2a9e5b83b9 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -18,7 +18,6 @@ #include "RandomMovementGenerator.h" #include "Creature.h" -#include "CreatureGroups.h" #include "Map.h" #include "MoveSplineInit.h" #include "MoveSpline.h" @@ -116,8 +115,7 @@ void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner) _timer.Reset(traveltime + resetTimer); // Call for creature group update - if (owner->GetFormation() && owner->GetFormation()->getLeader() == owner) - owner->GetFormation()->LeaderMoveTo(position); + owner->SignalFormationMovement(position); } template<class T> diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index f292c0a8091..3ca1d581982 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -17,99 +17,128 @@ */ #include "WaypointMovementGenerator.h" +#include "Creature.h" #include "CreatureAI.h" -#include "CreatureGroups.h" #include "Log.h" #include "MapManager.h" #include "MoveSpline.h" #include "MoveSplineInit.h" #include "ObjectMgr.h" +#include "Player.h" #include "Transport.h" +#include "WaypointDefines.h" +#include "WaypointManager.h" #include "World.h" +WaypointMovementGenerator<Creature>::WaypointMovementGenerator(WaypointPath& path, bool repeating) +{ + _path = &path; + _nextMoveTime = 0; + _recalculateSpeed = false; + _isArrivalDone = false; + _pathId = 0; + _repeating = repeating; + _loadedFromDB = false; + _stalled = false; +} + void WaypointMovementGenerator<Creature>::LoadPath(Creature* creature) { - if (!path_id) - path_id = creature->GetWaypointPath(); + if (_loadedFromDB) + { + if (!_pathId) + _pathId = creature->GetWaypointPath(); - i_path = sWaypointMgr->GetPath(path_id); + _path = sWaypointMgr->GetPath(_pathId); + } - if (!i_path) + if (!_path) { // No path id found for entry - TC_LOG_ERROR("sql.sql", "WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u DB GUID: %u) doesn't have waypoint path id: %u", creature->GetName().c_str(), creature->GetEntry(), creature->GetGUID().GetCounter(), creature->GetSpawnId(), path_id); + TC_LOG_ERROR("sql.sql", "WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u DB GUID: %u) doesn't have waypoint path id: %u", creature->GetName().c_str(), creature->GetEntry(), creature->GetGUID().GetCounter(), creature->GetSpawnId(), _pathId); return; } - StartMoveNow(creature); + _nextMoveTime.Reset(3000); + + if (CanMove(creature)) + 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) { - creature->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + creature->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); creature->SetWalk(false); } void WaypointMovementGenerator<Creature>::DoReset(Creature* creature) { - creature->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); - StartMoveNow(creature); + if (CanMove(creature)) + StartMoveNow(creature); } void WaypointMovementGenerator<Creature>::OnArrived(Creature* creature) { - if (!i_path || i_path->empty()) + if (!_path || _path->nodes.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) + WaypointNode const &waypoint = _path->nodes.at(_currentNode); + if (waypoint.delay) { - TC_LOG_DEBUG("maps.script", "Creature movement start script %u at point %u for %s.", i_path->at(i_currentNode)->event_id, i_currentNode, creature->GetGUID().ToString().c_str()); creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE); - creature->GetMap()->ScriptsStart(sWaypointScripts, i_path->at(i_currentNode)->event_id, creature, nullptr); + _nextMoveTime.Reset(waypoint.delay); } - // Inform script - MovementInform(creature); - creature->UpdateWaypointID(i_currentNode); - - if (i_path->at(i_currentNode)->delay) + if (waypoint.eventId && urand(0, 99) < waypoint.eventChance) { + TC_LOG_DEBUG("maps.script", "Creature movement start script %u at point %u for %s.", waypoint.eventId, _currentNode, creature->GetGUID().ToString().c_str()); creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE); - Stop(i_path->at(i_currentNode)->delay); + creature->GetMap()->ScriptsStart(sWaypointScripts, waypoint.eventId, creature, nullptr); + } + + // inform AI + if (creature->AI()) + { + creature->AI()->MovementInform(WAYPOINT_MOTION_TYPE, _currentNode); + + ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::OnArrived: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id); + creature->AI()->WaypointReached(_path->nodes[_currentNode].id, _path->id); } + + creature->UpdateWaypointID(_currentNode); } bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature) { - if (!i_path || i_path->empty()) + if (!creature || !creature->IsAlive()) return false; - // Dont allow dead creatures to move - if (!creature->IsAlive()) + if (!_path || _path->nodes.empty()) return false; - if (Stopped()) + // if the owner is the leader of its formation, check members status + if (creature->IsFormationLeader() && !creature->IsFormationLeaderMoveAllowed()) + { + _nextMoveTime.Reset(1000); return true; + } - bool transportPath = creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && creature->GetTransGUID(); + bool transportPath = creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && !creature->GetTransGUID().IsEmpty(); - if (m_isArrivalDone) + if (_isArrivalDone) { - if ((i_currentNode == i_path->size() - 1) && !repeating) // If that's our last waypoint + if ((_currentNode == _path->nodes.size() - 1) && !_repeating) // If that's our last waypoint { - float x = i_path->at(i_currentNode)->x; - float y = i_path->at(i_currentNode)->y; - float z = i_path->at(i_currentNode)->z; + WaypointNode const &waypoint = _path->nodes.at(_currentNode); + + float x = waypoint.x; + float y = waypoint.y; + float z = waypoint.z; float o = creature->GetOrientation(); if (!transportPath) @@ -127,21 +156,27 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature) transportPath = false; // else if (vehicle) - this should never happen, vehicle offsets are const } - - creature->GetMotionMaster()->Initialize(); return false; } - i_currentNode = (i_currentNode+1) % i_path->size(); + _currentNode = (_currentNode + 1) % _path->nodes.size(); + + // inform AI + if (creature->AI()) + { + ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::StartMove: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id); + creature->AI()->WaypointStarted(_path->nodes[_currentNode].id, _path->id); + } } - WaypointData const* node = i_path->at(i_currentNode); + WaypointNode const &waypoint = _path->nodes.at(_currentNode); + Position formationDest(waypoint.x, waypoint.y, waypoint.z, (waypoint.orientation && waypoint.delay) ? waypoint.orientation : 0.0f); - m_isArrivalDone = false; + _isArrivalDone = false; + _recalculateSpeed = false; creature->AddUnitState(UNIT_STATE_ROAMING_MOVE); - Position formationDest(node->x, node->y, node->z, (node->orientation && node->delay) ? node->orientation : 0.0f); Movement::MoveSplineInit init(creature); //! If creature is on transport, we assume waypoints set in DB are already transport offsets @@ -158,13 +193,13 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature) //! 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); + init.MoveTo(waypoint.x, waypoint.y, waypoint.z); //! 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); + if (waypoint.orientation && waypoint.delay) + init.SetFacing(waypoint.orientation); - switch (node->move_type) + switch (waypoint.moveType) { case WAYPOINT_MOVE_TYPE_LAND: init.SetAnimation(Movement::ToGround); @@ -178,47 +213,57 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature) case WAYPOINT_MOVE_TYPE_WALK: init.SetWalk(true); break; + default: + break; } init.Launch(); - // Call for creature group update - if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature) - creature->GetFormation()->LeaderMoveTo(formationDest, node->id, node->move_type, (node->orientation && node->delay) ? true : false); + // inform formation + creature->SignalFormationMovement(formationDest, waypoint.id, waypoint.moveType, (waypoint.orientation && waypoint.delay) ? true : false); return true; } bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 diff) { - // Waypoint movement can be switched on/off - // This is quite handy for escort quests and other stuff - if (creature->HasUnitState(UNIT_STATE_NOT_MOVE)) + if (!creature || !creature->IsAlive()) + return false; + + if (_stalled || creature->HasUnitState(UNIT_STATE_NOT_MOVE) || creature->IsMovementPreventedByCasting()) { - creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + creature->StopMoving(); return true; } + // prevent a crash at empty waypoint path. - if (!i_path || i_path->empty()) + if (!_path || _path->nodes.empty()) return false; - if (Stopped()) + if (!_nextMoveTime.Passed()) { - if (CanMove(diff)) - return StartMove(creature); + _nextMoveTime.Update(diff); + if (_nextMoveTime.Passed()) + return StartMoveNow(creature); } else { // Set home position at place on waypoint movement. - if (!creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) || !creature->GetTransGUID()) + if (!creature->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) || creature->GetTransGUID().IsEmpty()) creature->SetHomePosition(creature->GetPosition()); - if (creature->IsStopped()) - Stop(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER)); - else if (creature->movespline->Finalized()) + if (creature->movespline->Finalized()) { OnArrived(creature); - return StartMove(creature); + _isArrivalDone = true; + + if (_nextMoveTime.Passed()) + return StartMove(creature); + } + else if (_recalculateSpeed) + { + if (_nextMoveTime.Passed()) + StartMove(creature); } } return true; @@ -227,38 +272,61 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di void WaypointMovementGenerator<Creature>::MovementInform(Creature* creature) { if (creature->AI()) - creature->AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode); + creature->AI()->MovementInform(WAYPOINT_MOTION_TYPE, _currentNode); } bool WaypointMovementGenerator<Creature>::GetResetPos(Creature*, float& x, float& y, float& z) { // prevent a crash at empty waypoint path. - if (!i_path || i_path->empty()) + if (!_path || _path->nodes.empty()) return false; - WaypointData const* node = i_path->at(i_currentNode); - x = node->x; y = node->y; z = node->z; + WaypointNode const &waypoint = _path->nodes.at(_currentNode); + + x = waypoint.x; + y = waypoint.y; + z = waypoint.z; return true; } +void WaypointMovementGenerator<Creature>::Pause(uint32 timer/* = 0*/) +{ + _stalled = timer ? false : true; + _nextMoveTime.Reset(timer ? timer : 1); +} + +void WaypointMovementGenerator<Creature>::Resume(uint32 overrideTimer/* = 0*/) +{ + _stalled = false; + if (overrideTimer) + _nextMoveTime.Reset(overrideTimer); +} + +bool WaypointMovementGenerator<Creature>::CanMove(Creature* creature) +{ + return _nextMoveTime.Passed() && !creature->HasUnitState(UNIT_STATE_NOT_MOVE) && !creature->IsMovementPreventedByCasting(); +} //----------------------------------------------------// +#define FLIGHT_TRAVEL_UPDATE 100 +#define TIMEDIFF_NEXT_WP 250 +#define SKIP_SPLINE_POINT_DISTANCE_SQ (40.f * 40.f) +#define PLAYER_FLIGHT_SPEED 32.0f + uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const { - if (i_currentNode >= i_path.size()) - return i_path.size(); + if (_currentNode >= _path.size()) + return _path.size(); - uint32 curMapId = i_path[i_currentNode]->MapID; - for (uint32 i = i_currentNode; i < i_path.size(); ++i) - if (i_path[i]->MapID != curMapId) - return i; + uint32 curMapId = _path[_currentNode]->MapID; + for (uint32 itr = _currentNode; itr < _path.size(); ++itr) + if (_path[itr]->MapID != curMapId) + return itr; - return i_path.size(); + return _path.size(); } -#define SKIP_SPLINE_POINT_DISTANCE_SQ (40.0f * 40.0f) - bool IsNodeIncludedInShortenedPath(TaxiPathNodeEntry const* p1, TaxiPathNodeEntry const* p2) { return p1->MapID != p2->MapID || std::pow(p1->LocX - p2->LocX, 2) + std::pow(p1->LocY - p2->LocY, 2) > SKIP_SPLINE_POINT_DISTANCE_SQ; @@ -283,24 +351,24 @@ void FlightPathMovementGenerator::LoadPath(Player* player) bool passedPreviousSegmentProximityCheck = false; for (uint32 i = 0; i < nodes.size(); ++i) { - if (passedPreviousSegmentProximityCheck || !src || i_path.empty() || IsNodeIncludedInShortenedPath(i_path[i_path.size() - 1], nodes[i])) + if (passedPreviousSegmentProximityCheck || !src || _path.empty() || IsNodeIncludedInShortenedPath(_path[_path.size() - 1], nodes[i])) { if ((!src || (IsNodeIncludedInShortenedPath(start, nodes[i]) && i >= 2)) && (dst == taxi.size() - 1 || (IsNodeIncludedInShortenedPath(end, nodes[i]) && i < nodes.size() - 1))) { passedPreviousSegmentProximityCheck = true; - i_path.push_back(nodes[i]); + _path.push_back(nodes[i]); } } else { - i_path.pop_back(); + _path.pop_back(); --_pointsForPathSwitch.back().PathIndex; } } } - _pointsForPathSwitch.push_back({ uint32(i_path.size() - 1), int32(cost) }); + _pointsForPathSwitch.push_back({ uint32(_path.size() - 1), int32(cost) }); } } @@ -331,8 +399,6 @@ void FlightPathMovementGenerator::DoFinalize(Player* player) player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_TAXI_BENCHMARK); } -#define PLAYER_FLIGHT_SPEED 32.0f - void FlightPathMovementGenerator::DoReset(Player* player) { player->getHostileRefManager().setOnlineOfflineState(false); @@ -343,7 +409,7 @@ void FlightPathMovementGenerator::DoReset(Player* player) uint32 end = GetPathAtMapEnd(); for (uint32 i = GetCurrentNode(); i != end; ++i) { - G3D::Vector3 vertice(i_path[i]->LocX, i_path[i]->LocY, i_path[i]->LocZ); + G3D::Vector3 vertice(_path[i]->LocX, _path[i]->LocY, _path[i]->LocZ); init.Path().push_back(vertice); } init.SetFirstPointId(GetCurrentNode()); @@ -355,13 +421,13 @@ void FlightPathMovementGenerator::DoReset(Player* player) bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/) { uint32 pointId = (uint32)player->movespline->currentPathIdx(); - if (pointId > i_currentNode) + if (pointId > _currentNode) { bool departureEvent = true; do { - DoEventIfAny(player, i_path[i_currentNode], departureEvent); - while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= i_currentNode) + DoEventIfAny(player, _path[_currentNode], departureEvent); + while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= _currentNode) { _pointsForPathSwitch.pop_front(); player->m_taxi.NextTaxiDestination(); @@ -372,31 +438,31 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/) } } - if (pointId == i_currentNode) + if (pointId == _currentNode) break; - if (i_currentNode == _preloadTargetNode) + if (_currentNode == _preloadTargetNode) PreloadEndGrid(); - i_currentNode += (uint32)departureEvent; + _currentNode += departureEvent ? 1 : 0; departureEvent = !departureEvent; } while (true); } - return i_currentNode < (i_path.size() - 1); + return _currentNode < (_path.size() - 1); } void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() { - if (i_path.empty() || i_currentNode >= i_path.size()) + if (_path.empty() || _currentNode >= _path.size()) return; - uint32 map0 = i_path[i_currentNode]->MapID; - for (size_t i = i_currentNode + 1; i < i_path.size(); ++i) + uint32 map0 = _path[_currentNode]->MapID; + for (size_t i = _currentNode + 1; i < _path.size(); ++i) { - if (i_path[i]->MapID != map0) + if (_path[i]->MapID != map0) { - i_currentNode = i; + _currentNode = i; return; } } @@ -413,7 +479,7 @@ void FlightPathMovementGenerator::DoEventIfAny(Player* player, TaxiPathNodeEntry bool FlightPathMovementGenerator::GetResetPos(Player*, float& x, float& y, float& z) { - TaxiPathNodeEntry const* node = i_path[i_currentNode]; + TaxiPathNodeEntry const* node = _path[_currentNode]; x = node->LocX; y = node->LocY; z = node->LocZ; @@ -424,11 +490,11 @@ void FlightPathMovementGenerator::InitEndGridInfo() { /*! Storage to preload flightmaster grid at end of flight. For multi-stop flights, this will be reinitialized for each flightmaster at the end of each spline (or stop) in the flight. */ - uint32 nodeCount = i_path.size(); //! Number of nodes in path. - _endMapId = i_path[nodeCount - 1]->MapID; //! MapId of last node + uint32 nodeCount = _path.size(); //! Number of nodes in path. + _endMapId = _path[nodeCount - 1]->MapID; //! MapId of last node _preloadTargetNode = nodeCount - 3; - _endGridX = i_path[nodeCount - 1]->LocX; - _endGridY = i_path[nodeCount - 1]->LocY; + _endGridX = _path[nodeCount - 1]->LocX; + _endGridY = _path[nodeCount - 1]->LocY; } void FlightPathMovementGenerator::PreloadEndGrid() @@ -439,7 +505,7 @@ void FlightPathMovementGenerator::PreloadEndGrid() // Load the grid if (endMap) { - TC_LOG_DEBUG("misc", "Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path.size() - 1)); + TC_LOG_DEBUG("misc", "Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(_path.size() - 1)); endMap->LoadGrid(_endGridX, _endGridY); } else diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h index 7426a166ea1..2ea92f021da 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h @@ -19,98 +19,91 @@ #ifndef TRINITY_WAYPOINTMOVEMENTGENERATOR_H #define TRINITY_WAYPOINTMOVEMENTGENERATOR_H -/** @page PathMovementGenerator is used to generate movements +/** + * @page PathMovementGenerator is used to generate movements * of waypoints and flight paths. Each serves the purpose * of generate activities so that it generates updated * packets for the players. */ -#include "MovementGenerator.h" -#include "Creature.h" #include "DBCStructure.h" -#include "Player.h" +#include "MovementGenerator.h" #include "Timer.h" -#include "WaypointManager.h" -#define FLIGHT_TRAVEL_UPDATE 100 -#define TIMEDIFF_NEXT_WP 250 +class Creature; +class Player; +struct WaypointPath; -template<class T, class P> +template<class Entity, class BasePath> class PathMovementBase { public: - PathMovementBase() : i_path(), i_currentNode(0) { } + PathMovementBase() : _path(), _currentNode(0) { } virtual ~PathMovementBase() { }; - uint32 GetCurrentNode() const { return i_currentNode; } + uint32 GetCurrentNode() const { return _currentNode; } protected: - P i_path; - uint32 i_currentNode; + BasePath _path; + uint32 _currentNode; }; template<class T> class WaypointMovementGenerator; template<> -class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Creature, WaypointMovementGenerator<Creature> >, - public PathMovementBase<Creature, WaypointPath const*> +class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium<Creature, WaypointMovementGenerator<Creature>>, 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() { i_path = nullptr; } + explicit WaypointMovementGenerator(uint32 pathId = 0, bool repeating = true) : _nextMoveTime(0), _recalculateSpeed(false), _isArrivalDone(false), _pathId(pathId), _repeating(repeating), _loadedFromDB(true), _stalled(false) { } + explicit WaypointMovementGenerator(WaypointPath& path, bool repeating = true); + + ~WaypointMovementGenerator() { _path = nullptr; } + void DoInitialize(Creature*); void DoFinalize(Creature*); void DoReset(Creature*); bool DoUpdate(Creature*, uint32 diff); - void MovementInform(Creature*); - MovementGeneratorType GetMovementGeneratorType() const override { return WAYPOINT_MOTION_TYPE; } + void UnitSpeedChanged() override { _recalculateSpeed = true; } + void Pause(uint32 timer = 0) override; + void Resume(uint32 overrideTimer = 0) override; - // now path movement implmementation - void LoadPath(Creature*); + void MovementInform(Creature*); bool GetResetPos(Creature*, float& x, float& y, float& z); private: - - void Stop(int32 time) { i_nextMoveTime.Reset(time);} - - bool Stopped() { return !i_nextMoveTime.Passed();} - - bool CanMove(int32 diff) - { - i_nextMoveTime.Update(diff); - return i_nextMoveTime.Passed(); - } - + void LoadPath(Creature*); void OnArrived(Creature*); bool StartMove(Creature*); - - void StartMoveNow(Creature* creature) + bool CanMove(Creature*); + bool StartMoveNow(Creature* creature) { - i_nextMoveTime.Reset(0); - StartMove(creature); + _nextMoveTime.Reset(0); + return StartMove(creature); } - TimeTrackerSmall i_nextMoveTime; - bool m_isArrivalDone; - uint32 path_id; - bool repeating; + TimeTrackerSmall _nextMoveTime; + bool _recalculateSpeed; + bool _isArrivalDone; + uint32 _pathId; + bool _repeating; + bool _loadedFromDB; + bool _stalled; }; -/** FlightPathMovementGenerator generates movement of the player for the paths +/** + * FlightPathMovementGenerator generates movement of the player for the paths * and hence generates ground and activities for the player. */ -class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, FlightPathMovementGenerator >, - public PathMovementBase<Player, TaxiPathNodeList> +class FlightPathMovementGenerator : public MovementGeneratorMedium<Player, FlightPathMovementGenerator>, public PathMovementBase<Player, TaxiPathNodeList> { public: explicit FlightPathMovementGenerator(uint32 startNode = 0) { - i_currentNode = startNode; + _currentNode = startNode; _endGridX = 0.0f; _endGridY = 0.0f; _endMapId = 0; @@ -123,15 +116,14 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, Flig bool DoUpdate(Player*, uint32); MovementGeneratorType GetMovementGeneratorType() const override { return FLIGHT_MOTION_TYPE; } - TaxiPathNodeList const& GetPath() { return i_path; } + TaxiPathNodeList const& GetPath() { return _path; } uint32 GetPathAtMapEnd() const; - bool HasArrived() const { return (i_currentNode >= i_path.size()); } + bool HasArrived() const { return (_currentNode >= _path.size()); } void SetCurrentNodeAfterTeleport(); - void SkipCurrentNode() { ++i_currentNode; } + void SkipCurrentNode() { ++_currentNode; } void DoEventIfAny(Player* player, TaxiPathNodeEntry const* node, bool departure); bool GetResetPos(Player*, float& x, float& y, float& z); - void InitEndGridInfo(); void PreloadEndGrid(); diff --git a/src/server/game/Movement/Waypoints/WaypointDefines.h b/src/server/game/Movement/Waypoints/WaypointDefines.h new file mode 100644 index 00000000000..dbb7a15fa5c --- /dev/null +++ b/src/server/game/Movement/Waypoints/WaypointDefines.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_WAYPOINTDEFINES_H +#define TRINITY_WAYPOINTDEFINES_H + +#include "Define.h" +#include <vector> + +enum WaypointMoveType +{ + WAYPOINT_MOVE_TYPE_WALK, + WAYPOINT_MOVE_TYPE_RUN, + WAYPOINT_MOVE_TYPE_LAND, + WAYPOINT_MOVE_TYPE_TAKEOFF, + + WAYPOINT_MOVE_TYPE_MAX +}; + +struct WaypointNode +{ + WaypointNode() : id(0), x(0.f), y(0.f), z(0.f), orientation(0.f), delay(0), eventId(0), moveType(WAYPOINT_MOVE_TYPE_RUN), eventChance(0) { } + WaypointNode(uint32 _id, float _x, float _y, float _z, float _orientation = 0.f, uint32 _delay = 0) + { + id = _id; + x = _x; + y = _y; + z = _z; + orientation = _orientation; + delay = _delay; + eventId = 0; + moveType = WAYPOINT_MOVE_TYPE_WALK; + eventChance = 100; + } + + uint32 id; + float x, y, z, orientation; + uint32 delay; + uint32 eventId; + uint32 moveType; + uint8 eventChance; +}; + +struct WaypointPath +{ + WaypointPath() : id(0) { } + WaypointPath(uint32 _id, std::vector<WaypointNode>&& _nodes) + { + id = _id; + nodes = _nodes; + } + + std::vector<WaypointNode> nodes; + uint32 id; +}; + +#endif diff --git a/src/server/game/Movement/Waypoints/WaypointManager.cpp b/src/server/game/Movement/Waypoints/WaypointManager.cpp index 76c6228d302..3112459245f 100644 --- a/src/server/game/Movement/Waypoints/WaypointManager.cpp +++ b/src/server/game/Movement/Waypoints/WaypointManager.cpp @@ -16,27 +16,12 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "WaypointManager.h" #include "DatabaseEnv.h" #include "GridDefines.h" -#include "WaypointManager.h" #include "MapManager.h" #include "Log.h" -WaypointMgr::WaypointMgr() { } - -WaypointMgr::~WaypointMgr() -{ - for (WaypointPathContainer::iterator itr = _waypointStore.begin(); itr != _waypointStore.end(); ++itr) - { - for (WaypointPath::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it) - delete *it; - - itr->second.clear(); - } - - _waypointStore.clear(); -} - void WaypointMgr::Load() { uint32 oldMSTime = getMSTime(); @@ -55,11 +40,7 @@ void WaypointMgr::Load() do { Field* fields = result->Fetch(); - WaypointData* wp = new WaypointData(); - uint32 pathId = fields[0].GetUInt32(); - WaypointPath& path = _waypointStore[pathId]; - float x = fields[2].GetFloat(); float y = fields[3].GetFloat(); float z = fields[4].GetFloat(); @@ -68,25 +49,27 @@ void WaypointMgr::Load() Trinity::NormalizeMapCoord(x); Trinity::NormalizeMapCoord(y); - wp->id = fields[1].GetUInt32(); - wp->x = x; - wp->y = y; - wp->z = z; - wp->orientation = o; - wp->move_type = fields[6].GetUInt32(); + WaypointNode waypoint; + waypoint.id = fields[1].GetUInt32(); + waypoint.x = x; + waypoint.y = y; + waypoint.z = z; + waypoint.orientation = o; + waypoint.moveType = fields[6].GetUInt32(); - if (wp->move_type >= WAYPOINT_MOVE_TYPE_MAX) + if (waypoint.moveType >= WAYPOINT_MOVE_TYPE_MAX) { - TC_LOG_ERROR("sql.sql", "Waypoint %u in waypoint_data has invalid move_type, ignoring", wp->id); - delete wp; + TC_LOG_ERROR("sql.sql", "Waypoint %u in waypoint_data has invalid move_type, ignoring", waypoint.id); continue; } - wp->delay = fields[7].GetUInt32(); - wp->event_id = fields[8].GetUInt32(); - wp->event_chance = fields[9].GetInt16(); + waypoint.delay = fields[7].GetUInt32(); + waypoint.eventId = fields[8].GetUInt32(); + waypoint.eventChance = fields[9].GetInt16(); - path.push_back(wp); + WaypointPath& path = _waypointStore[pathId]; + path.id = pathId; + path.nodes.push_back(std::move(waypoint)); ++count; } while (result->NextRow()); @@ -102,14 +85,9 @@ WaypointMgr* WaypointMgr::instance() void WaypointMgr::ReloadPath(uint32 id) { - WaypointPathContainer::iterator itr = _waypointStore.find(id); + auto itr = _waypointStore.find(id); if (itr != _waypointStore.end()) - { - for (WaypointPath::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it) - delete *it; - _waypointStore.erase(itr); - } PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_BY_ID); @@ -120,13 +98,10 @@ void WaypointMgr::ReloadPath(uint32 id) if (!result) return; - WaypointPath& path = _waypointStore[id]; - + std::vector<WaypointNode> values; do { Field* fields = result->Fetch(); - WaypointData* wp = new WaypointData(); - float x = fields[1].GetFloat(); float y = fields[2].GetFloat(); float z = fields[3].GetFloat(); @@ -135,26 +110,36 @@ void WaypointMgr::ReloadPath(uint32 id) Trinity::NormalizeMapCoord(x); Trinity::NormalizeMapCoord(y); - wp->id = fields[0].GetUInt32(); - wp->x = x; - wp->y = y; - wp->z = z; - wp->orientation = o; - wp->move_type = fields[5].GetUInt32(); + WaypointNode waypoint; + waypoint.id = fields[0].GetUInt32(); + waypoint.x = x; + waypoint.y = y; + waypoint.z = z; + waypoint.orientation = o; + waypoint.moveType = fields[5].GetUInt32(); - if (wp->move_type >= WAYPOINT_MOVE_TYPE_MAX) + if (waypoint.moveType >= WAYPOINT_MOVE_TYPE_MAX) { - TC_LOG_ERROR("sql.sql", "Waypoint %u in waypoint_data has invalid move_type, ignoring", wp->id); - delete wp; + TC_LOG_ERROR("sql.sql", "Waypoint %u in waypoint_data has invalid move_type, ignoring", waypoint.id); continue; } - wp->delay = fields[6].GetUInt32(); - wp->event_id = fields[7].GetUInt32(); - wp->event_chance = fields[8].GetUInt8(); - - path.push_back(wp); + waypoint.delay = fields[6].GetUInt32(); + waypoint.eventId = fields[7].GetUInt32(); + waypoint.eventChance = fields[8].GetUInt8(); + values.push_back(std::move(waypoint)); } while (result->NextRow()); + + _waypointStore[id] = WaypointPath(id, std::move(values)); +} + +WaypointPath const* WaypointMgr::GetPath(uint32 id) const +{ + auto itr = _waypointStore.find(id); + if (itr != _waypointStore.end()) + return &itr->second; + + return nullptr; } diff --git a/src/server/game/Movement/Waypoints/WaypointManager.h b/src/server/game/Movement/Waypoints/WaypointManager.h index f62805594ef..769e45432e7 100644 --- a/src/server/game/Movement/Waypoints/WaypointManager.h +++ b/src/server/game/Movement/Waypoints/WaypointManager.h @@ -20,32 +20,10 @@ #define TRINITY_WAYPOINTMANAGER_H #include "Define.h" +#include "WaypointDefines.h" #include <vector> #include <unordered_map> -enum WaypointMoveType -{ - WAYPOINT_MOVE_TYPE_WALK, - WAYPOINT_MOVE_TYPE_RUN, - WAYPOINT_MOVE_TYPE_LAND, - WAYPOINT_MOVE_TYPE_TAKEOFF, - - WAYPOINT_MOVE_TYPE_MAX -}; - -struct WaypointData -{ - uint32 id; - float x, y, z, orientation; - uint32 delay; - uint32 event_id; - uint32 move_type; - uint8 event_chance; -}; - -typedef std::vector<WaypointData*> WaypointPath; -typedef std::unordered_map<uint32, WaypointPath> WaypointPathContainer; - class TC_GAME_API WaypointMgr { public: @@ -58,20 +36,12 @@ class TC_GAME_API WaypointMgr void Load(); // Returns the path from a given id - WaypointPath const* GetPath(uint32 id) const - { - WaypointPathContainer::const_iterator itr = _waypointStore.find(id); - if (itr != _waypointStore.end()) - return &itr->second; - - return nullptr; - } + WaypointPath const* GetPath(uint32 id) const; private: - WaypointMgr(); - ~WaypointMgr(); + WaypointMgr() { } - WaypointPathContainer _waypointStore; + std::unordered_map<uint32, WaypointPath> _waypointStore; }; #define sWaypointMgr WaypointMgr::instance() |
