fix(combat): escape occupied login positions

Port retail's radius-aware placement ring so a relogging player is seated beside creatures occupying the saved location, and register the local body in the shared resolved-shadow pipeline. Route new forward movement and jump through AbortAutomaticAttack so repeat combat cancels immediately on movement.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-12 22:20:17 +02:00
parent e671b8a5c4
commit 00fe993f6f
11 changed files with 643 additions and 16 deletions

View file

@ -1325,4 +1325,47 @@ public sealed class PhysicsEngine
return resolveResult;
}
/// <summary>
/// Runs retail's radius-aware placement-ring search after the host has
/// validated the server's cell and grounded the initial position. This is
/// the <c>CTransition::find_placement_pos</c> half of enter-world
/// <c>SetPosition</c>; unlike an ordinary zero-distance transition it tests
/// object occupancy and can seat a relogging player beside a creature that
/// now occupies the saved location.
/// </summary>
public ResolveResult ResolvePlacement(
Vector3 position,
uint cellId,
float sphereRadius,
float sphereHeight,
float stepUpHeight,
float stepDownHeight,
ObjectInfoState moverFlags = ObjectInfoState.None,
uint movingEntityId = 0)
{
var transition = new Transition();
transition.ObjectInfo.StepUpHeight = stepUpHeight;
transition.ObjectInfo.StepDownHeight = stepDownHeight;
transition.ObjectInfo.StepDown = true;
transition.ObjectInfo.SelfEntityId = movingEntityId;
transition.ObjectInfo.State = moverFlags;
transition.SpherePath.InitPath(
position, position, cellId, sphereRadius, sphereHeight);
transition.SpherePath.InsertType = InsertType.Placement;
bool ok = transition.FindPlacementPos(this);
var sp = transition.SpherePath;
var ci = transition.CollisionInfo;
bool onGround = ci.ContactPlaneValid
|| transition.ObjectInfo.State.HasFlag(ObjectInfoState.OnWalkable);
return new ResolveResult(
sp.CurPos,
sp.CurCellId != 0 ? sp.CurCellId : cellId,
onGround,
ci.CollisionNormalValid,
ci.CollisionNormal,
ok);
}
}