Improve horizontal distance calculations for interaction targeting

This commit is contained in:
2026-04-27 15:21:09 +02:00
parent 7cc6fb9ad6
commit 0857b83a09

View File

@@ -136,6 +136,15 @@ function distanceBetweenVec3(left: Vec3, right: Vec3): number {
return Math.sqrt(lengthSquaredVec3(subtractVec3(left, right)));
}
function distanceBetweenVec2(
left: { x: number; y: number },
right: { x: number; y: number }
): number {
const dx = left.x - right.x;
const dy = left.y - right.y;
return Math.sqrt(dx * dx + dy * dy);
}
function normalizeVec3(vector: Vec3): Vec3 | null {
const lengthSquared = lengthSquaredVec3(vector);
@@ -242,6 +251,26 @@ function distanceToAxisAlignedBox(
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}
function distanceToHorizontalAxisAlignedBounds(
position: Vec3,
bounds: { min: Vec3; max: Vec3 }
): number {
const dx =
position.x < bounds.min.x
? bounds.min.x - position.x
: position.x > bounds.max.x
? position.x - bounds.max.x
: 0;
const dz =
position.z < bounds.min.z
? bounds.min.z - position.z
: position.z > bounds.max.z
? position.z - bounds.max.z
: 0;
return Math.sqrt(dx * dx + dz * dz);
}
function isPlayerInsideTriggerVolume(
feetPosition: Vec3,
eyePosition: Vec3,
@@ -507,6 +536,16 @@ function collectRuntimeInteractionTargetSources(
}
const distance = distanceBetweenVec3(interactionOrigin, interactable.position);
const horizontalDistance = distanceBetweenVec2(
{
x: interactionOrigin.x,
y: interactionOrigin.z
},
{
x: interactable.position.x,
y: interactable.position.z
}
);
const targetRadius = getInteractableTargetRadius(interactable);
const acquisitionRange = options.useTargetingReach
? TARGETING_ACQUISITION_REACH
@@ -514,7 +553,10 @@ function collectRuntimeInteractionTargetSources(
targetRadius +
DEFAULT_INTERACTION_PROMPT_NEAR_FIELD_RADIUS;
if (distance > acquisitionRange) {
if (
(options.useTargetingReach ? distance : horizontalDistance) >
acquisitionRange
) {
continue;
}
@@ -545,13 +587,20 @@ function collectRuntimeInteractionTargetSources(
const bounds = getNpcDialogueTargetBounds(npc);
const horizontalRadius = getNpcHorizontalTargetRadius(npc, bounds);
const distance = distanceToAxisAlignedBox(interactionOrigin, bounds);
const horizontalDistance = distanceToHorizontalAxisAlignedBounds(
interactionOrigin,
bounds
);
const acquisitionRange = options.useTargetingReach
? TARGETING_ACQUISITION_REACH
: (options.interactionReachMeters ?? bounds.range) +
horizontalRadius +
DEFAULT_INTERACTION_PROMPT_NEAR_FIELD_RADIUS;
if (distance > acquisitionRange) {
if (
(options.useTargetingReach ? distance : horizontalDistance) >
acquisitionRange
) {
continue;
}