diff --git a/src/server/game/AI/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp index ec22e9e4eba..17e03495593 100644 --- a/src/server/game/AI/CreatureAISelector.cpp +++ b/src/server/game/AI/CreatureAISelector.cpp @@ -131,12 +131,7 @@ namespace FactorySelector MovementGenerator* SelectMovementGenerator(Unit* unit) { - MovementGeneratorType type = unit->GetDefaultMovementType(); - if (Creature* creature = unit->ToCreature()) - if (!creature->GetPlayerMovingMe()) - type = creature->GetDefaultMovementType(); - - MovementGeneratorCreator const* mv_factory = sMovementGeneratorRegistry->GetRegistryItem(type); + MovementGeneratorCreator const* mv_factory = sMovementGeneratorRegistry->GetRegistryItem(unit->GetDefaultMovementType()); return ASSERT_NOTNULL(mv_factory)->Create(unit); } diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 8da8904b845..3ca8b75f929 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2973,6 +2973,14 @@ bool Creature::CanSwim() const return false; } +MovementGeneratorType Creature::GetDefaultMovementType() const +{ + if (!GetPlayerMovingMe()) + return m_defaultMovementType; + + return IDLE_MOTION_TYPE; +} + void Creature::AllLootRemovedFromCorpse() { time_t now = GameTime::GetGameTime(); diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index bab44b0740b..7cecf8e1d3e 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -160,7 +160,7 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma bool CanEnterWater() const override { return (CanSwim() || IsAmphibious()); }; bool CanFly() const override { return (IsFlying() || HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY)); } - MovementGeneratorType GetDefaultMovementType() const override { return m_defaultMovementType; } + MovementGeneratorType GetDefaultMovementType() const override; void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; } CreatureClassifications GetCreatureClassification() const { return GetCreatureTemplate()->Classification; } diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index d33e418c51f..bf2d2669d7d 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -803,10 +803,6 @@ void MotionMaster::MoveCharge(PathGenerator const& path, float speed /*= SPEED_C void MotionMaster::MoveKnockbackFrom(Position const& origin, float speedXY, float speedZ, float angle /*= M_PI*/, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/) { - // This function may make players fall below map - if (_owner->GetTypeId() == TYPEID_PLAYER) - return; - if (std::abs(speedXY) < 0.01f && std::abs(speedZ) < 0.01f) return; @@ -1144,8 +1140,13 @@ void MotionMaster::MovePath(uint32 pathId, bool repeatable, OptionalGetGUID(), pathId, repeatable ? "YES" : "NO"); - Add(new WaypointMovementGenerator(pathId, repeatable, duration, speed, speedSelectionMode, waitTimeRangeAtPathEnd, - wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, exactSplinePath, generatePath, std::move(scriptResult)), MOTION_SLOT_DEFAULT); + + if (_owner->GetTypeId() == TYPEID_UNIT) + Add(new WaypointMovementGenerator(pathId, repeatable, duration, speed, speedSelectionMode, waitTimeRangeAtPathEnd, + wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, exactSplinePath, generatePath, std::move(scriptResult)), MOTION_SLOT_DEFAULT); + else + Add(new WaypointMovementGenerator(pathId, repeatable, duration, speed, speedSelectionMode, waitTimeRangeAtPathEnd, + wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, exactSplinePath, generatePath, std::move(scriptResult)), MOTION_SLOT_DEFAULT); } void MotionMaster::MovePath(WaypointPath const& path, bool repeatable, Optional duration /*= {}*/, Optional speed /*= {}*/, @@ -1157,8 +1158,13 @@ void MotionMaster::MovePath(WaypointPath const& path, bool repeatable, Optional< { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePath: '{}', starts moving over path Id: {} (repeatable: {})", _owner->GetGUID(), path.Id, repeatable ? "YES" : "NO"); - Add(new WaypointMovementGenerator(path, repeatable, duration, speed, speedSelectionMode, waitTimeRangeAtPathEnd, - wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, exactSplinePath, generatePath, std::move(scriptResult)), MOTION_SLOT_DEFAULT); + + if (_owner->GetTypeId() == TYPEID_UNIT) + Add(new WaypointMovementGenerator(path, repeatable, duration, speed, speedSelectionMode, waitTimeRangeAtPathEnd, + wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, exactSplinePath, generatePath, std::move(scriptResult)), MOTION_SLOT_DEFAULT); + else + Add(new WaypointMovementGenerator(path, repeatable, duration, speed, speedSelectionMode, waitTimeRangeAtPathEnd, + wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, exactSplinePath, generatePath, std::move(scriptResult)), MOTION_SLOT_DEFAULT); } void MotionMaster::MoveRotate(uint32 id, RotateDirection direction, Optional time /*= {}*/, diff --git a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h index ada9c742781..82969b337ca 100644 --- a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h @@ -30,7 +30,7 @@ struct TaxiPathNodeEntry; * FlightPathMovementGenerator generates movement of the player for the paths * and hence generates ground and activities for the player. */ -class FlightPathMovementGenerator : public MovementGeneratorMedium, public PathMovementBase> +class FlightPathMovementGenerator : public MovementGeneratorMedium, public PathMovementBase> { public: explicit FlightPathMovementGenerator(Optional speed, diff --git a/src/server/game/Movement/MovementGenerators/PathMovementBase.h b/src/server/game/Movement/MovementGenerators/PathMovementBase.h index 7fe02bd100f..cdb2bdcbe20 100644 --- a/src/server/game/Movement/MovementGenerators/PathMovementBase.h +++ b/src/server/game/Movement/MovementGenerators/PathMovementBase.h @@ -21,7 +21,7 @@ #include "Define.h" #include -template +template class PathMovementBase { public: diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index 4bb6db88060..aacaca8c950 100644 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -25,6 +25,7 @@ #include "MoveSplineInit.h" #include "MovementDefines.h" #include "PathGenerator.h" +#include "Player.h" #include "Transport.h" #include "WaypointManager.h" #include @@ -34,72 +35,78 @@ namespace constexpr Milliseconds SEND_NEXT_POINT_EARLY_DELTA = 1500ms; } -WaypointMovementGenerator::WaypointMovementGenerator(uint32 pathId, bool repeating, Optional duration, Optional speed, +template +WaypointMovementGenerator::WaypointMovementGenerator(uint32 pathId, bool repeating, Optional duration, Optional speed, MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional> waitTimeRangeAtPathEnd, Optional wanderDistanceAtPathEnds, Optional followPathBackwardsFromEndToStart, Optional exactSplinePath, bool generatePath, Optional>&& scriptResult /*= {}*/) - : PathMovementBase(PathType(std::in_place_type)), _pathId(pathId), _speed(speed), _speedSelectionMode(speedSelectionMode), + : PathMovementBase(sWaypointMgr->GetPath(pathId)), _speed(speed), _speedSelectionMode(speedSelectionMode), _waitTimeRangeAtPathEnd(std::move(waitTimeRangeAtPathEnd)), _wanderDistanceAtPathEnds(wanderDistanceAtPathEnds), _followPathBackwardsFromEndToStart(followPathBackwardsFromEndToStart), _exactSplinePath(exactSplinePath), _repeating(repeating), _generatePath(generatePath), _moveTimer(0), _nextMoveTime(0), _waypointTransitionSplinePointsIndex(0), _isReturningToStart(false) { - Mode = MOTION_MODE_DEFAULT; - Priority = MOTION_PRIORITY_NORMAL; - Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; - BaseUnitState = UNIT_STATE_ROAMING; - ScriptResult = std::move(scriptResult); + this->Mode = MOTION_MODE_DEFAULT; + this->Priority = MOTION_PRIORITY_NORMAL; + this->Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + this->BaseUnitState = UNIT_STATE_ROAMING; + this->ScriptResult = std::move(scriptResult); if (duration) _duration.emplace(*duration); } -WaypointMovementGenerator::WaypointMovementGenerator(WaypointPath const& path, bool repeating, Optional duration, Optional speed, +template +WaypointMovementGenerator::WaypointMovementGenerator(WaypointPath const& path, bool repeating, Optional duration, Optional speed, MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional> waitTimeRangeAtPathEnd, Optional wanderDistanceAtPathEnds, Optional followPathBackwardsFromEndToStart, Optional exactSplinePath, bool generatePath, Optional>&& scriptResult /*= {}*/) - : PathMovementBase(std::make_unique(path)), _pathId(0), _speed(speed), _speedSelectionMode(speedSelectionMode), + : PathMovementBase(std::make_unique(path)), _speed(speed), _speedSelectionMode(speedSelectionMode), _waitTimeRangeAtPathEnd(std::move(waitTimeRangeAtPathEnd)), _wanderDistanceAtPathEnds(wanderDistanceAtPathEnds), _followPathBackwardsFromEndToStart(followPathBackwardsFromEndToStart), _exactSplinePath(exactSplinePath), _repeating(repeating), _generatePath(generatePath), _moveTimer(0), _nextMoveTime(0), _waypointTransitionSplinePointsIndex(0), _isReturningToStart(false) { - Mode = MOTION_MODE_DEFAULT; - Priority = MOTION_PRIORITY_NORMAL; - Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; - BaseUnitState = UNIT_STATE_ROAMING; - ScriptResult = std::move(scriptResult); + this->Mode = MOTION_MODE_DEFAULT; + this->Priority = MOTION_PRIORITY_NORMAL; + this->Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; + this->BaseUnitState = UNIT_STATE_ROAMING; + this->ScriptResult = std::move(scriptResult); if (duration) _duration.emplace(*duration); - std::get>(_path)->BuildSegments(); + std::get>(this->_path)->BuildSegments(); } -WaypointMovementGenerator::~WaypointMovementGenerator() = default; +template +WaypointMovementGenerator::~WaypointMovementGenerator() = default; -MovementGeneratorType WaypointMovementGenerator::GetMovementGeneratorType() const +template +MovementGeneratorType WaypointMovementGenerator::GetMovementGeneratorType() const { return WAYPOINT_MOTION_TYPE; } -void WaypointMovementGenerator::Pause(uint32 timer) +template +void WaypointMovementGenerator::Pause(uint32 timer) { if (timer) { // Don't try to paused an already paused generator - if (HasFlag(MOVEMENTGENERATOR_FLAG_PAUSED)) + if (this->HasFlag(MOVEMENTGENERATOR_FLAG_PAUSED)) return; - AddFlag(MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); + this->AddFlag(MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); _nextMoveTime.Reset(timer); - RemoveFlag(MOVEMENTGENERATOR_FLAG_PAUSED); + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_PAUSED); } else { - AddFlag(MOVEMENTGENERATOR_FLAG_PAUSED); + this->AddFlag(MOVEMENTGENERATOR_FLAG_PAUSED); _nextMoveTime.Reset(1); // Needed so that Update does not behave as if node was reached - RemoveFlag(MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); } } -void WaypointMovementGenerator::Resume(uint32 overrideTimer) +template +void WaypointMovementGenerator::Resume(uint32 overrideTimer) { if (overrideTimer) _nextMoveTime.Reset(overrideTimer); @@ -107,10 +114,11 @@ void WaypointMovementGenerator::Resume(uint32 overrideTimer) if (_nextMoveTime.Passed()) _nextMoveTime.Reset(1); // Needed so that Update does not behave as if node was reached - RemoveFlag(MOVEMENTGENERATOR_FLAG_PAUSED); + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_PAUSED); } -bool WaypointMovementGenerator::GetResetPosition(Unit* /*owner*/, float& x, float& y, float& z) +template +bool WaypointMovementGenerator::GetResetPosition(Unit* /*owner*/, float& x, float& y, float& z) { // prevent a crash at empty waypoint path. WaypointPath const* path = GetPath(); @@ -126,22 +134,15 @@ bool WaypointMovementGenerator::GetResetPosition(Unit* /*owner*/, floa return true; } -void WaypointMovementGenerator::DoInitialize(Creature* owner) +template +void WaypointMovementGenerator::DoInitialize(T* owner) { - RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING | MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); - - if (IsLoadedFromDB()) - { - if (!_pathId) - _pathId = owner->GetWaypointPathId(); - - _path = sWaypointMgr->GetPath(_pathId); - } + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING | MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); WaypointPath const* path = GetPath(); if (!path) { - TC_LOG_ERROR("sql.sql", "WaypointMovementGenerator::DoInitialize: couldn't load path for creature ({}) (_pathId: {})", owner->GetGUID(), _pathId); + TC_LOG_ERROR("sql.sql", "WaypointMovementGenerator::DoInitialize: couldn't load path for {}", owner->GetGUID()); return; } @@ -153,22 +154,24 @@ void WaypointMovementGenerator::DoInitialize(Creature* owner) _nextMoveTime.Reset(1000); } -void WaypointMovementGenerator::DoReset(Creature* owner) +template +void WaypointMovementGenerator::DoReset(T* owner) { - RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); owner->StopMoving(); - if (!HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED) && _nextMoveTime.Passed()) + if (!this->HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED) && _nextMoveTime.Passed()) _nextMoveTime.Reset(1); // Needed so that Update does not behave as if node was reached } -bool WaypointMovementGenerator::DoUpdate(Creature* owner, uint32 diff) +template +bool WaypointMovementGenerator::DoUpdate(T* owner, uint32 diff) { - if (!owner || !owner->IsAlive()) + if (!owner->IsAlive()) return true; - if (HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED | MOVEMENTGENERATOR_FLAG_PAUSED)) + if (this->HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED | MOVEMENTGENERATOR_FLAG_PAUSED)) return true; WaypointPath const* path = GetPath(); @@ -180,23 +183,25 @@ bool WaypointMovementGenerator::DoUpdate(Creature* owner, uint32 diff) _duration->Update(diff); if (_duration->Passed()) { - RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY); - AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); - AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); - owner->UpdateCurrentWaypointInfo(0, 0); - SetScriptResult(MovementStopReason::Finished); + if constexpr (std::is_base_of_v) + owner->UpdateCurrentWaypointInfo(0, 0); + + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY); + this->AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); + this->AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + this->SetScriptResult(MovementStopReason::Finished); return false; } } if (owner->HasUnitState(UNIT_STATE_NOT_MOVE | UNIT_STATE_LOST_CONTROL) || owner->IsMovementPreventedByCasting()) { - AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); + this->AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); owner->StopMoving(); return true; } - if (HasFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED)) + if (this->HasFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED)) { /* * relaunch only if @@ -208,21 +213,22 @@ bool WaypointMovementGenerator::DoUpdate(Creature* owner, uint32 diff) * * TODO: ((_nextMoveTime.Passed() && VALID_MOVEMENT) || (!_nextMoveTime.Passed() && !HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED))) */ - if (HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED) && (_nextMoveTime.Passed() || !HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED))) + if (this->HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED) && (_nextMoveTime.Passed() || !this->HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED))) { StartMove(owner, true); return true; } - RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); } // if it's moving if (!UpdateMoveTimer(diff) && !owner->movespline->Finalized()) { // set home position at place (every MotionMaster::UpdateMotion) - if (owner->GetTransGUID().IsEmpty()) - owner->SetHomePosition(owner->GetPosition()); + if constexpr (std::is_base_of_v) + if (owner->GetTransGUID().IsEmpty()) + owner->SetHomePosition(owner->GetPosition()); // handle switching points in continuous segments if (IsExactSplinePath()) @@ -233,25 +239,28 @@ bool WaypointMovementGenerator::DoUpdate(Creature* owner, uint32 diff) OnArrived(owner); ++_waypointTransitionSplinePointsIndex; if (ComputeNextNode()) - if (CreatureAI* ai = owner->AI()) - ai->WaypointStarted(path->Nodes[_currentNode].Id, path->Id); + { + if constexpr (std::is_base_of_v) + if (CreatureAI* ai = owner->AI()) + ai->WaypointStarted(path->Nodes[_currentNode].Id, path->Id); + } } } // relaunch movement if its speed has changed - if (HasFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING)) + if (this->HasFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING)) StartMove(owner, true); } else if (!_nextMoveTime.Passed()) // it's not moving, is there a timer? { if (UpdateWaitTimer(diff)) { - if (!HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED)) // initial movement call + if (!this->HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED)) // initial movement call { StartMove(owner); return true; } - else if (!HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) // timer set before node was reached, resume now + else if (!this->HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) // timer set before node was reached, resume now { StartMove(owner, true); return true; @@ -262,10 +271,10 @@ bool WaypointMovementGenerator::DoUpdate(Creature* owner, uint32 diff) } else // not moving, no timer { - if (HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED) && !HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) + if (this->HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED) && !this->HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) { OnArrived(owner); // hooks and wait timer reset (if necessary) - AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); // signals to future StartMove that it reached a node + this->AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); // signals to future StartMove that it reached a node } if (_nextMoveTime.Passed()) // OnArrived might have set a timer @@ -275,27 +284,36 @@ bool WaypointMovementGenerator::DoUpdate(Creature* owner, uint32 diff) return true; } -void WaypointMovementGenerator::DoDeactivate(Creature* owner) +template +void WaypointMovementGenerator::DoDeactivate(T* owner) { - AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + this->AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); } -void WaypointMovementGenerator::DoFinalize(Creature* owner, bool active, bool movementInform) +template +void WaypointMovementGenerator::DoFinalize(T* owner, bool active, bool movementInform) { - AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + this->AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); if (active) { owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); // TODO: Research if this modification is needed, which most likely isnt - owner->SetWalk(false); + if constexpr (std::is_base_of_v) + owner->SetWalk(false); } if (movementInform) - SetScriptResult(MovementStopReason::Finished); + this->SetScriptResult(MovementStopReason::Finished); } +template +void WaypointMovementGenerator::MovementInform(T const* /*owner*/) const +{ +} + +template <> void WaypointMovementGenerator::MovementInform(Creature const* owner) const { WaypointPath const* path = GetPath(); @@ -307,7 +325,8 @@ void WaypointMovementGenerator::MovementInform(Creature const* owner) } } -void WaypointMovementGenerator::OnArrived(Creature* owner) +template +void WaypointMovementGenerator::OnArrived(T* owner) { WaypointPath const* path = GetPath(); if (!path || path->Nodes.empty()) @@ -331,14 +350,15 @@ void WaypointMovementGenerator::OnArrived(Creature* owner) _duration->Update(waitTime); // count the random movement time as part of waypoing movement action if (_wanderDistanceAtPathEnds) - owner->GetMotionMaster()->MoveRandom(*_wanderDistanceAtPathEnds, waitTime, MOTION_SLOT_ACTIVE); + owner->GetMotionMaster()->MoveRandom(*_wanderDistanceAtPathEnds, waitTime, _speed, _speedSelectionMode, MOTION_SLOT_ACTIVE); else _nextMoveTime.Reset(waitTime); } MovementInform(owner); - owner->UpdateCurrentWaypointInfo(waypoint.Id, path->Id); + if constexpr (std::is_base_of_v) + owner->UpdateCurrentWaypointInfo(waypoint.Id, path->Id); } namespace @@ -441,73 +461,91 @@ void CreateMergedPath(Unit const* owner, WaypointPath const* path, uint32 previo } } -void WaypointMovementGenerator::StartMove(Creature* owner, bool relaunch/* = false*/) +template +void WaypointMovementGenerator::StartMove(T* owner, bool relaunch/* = false*/) { // sanity checks - if (!owner || !owner->IsAlive() || HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED) || (relaunch && (HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED) || !HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED)))) + if (!owner->IsAlive() || this->HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED) + || (relaunch && (this->HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED) || !this->HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED)))) return; WaypointPath const* path = GetPath(); if (!path || path->Nodes.empty()) return; - if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting() || (owner->IsFormationLeader() && !owner->IsFormationLeaderMoveAllowed())) // if cannot move OR cannot move because of formation + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) // if cannot move { _nextMoveTime.Reset(1000); // delay 1s return; } + if constexpr (std::is_base_of_v) + { + if (owner->IsFormationLeader() && !owner->IsFormationLeaderMoveAllowed()) // if cannot move because of formation + { + _nextMoveTime.Reset(1000); // delay 1s + return; + } + } + bool const transportPath = !owner->GetTransGUID().IsEmpty(); uint32 previousNode = _currentNode; - if (HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED) && HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED)) + if (this->HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED) && this->HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED)) { if (ComputeNextNode()) { ASSERT(_currentNode < path->Nodes.size(), "WaypointMovementGenerator::StartMove: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, path->Id); // inform AI - if (CreatureAI* AI = owner->AI()) - AI->WaypointStarted(path->Nodes[_currentNode].Id, path->Id); + if constexpr (std::is_base_of_v) + if (CreatureAI* AI = owner->AI()) + AI->WaypointStarted(path->Nodes[_currentNode].Id, path->Id); } else { - WaypointNode const& waypoint = path->Nodes[_currentNode]; - float x = waypoint.X; - float y = waypoint.Y; - float z = waypoint.Z; - float o = owner->GetOrientation(); + this->AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); - if (!transportPath) - owner->SetHomePosition(x, y, z, o); - else + if constexpr (std::is_base_of_v) { - if (TransportBase* trans = owner->GetTransport()) + owner->UpdateCurrentWaypointInfo(0, 0); + + WaypointNode const& waypoint = path->Nodes[_currentNode]; + float x = waypoint.X; + float y = waypoint.Y; + float z = waypoint.Z; + float o = owner->GetOrientation(); + + if (!transportPath) + owner->SetHomePosition(x, y, z, o); + else { - o -= trans->GetTransportOrientation(); - owner->SetTransportHomePosition(x, y, z, o); - owner->SetHomePosition(trans->GetPositionWithOffset(owner->GetTransportHomePosition())); + if (TransportBase* trans = owner->GetTransport()) + { + o -= trans->GetTransportOrientation(); + owner->SetTransportHomePosition(x, y, z, o); + owner->SetHomePosition(trans->GetPositionWithOffset(owner->GetTransportHomePosition())); + } + // else if (vehicle) - this should never happen, vehicle offsets are const } - // else if (vehicle) - this should never happen, vehicle offsets are const + + // inform AI + if (CreatureAI* AI = owner->AI()) + AI->WaypointPathEnded(waypoint.Id, path->Id); } - AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); - owner->UpdateCurrentWaypointInfo(0, 0); - // inform AI - if (CreatureAI* AI = owner->AI()) - AI->WaypointPathEnded(waypoint.Id, path->Id); - - SetScriptResult(MovementStopReason::Finished); + this->SetScriptResult(MovementStopReason::Finished); return; } } - else if (!HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED)) + else if (!this->HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED)) { - AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); + this->AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); // inform AI - if (CreatureAI* AI = owner->AI()) - AI->WaypointStarted(path->Nodes[_currentNode].Id, path->Id); + if constexpr (std::is_base_of_v) + if (CreatureAI* AI = owner->AI()) + AI->WaypointStarted(path->Nodes[_currentNode].Id, path->Id); } ASSERT(_currentNode < path->Nodes.size(), "WaypointMovementGenerator::StartMove: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, path->Id); @@ -524,7 +562,7 @@ void WaypointMovementGenerator::StartMove(Creature* owner, bool relaun _waypointTransitionSplinePointsIndex = 0; - RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_INFORM_ENABLED | MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_INFORM_ENABLED | MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); @@ -613,10 +651,12 @@ void WaypointMovementGenerator::StartMove(Creature* owner, bool relaun _moveTimer.Reset(duration); // inform formation - owner->SignalFormationMovement(); + if constexpr (std::is_base_of_v) + owner->SignalFormationMovement(); } -bool WaypointMovementGenerator::ComputeNextNode() +template +bool WaypointMovementGenerator::ComputeNextNode() { WaypointPath const* path = GetPath(); if ((_currentNode == path->Nodes.size() - 1) && !_repeating) @@ -647,7 +687,8 @@ bool WaypointMovementGenerator::ComputeNextNode() return true; } -bool WaypointMovementGenerator::IsFollowingPathBackwardsFromEndToStart() const +template +bool WaypointMovementGenerator::IsFollowingPathBackwardsFromEndToStart() const { if (_followPathBackwardsFromEndToStart) return *_followPathBackwardsFromEndToStart; @@ -655,7 +696,8 @@ bool WaypointMovementGenerator::IsFollowingPathBackwardsFromEndToStart return GetPath()->Flags.HasFlag(WaypointPathFlags::FollowPathBackwardsFromEndToStart); } -bool WaypointMovementGenerator::IsExactSplinePath() const +template +bool WaypointMovementGenerator::IsExactSplinePath() const { if (_exactSplinePath) return *_exactSplinePath; @@ -663,7 +705,8 @@ bool WaypointMovementGenerator::IsExactSplinePath() const return GetPath()->Flags.HasFlag(WaypointPathFlags::ExactSplinePath); } -bool WaypointMovementGenerator::IsCyclic() const +template +bool WaypointMovementGenerator::IsCyclic() const { return !IsFollowingPathBackwardsFromEndToStart() && IsExactSplinePath() @@ -671,14 +714,18 @@ bool WaypointMovementGenerator::IsCyclic() const && GetPath()->ContinuousSegments.size() == 1; } -std::string WaypointMovementGenerator::GetDebugInfo() const +template +std::string WaypointMovementGenerator::GetDebugInfo() const { return Trinity::StringFormat("{}\n{}", PathMovementBase::GetDebugInfo(), - MovementGeneratorMedium::GetDebugInfo()); + MovementGeneratorMedium::GetDebugInfo()); } -MovementGenerator* WaypointMovementFactory::Create(Unit* /*object*/) const +MovementGenerator* WaypointMovementFactory::Create(Unit* object) const { - return new WaypointMovementGenerator(0, true); + return new WaypointMovementGenerator(object->ToCreature()->GetWaypointPathId(), true); } + +template class WaypointMovementGenerator; +template class WaypointMovementGenerator; diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h index fb981f400cd..217687e12fb 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h @@ -24,15 +24,11 @@ #include "WaypointDefines.h" #include -class Creature; class Unit; -template -class WaypointMovementGenerator; - -template<> -class WaypointMovementGenerator : public MovementGeneratorMedium>, - public PathMovementBase>> +template +class WaypointMovementGenerator : public MovementGeneratorMedium>, + public PathMovementBase>> { public: explicit WaypointMovementGenerator(uint32 pathId, bool repeating, Optional duration = {}, Optional speed = {}, @@ -49,25 +45,25 @@ class WaypointMovementGenerator : public MovementGeneratorMediumAddFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING); } void Pause(uint32 timer) override; void Resume(uint32 overrideTimer) override; bool GetResetPosition(Unit*, float& x, float& y, float& z) override; - void DoInitialize(Creature*); - void DoReset(Creature*); - bool DoUpdate(Creature*, uint32); - void DoDeactivate(Creature*); - void DoFinalize(Creature*, bool, bool); + void DoInitialize(T* owner); + void DoReset(T* owner); + bool DoUpdate(T* owner, uint32 diff); + void DoDeactivate(T* owner); + void DoFinalize(T* owner, bool active, bool movementInform); WaypointPath const* GetPath() const { return std::visit([](auto&& path) -> WaypointPath const* { return std::addressof(*path); }, _path); } std::string GetDebugInfo() const override; private: - void MovementInform(Creature const*) const; - void OnArrived(Creature*); - void StartMove(Creature*, bool relaunch = false); + void MovementInform(T const* owner) const; + void OnArrived(T* owner); + void StartMove(T* owner, bool relaunch = false); bool ComputeNextNode(); bool UpdateMoveTimer(uint32 diff) { return UpdateTimer(_moveTimer, diff); } bool UpdateWaitTimer(uint32 diff) { return UpdateTimer(_nextMoveTime, diff); } @@ -88,7 +84,6 @@ class WaypointMovementGenerator : public MovementGeneratorMedium(_path); } - uint32 _pathId; Optional _duration; Optional _speed; MovementWalkRunSpeedSelectionMode _speedSelectionMode; diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp index 1e60b0fb7dd..06384f77b62 100644 --- a/src/server/scripts/Commands/cs_wp.cpp +++ b/src/server/scripts/Commands/cs_wp.cpp @@ -171,7 +171,7 @@ public: return false; } - if (!pathid) + if (!pathid || !sWaypointMgr->GetPath(pathid)) { handler->PSendSysMessage("%s%s|r", "|cffff33ff", "No valid path number provided."); return true; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 817dbb1e393..e06c49c656b 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -782,7 +782,7 @@ class boss_flame_leviathan_overload_device : public CreatureScript if (Unit* player = me->GetVehicle()->GetPassenger(SEAT_PLAYER)) { me->GetVehicleBase()->CastSpell(player, SPELL_SMOKE_TRAIL, true); - player->GetMotionMaster()->MoveKnockbackFrom(me->GetVehicleBase()->GetPosition(), 30, 30); + player->KnockbackFrom(me->GetVehicleBase()->GetPosition(), 30, 30); player->ExitVehicle(); } }