mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
feat(Core/Travel): Port TravelPath::ClipPath; call from MoveFarTo, drop inline clip
This commit is contained in:
parent
37b518aafe
commit
f32ebb8f6b
@ -125,6 +125,12 @@ bool NewRpgBaseAction::MoveFarTo(WorldPosition dest)
|
|||||||
if (onTransport)
|
if (onTransport)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// ClipPath — truncate at first hostile creature in range / non-walkable
|
||||||
|
// hop / drifted past reactDistance / > 125 sqDist jump.
|
||||||
|
path.ClipPath(botAI, bot, false);
|
||||||
|
if (path.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
// Walk dispatch.
|
// Walk dispatch.
|
||||||
std::vector<WorldPosition> const& pts = path.getPointPath();
|
std::vector<WorldPosition> const& pts = path.getPointPath();
|
||||||
Movement::PointsArray points;
|
Movement::PointsArray points;
|
||||||
@ -164,42 +170,8 @@ bool NewRpgBaseAction::DispatchPathPoints(WorldPosition const& dest,
|
|||||||
for (auto& pt : points)
|
for (auto& pt : points)
|
||||||
bot->UpdateAllowedPositionZ(pt.x, pt.y, pt.z);
|
bot->UpdateAllowedPositionZ(pt.x, pt.y, pt.z);
|
||||||
|
|
||||||
// ClipPath — truncate path at first hostile creature within its
|
// ClipPath now runs at MoveFarTo level on the TravelPath before the
|
||||||
// own attack range. Skipped while in combat or dead.
|
// points array is built. No per-dispatch clip here.
|
||||||
if (botAI->GetState() != BOT_STATE_COMBAT && bot->IsAlive())
|
|
||||||
{
|
|
||||||
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
|
|
||||||
if (!targets.empty())
|
|
||||||
{
|
|
||||||
size_t clipAt = points.size();
|
|
||||||
for (size_t i = 0; i < points.size() && clipAt == points.size(); ++i)
|
|
||||||
{
|
|
||||||
for (ObjectGuid const& guid : targets)
|
|
||||||
{
|
|
||||||
Unit* unit = botAI->GetUnit(guid);
|
|
||||||
if (!unit || !unit->IsAlive())
|
|
||||||
continue;
|
|
||||||
Creature* cre = unit->ToCreature();
|
|
||||||
if (!cre)
|
|
||||||
continue;
|
|
||||||
if (unit->GetLevel() > bot->GetLevel() + 5)
|
|
||||||
continue;
|
|
||||||
float range = cre->GetAttackDistance(bot);
|
|
||||||
float dx = unit->GetPositionX() - points[i].x;
|
|
||||||
float dy = unit->GetPositionY() - points[i].y;
|
|
||||||
float dz = unit->GetPositionZ() - points[i].z;
|
|
||||||
if (dx * dx + dy * dy + dz * dz > range * range)
|
|
||||||
continue;
|
|
||||||
if (!unit->IsWithinLOSInMap(bot))
|
|
||||||
continue;
|
|
||||||
clipAt = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (clipAt < points.size() && clipAt + 1 < points.size())
|
|
||||||
points.erase(points.begin() + clipAt + 1, points.end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (points.size() < 2)
|
if (points.size() < 2)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -956,6 +956,75 @@ bool TravelPath::UpcommingSpecialMovement(WorldPosition startPos,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TravelPath::ClipPath(PlayerbotAI* ai, Unit* mover, bool ignoreEnemyTargets)
|
||||||
|
{
|
||||||
|
auto startP = getNextPoint(WorldPosition(mover), 0.0f, false);
|
||||||
|
cutTo(*startP, false);
|
||||||
|
|
||||||
|
if (startP == fullPath.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
GuidVector targets;
|
||||||
|
Player* bot = ai ? ai->GetBot() : nullptr;
|
||||||
|
if (bot && ai->GetState() != BOT_STATE_COMBAT && !bot->isDead() && !ignoreEnemyTargets)
|
||||||
|
targets = AI_VALUE(GuidVector, "possible targets");
|
||||||
|
|
||||||
|
auto endP = fullPath.end();
|
||||||
|
auto prevP = fullPath.begin();
|
||||||
|
float const reactSq = sPlayerbotAIConfig.reactDistance * sPlayerbotAIConfig.reactDistance;
|
||||||
|
|
||||||
|
for (auto p = fullPath.begin(); p != fullPath.end(); ++p)
|
||||||
|
{
|
||||||
|
// Hostile-target check: stop before walking into a mob that
|
||||||
|
// would aggro. Level-capped (mover->level + 5) so over-level
|
||||||
|
// mobs we'd avoid anyway are ignored.
|
||||||
|
for (ObjectGuid const& targetGuid : targets)
|
||||||
|
{
|
||||||
|
if (!targetGuid.IsCreature())
|
||||||
|
continue;
|
||||||
|
Unit* unit = ai->GetUnit(targetGuid);
|
||||||
|
if (!unit || unit->isDead())
|
||||||
|
continue;
|
||||||
|
if (unit->GetLevel() > mover->GetLevel() + 5)
|
||||||
|
continue;
|
||||||
|
Creature* cre = unit->ToCreature();
|
||||||
|
if (!cre)
|
||||||
|
continue;
|
||||||
|
float const range = cre->GetAttackDistance(mover);
|
||||||
|
if (WorldPosition(unit).sqDistance(p->point) > range * range)
|
||||||
|
continue;
|
||||||
|
if (!unit->IsHostileTo(mover) || !unit->IsWithinLOSInMap(mover))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
endP = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (endP != fullPath.end())
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Reject paths that drift past reactDistance from the start —
|
||||||
|
// a sign the path looped or wandered.
|
||||||
|
if (p->point.sqDistance(fullPath.begin()->point) > reactSq)
|
||||||
|
endP = p;
|
||||||
|
// Non-walkable hop in the middle (portal/transport/etc.) terminates.
|
||||||
|
else if (!p->isWalkable())
|
||||||
|
endP = p;
|
||||||
|
// Gap between adjacent points > ~11y (sqDist 125) — likely bad data.
|
||||||
|
else if (p->point.sqDistance(prevP->point) > 125.0f)
|
||||||
|
endP = prevP;
|
||||||
|
|
||||||
|
if (endP != fullPath.end())
|
||||||
|
break;
|
||||||
|
|
||||||
|
prevP = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endP == fullPath.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
fullPath.erase(std::next(endP), fullPath.end());
|
||||||
|
}
|
||||||
|
|
||||||
bool TravelPath::makeShortCut(WorldPosition startPos, float maxDist, Unit* bot)
|
bool TravelPath::makeShortCut(WorldPosition startPos, float maxDist, Unit* bot)
|
||||||
{
|
{
|
||||||
if (GetPath().empty())
|
if (GetPath().empty())
|
||||||
|
|||||||
@ -507,6 +507,13 @@ public:
|
|||||||
// dispatches the matching special-movement handler on the new head.
|
// dispatches the matching special-movement handler on the new head.
|
||||||
bool UpcommingSpecialMovement(WorldPosition startPos, float maxDist, bool onTransport);
|
bool UpcommingSpecialMovement(WorldPosition startPos, float maxDist, bool onTransport);
|
||||||
|
|
||||||
|
// Truncate the path at the first waypoint that would put the bot in
|
||||||
|
// range of a hostile creature (within attack range, in LOS, level-cap
|
||||||
|
// sane), at a non-walkable hop, after drifting beyond reactDistance
|
||||||
|
// from the start, or across a > 125-sqDist jump. Set ignoreEnemyTargets
|
||||||
|
// to suppress the hostile-target check (used by combat repositioning).
|
||||||
|
void ClipPath(PlayerbotAI* ai, Unit* mover, bool ignoreEnemyTargets = false);
|
||||||
|
|
||||||
// Reject paths the navmesh accepts but a player can't walk:
|
// Reject paths the navmesh accepts but a player can't walk:
|
||||||
// 2-point shortcut over 5y, or > 10y vertical drop with slope steeper than 2:1.
|
// 2-point shortcut over 5y, or > 10y vertical drop with slope steeper than 2:1.
|
||||||
static bool IsPathCheating(std::vector<WorldPosition> const& path,
|
static bool IsPathCheating(std::vector<WorldPosition> const& path,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user