fix(Core/Movement): guard empty taxi flight paths (#26468)
This commit is contained in:
@@ -28,6 +28,7 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "MoveSpline.h"
|
#include "MoveSpline.h"
|
||||||
#include "MoveSplineInit.h"
|
#include "MoveSplineInit.h"
|
||||||
|
#include "Player.h"
|
||||||
#include "PointMovementGenerator.h"
|
#include "PointMovementGenerator.h"
|
||||||
#include "RandomMovementGenerator.h"
|
#include "RandomMovementGenerator.h"
|
||||||
#include "TargetedMovementGenerator.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);
|
LOG_DEBUG("movement.motionmaster", "{} taxi to (Path {} node {})", _owner->GetName(), path, pathnode);
|
||||||
FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(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);
|
Mutate(mgen, MOTION_SLOT_CONTROLLED);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -568,26 +568,34 @@ 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;
|
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();
|
_pointsForPathSwitch.clear();
|
||||||
|
auto fail = [&]()
|
||||||
|
{
|
||||||
|
i_path.clear();
|
||||||
|
_pointsForPathSwitch.clear();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
std::deque<uint32> const& taxi = player->m_taxi.GetPath();
|
std::deque<uint32> const& taxi = player->m_taxi.GetPath();
|
||||||
float discount = player->GetReputationPriceDiscount(player->m_taxi.GetFlightMasterFactionTemplate());
|
float discount = player->GetReputationPriceDiscount(player->m_taxi.GetFlightMasterFactionTemplate());
|
||||||
for (uint32 src = 0, dst = 1; dst < taxi.size(); src = dst++)
|
for (uint32 src = 0, dst = 1; dst < taxi.size(); src = dst++)
|
||||||
{
|
{
|
||||||
uint32 path, cost;
|
uint32 path, cost;
|
||||||
sObjectMgr->GetTaxiPath(taxi[src], taxi[dst], path, cost);
|
sObjectMgr->GetTaxiPath(taxi[src], taxi[dst], path, cost);
|
||||||
if (path > sTaxiPathNodesByPath.size())
|
if (path >= sTaxiPathNodesByPath.size())
|
||||||
{
|
return fail();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TaxiPathNodeList const& nodes = sTaxiPathNodesByPath[path];
|
TaxiPathNodeList const& nodes = sTaxiPathNodesByPath[path];
|
||||||
if (!nodes.empty())
|
if (nodes.empty())
|
||||||
{
|
return fail();
|
||||||
|
|
||||||
TaxiPathNodeEntry const* start = nodes[0];
|
TaxiPathNodeEntry const* start = nodes[0];
|
||||||
TaxiPathNodeEntry const* end = nodes[nodes.size() - 1];
|
TaxiPathNodeEntry const* end = nodes[nodes.size() - 1];
|
||||||
bool passedPreviousSegmentProximityCheck = false;
|
bool passedPreviousSegmentProximityCheck = false;
|
||||||
|
bool addedPathNode = false;
|
||||||
for (uint32 i = 0; i < nodes.size(); ++i)
|
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]))
|
||||||
@@ -597,6 +605,7 @@ void FlightPathMovementGenerator::LoadPath(Player* player)
|
|||||||
{
|
{
|
||||||
passedPreviousSegmentProximityCheck = true;
|
passedPreviousSegmentProximityCheck = true;
|
||||||
i_path.push_back(nodes[i]);
|
i_path.push_back(nodes[i]);
|
||||||
|
addedPathNode = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -605,7 +614,9 @@ void FlightPathMovementGenerator::LoadPath(Player* player)
|
|||||||
--_pointsForPathSwitch.back().PathIndex;
|
--_pointsForPathSwitch.back().PathIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (!addedPathNode || i_path.empty())
|
||||||
|
return fail();
|
||||||
|
|
||||||
_pointsForPathSwitch.push_back({ uint32(i_path.size() - 1), int32(ceil(cost * discount)) });
|
_pointsForPathSwitch.push_back({ uint32(i_path.size() - 1), int32(ceil(cost * discount)) });
|
||||||
}
|
}
|
||||||
@@ -630,6 +641,11 @@ void FlightPathMovementGenerator::LoadPath(Player* player)
|
|||||||
else
|
else
|
||||||
i_currentNode = 0;
|
i_currentNode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i_path.empty())
|
||||||
|
return fail();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlightPathMovementGenerator::DoInitialize(Player* player)
|
void FlightPathMovementGenerator::DoInitialize(Player* player)
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, Flig
|
|||||||
_endMapId = 0;
|
_endMapId = 0;
|
||||||
_preloadTargetNode = 0;
|
_preloadTargetNode = 0;
|
||||||
}
|
}
|
||||||
void LoadPath(Player* player);
|
bool LoadPath(Player* player);
|
||||||
void DoInitialize(Player*);
|
void DoInitialize(Player*);
|
||||||
void DoReset(Player*);
|
void DoReset(Player*);
|
||||||
void DoFinalize(Player*);
|
void DoFinalize(Player*);
|
||||||
|
|||||||
Reference in New Issue
Block a user