fix(B.6+B.7): arrival predicate uses safety margin INSIDE ACE's WithinUseRadius
Trace showed local arrival landing at 3.025 m from a target with
objDist=3.00. The previous arrival used ArrivalEpsilon=0.05 to
EXPAND the threshold (dist <= 3.05), so the body stopped right at
the boundary. ACE's server-side WithinUseRadius is strict
(dist <= radius), so 3.025 > 3.00 — ACE rejected the re-sent
action and looped back to MoveToObject. User had to manually
re-press R because auto-arrival kept landing just-outside-range.
Fix: walk INSIDE ACE's radius by a safety margin (0.3–0.5 m, capped
at 40 % of threshold so tight pickup radii like 0.6 m stay
reachable).
arrivalThreshold = wire's distanceToObject or minDistance
safetyMargin = min(0.5, arrivalThreshold * 0.4)
effectiveArrival = max(arrivalThreshold - safetyMargin, 0.1)
Examples:
objDist=3.00 (NPC) → walk to ≤2.50 m (ACE happy at 3.0)
objDist=2.00 (door) → walk to ≤1.50 m
objDist=0.60 (item) → walk to ≤0.36 m
objDist=0.50 (small) → walk to ≤0.30 m
Flee case (moveTowards=false) keeps its original predicate with
+ArrivalEpsilon — that's the boundary check semantics for fleeing
to a min-distance, not a max-distance use radius.
This commit is contained in:
parent
a0fa3d68a7
commit
39ff3a5505
1 changed files with 12 additions and 3 deletions
|
|
@ -445,15 +445,24 @@ public sealed class PlayerMovementController
|
||||||
float dy = _autoWalkDestination.Y - pos.Y;
|
float dy = _autoWalkDestination.Y - pos.Y;
|
||||||
float dist = MathF.Sqrt(dx * dx + dy * dy);
|
float dist = MathF.Sqrt(dx * dx + dy * dy);
|
||||||
|
|
||||||
// Arrival predicate (RemoteMoveToDriver convention; matches retail).
|
// Arrival predicate. CRITICAL: ACE's server-side WithinUseRadius
|
||||||
|
// is strict (dist <= radius), so arriving exactly at the radius
|
||||||
|
// boundary fails — ACE rejects the action and replies with
|
||||||
|
// another MoveToObject. To ensure the re-sent action lands
|
||||||
|
// INSIDE ACE's radius, we apply a safety margin that walks
|
||||||
|
// 0.3–0.5 m past the boundary (capped to 40 % of the threshold
|
||||||
|
// so tight pickup radii like 0.6 m stay reachable without
|
||||||
|
// collapsing to zero).
|
||||||
float arrivalThreshold = _autoWalkMoveTowards
|
float arrivalThreshold = _autoWalkMoveTowards
|
||||||
? _autoWalkDistanceToObject
|
? _autoWalkDistanceToObject
|
||||||
: _autoWalkMinDistance;
|
: _autoWalkMinDistance;
|
||||||
|
float safetyMargin = MathF.Min(0.5f, arrivalThreshold * 0.4f);
|
||||||
|
float effectiveArrival = MathF.Max(arrivalThreshold - safetyMargin, 0.1f);
|
||||||
bool arrived =
|
bool arrived =
|
||||||
(_autoWalkMoveTowards
|
(_autoWalkMoveTowards
|
||||||
&& dist <= arrivalThreshold + RemoteMoveToDriver.ArrivalEpsilon)
|
&& dist <= effectiveArrival)
|
||||||
|| (!_autoWalkMoveTowards
|
|| (!_autoWalkMoveTowards
|
||||||
&& dist >= arrivalThreshold - RemoteMoveToDriver.ArrivalEpsilon);
|
&& dist >= arrivalThreshold + RemoteMoveToDriver.ArrivalEpsilon);
|
||||||
if (arrived)
|
if (arrived)
|
||||||
{
|
{
|
||||||
EndServerAutoWalk("arrived");
|
EndServerAutoWalk("arrived");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue