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>
68 lines
2.1 KiB
C#
68 lines
2.1 KiB
C#
using System.Numerics;
|
|
using AcDream.Core.Physics;
|
|
|
|
namespace AcDream.Core.Tests.Physics;
|
|
|
|
/// <summary>
|
|
/// Conformance coverage for retail
|
|
/// <c>ACCWeenieObject::ObjectsInRange @ 0x0058C1A0</c>. The external-container
|
|
/// registration passes <c>useRadii=true</c> and <c>ignoreZDelta=false</c> at
|
|
/// <c>gmExternalContainerUI::SetGroundObject @ 0x004CBBD0</c>.
|
|
/// </summary>
|
|
public sealed class ObjectRangeMathTests
|
|
{
|
|
[Fact]
|
|
public void ExternalContainerRange_UsesSurfaceGapRatherThanCenterDistance()
|
|
{
|
|
var player = new Vector3(7.01f, 98.06f, -0.45f);
|
|
var corpse = new Vector3(3.73f, 98.03f, -0.44f);
|
|
|
|
bool inRange = ObjectRangeMath.ObjectsInRange(
|
|
player, firstRadius: 0.48f, firstHeight: 1.835f,
|
|
corpse, secondRadius: 0.80f, secondHeight: 0.50f,
|
|
range: 2.01,
|
|
useRadii: true,
|
|
ignoreZDelta: false);
|
|
|
|
Assert.True(inRange);
|
|
}
|
|
|
|
[Fact]
|
|
public void CenterDistanceMode_DoesNotSubtractObjectRadii()
|
|
{
|
|
bool inRange = ObjectRangeMath.ObjectsInRange(
|
|
Vector3.Zero, firstRadius: 10f, firstHeight: 10f,
|
|
new Vector3(3f, 0f, 0f), secondRadius: 10f, secondHeight: 10f,
|
|
range: 2.0,
|
|
useRadii: false,
|
|
ignoreZDelta: false);
|
|
|
|
Assert.False(inRange);
|
|
}
|
|
|
|
[Fact]
|
|
public void IgnoreZDelta_UsesXyCenterDistanceAndTakesPrecedenceOverRadii()
|
|
{
|
|
bool inRange = ObjectRangeMath.ObjectsInRange(
|
|
Vector3.Zero, firstRadius: 100f, firstHeight: 100f,
|
|
new Vector3(3f, 4f, 1000f), secondRadius: 100f, secondHeight: 100f,
|
|
range: 5.0,
|
|
useRadii: true,
|
|
ignoreZDelta: true);
|
|
|
|
Assert.True(inRange);
|
|
}
|
|
|
|
[Fact]
|
|
public void RangeBoundary_IsInclusive()
|
|
{
|
|
bool inRange = ObjectRangeMath.ObjectsInRange(
|
|
Vector3.Zero, firstRadius: 0f, firstHeight: 0f,
|
|
new Vector3(3f, 4f, 0f), secondRadius: 0f, secondHeight: 0f,
|
|
range: 5.0,
|
|
useRadii: false,
|
|
ignoreZDelta: false);
|
|
|
|
Assert.True(inRange);
|
|
}
|
|
}
|