diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 0801edecfd..aba6e2c7bf 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -28,6 +28,7 @@ #include "Log.h" #include "MoveSpline.h" #include "MoveSplineInit.h" +#include "Player.h" #include "PointMovementGenerator.h" #include "RandomMovementGenerator.h" #include "TargetedMovementGenerator.h" @@ -837,7 +838,17 @@ void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode) { LOG_DEBUG("movement.motionmaster", "{} taxi to (Path {} node {})", _owner->GetName(), path, pathnode); FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(pathnode); - mgen->LoadPath(_owner->ToPlayer()); + Player* player = _owner->ToPlayer(); + if (!mgen->LoadPath(player)) + { + LOG_ERROR("movement.motionmaster", "{} failed to build taxi path (Path {} node {}), clearing taxi destinations", + _owner->GetName(), path, pathnode); + player->m_taxi.ClearTaxiDestinations(); + player->Dismount(); + delete mgen; + return; + } + Mutate(mgen, MOTION_SLOT_CONTROLLED); } else diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index c40d5a0d02..27c2cc45be 100644 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -568,45 +568,56 @@ bool IsNodeIncludedInShortenedPath(TaxiPathNodeEntry const* p1, TaxiPathNodeEntr return p1->mapid != p2->mapid || std::pow(p1->x - p2->x, 2) + std::pow(p1->y - p2->y, 2) > SKIP_SPLINE_POINT_DISTANCE_SQ; } -void FlightPathMovementGenerator::LoadPath(Player* player) +bool FlightPathMovementGenerator::LoadPath(Player* player) { + i_path.clear(); _pointsForPathSwitch.clear(); + auto fail = [&]() + { + i_path.clear(); + _pointsForPathSwitch.clear(); + return false; + }; + std::deque const& taxi = player->m_taxi.GetPath(); float discount = player->GetReputationPriceDiscount(player->m_taxi.GetFlightMasterFactionTemplate()); for (uint32 src = 0, dst = 1; dst < taxi.size(); src = dst++) { uint32 path, cost; sObjectMgr->GetTaxiPath(taxi[src], taxi[dst], path, cost); - if (path > sTaxiPathNodesByPath.size()) - { - return; - } + if (path >= sTaxiPathNodesByPath.size()) + return fail(); TaxiPathNodeList const& nodes = sTaxiPathNodesByPath[path]; - if (!nodes.empty()) + if (nodes.empty()) + return fail(); + + TaxiPathNodeEntry const* start = nodes[0]; + TaxiPathNodeEntry const* end = nodes[nodes.size() - 1]; + bool passedPreviousSegmentProximityCheck = false; + bool addedPathNode = false; + for (uint32 i = 0; i < nodes.size(); ++i) { - TaxiPathNodeEntry const* start = nodes[0]; - TaxiPathNodeEntry const* end = nodes[nodes.size() - 1]; - 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 || i_path.empty() || IsNodeIncludedInShortenedPath(i_path[i_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))) { - 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]); - } - } - else - { - i_path.pop_back(); - --_pointsForPathSwitch.back().PathIndex; + passedPreviousSegmentProximityCheck = true; + i_path.push_back(nodes[i]); + addedPathNode = true; } } + else + { + i_path.pop_back(); + --_pointsForPathSwitch.back().PathIndex; + } } + if (!addedPathNode || i_path.empty()) + return fail(); + _pointsForPathSwitch.push_back({ uint32(i_path.size() - 1), int32(ceil(cost * discount)) }); } @@ -630,6 +641,11 @@ void FlightPathMovementGenerator::LoadPath(Player* player) else i_currentNode = 0; } + + if (i_path.empty()) + return fail(); + + return true; } void FlightPathMovementGenerator::DoInitialize(Player* player) diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h index 12479820a0..66fd141628 100644 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h @@ -108,7 +108,7 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, Flig _endMapId = 0; _preloadTargetNode = 0; } - void LoadPath(Player* player); + bool LoadPath(Player* player); void DoInitialize(Player*); void DoReset(Player*); void DoFinalize(Player*);