Keep external-container visibility tied to the signed surface gap between the player and container physics cylinders, matching gmExternalContainerUI's authored UseRadius range watcher. This prevents a valid ViewContents response from being closed at ACE's natural approach endpoint. Port Position::cylinder_distance and ACCWeenieObject::ObjectsInRange into Core with conformance coverage for 3-D separation, overlap, mode precedence, and inclusive boundaries. Release build succeeds and all 5,895 tests pass with five intentional skips. Co-authored-by: OpenAI Codex <codex@openai.com>
53 lines
1.5 KiB
C#
53 lines
1.5 KiB
C#
using System.Numerics;
|
|
using AcDream.Core.Physics.Motion;
|
|
|
|
namespace AcDream.Core.Physics;
|
|
|
|
/// <summary>
|
|
/// Retail object-range predicate used by <c>CPlayerSystem</c> range handlers.
|
|
/// Port of <c>ACCWeenieObject::ObjectsInRange @ 0x0058C1A0</c>.
|
|
/// </summary>
|
|
public static class ObjectRangeMath
|
|
{
|
|
/// <summary>
|
|
/// Tests two live physics objects against a caller-supplied range. Retail
|
|
/// gives <paramref name="ignoreZDelta"/> precedence; otherwise
|
|
/// <paramref name="useRadii"/> selects cylinder-gap distance instead of
|
|
/// ordinary center distance.
|
|
/// </summary>
|
|
public static bool ObjectsInRange(
|
|
Vector3 firstPosition,
|
|
float firstRadius,
|
|
float firstHeight,
|
|
Vector3 secondPosition,
|
|
float secondRadius,
|
|
float secondHeight,
|
|
double range,
|
|
bool useRadii,
|
|
bool ignoreZDelta)
|
|
{
|
|
double distance;
|
|
if (ignoreZDelta)
|
|
{
|
|
double dx = secondPosition.X - firstPosition.X;
|
|
double dy = secondPosition.Y - firstPosition.Y;
|
|
distance = Math.Sqrt(dx * dx + dy * dy);
|
|
}
|
|
else if (useRadii)
|
|
{
|
|
distance = MoveToMath.CylinderDistance(
|
|
firstRadius,
|
|
firstHeight,
|
|
firstPosition,
|
|
secondRadius,
|
|
secondHeight,
|
|
secondPosition);
|
|
}
|
|
else
|
|
{
|
|
distance = Vector3.Distance(firstPosition, secondPosition);
|
|
}
|
|
|
|
return distance <= range;
|
|
}
|
|
}
|