mirror of
https://gitcode.com/GitHub_Trending/az/azerothcore-wotlk.git
synced 2026-07-10 19:03:11 +00:00
fix(Core/Movement): guard empty taxi flight paths (#26468)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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<uint32> 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)
|
||||
|
||||
@@ -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*);
|
||||
|
||||
Reference in New Issue
Block a user