Release Healer Man 0.1.35

This commit is contained in:
phenom committed 2026-09-12 16:02:15 -04:00
1 parent 46c272f889
commit 40d9f346d8
13 files changed
+218 -118

No files matched your search

+6 -12
View File
@@ -1,6 +1,7 @@
import type RAPIER from "@dimforge/rapier3d-compat";
import type { World } from "@dimforge/rapier3d-compat";
import type { PartyWorldPosition } from "../game/partyRuntimeRegistry";
import { ACTOR_TERRAIN_QUERY_GROUPS } from "./actorCollision";
const COLLISION_RADIUS = 0.34;
const COLLISION_HALF_HEIGHT = 0.48;
@@ -11,14 +12,6 @@ export const PARTY_FLOOR_RAY_DEPTH = 2;
const FLOOR_SAMPLE_SPACING = 0.6;
const MAX_FLOOR_DELTA = 0.55;
export function partyTerrainQueryFlags(rapier: typeof RAPIER) {
// Actor capsules are not terrain. Crowd spacing is handled separately by
// party separation; counting the player here blocks recalls and replans.
return rapier.QueryFilterFlags.EXCLUDE_SENSORS
| rapier.QueryFilterFlags.EXCLUDE_DYNAMIC
| rapier.QueryFilterFlags.EXCLUDE_KINEMATIC;
}
/** Shared by live party routing and collision-backed traversal regressions. */
export function createPartyDirectSegmentValidator(rapier: typeof RAPIER, world: World) {
const capsule = new rapier.Capsule(
@@ -26,7 +19,7 @@ export function createPartyDirectSegmentValidator(rapier: typeof RAPIER, world:
COLLISION_RADIUS,
);
const rotation = { x: 0, y: 0, z: 0, w: 1 };
const flags = partyTerrainQueryFlags(rapier);
const flags = rapier.QueryFilterFlags.EXCLUDE_SENSORS;
return (start: PartyWorldPosition, end: PartyWorldPosition): boolean => {
const dx = end[0] - start[0];
const dy = end[1] - start[1];
@@ -43,6 +36,7 @@ export function createPartyDirectSegmentValidator(rapier: typeof RAPIER, world:
distance,
false,
flags,
ACTOR_TERRAIN_QUERY_GROUPS,
);
if (obstacle && obstacle.time_of_impact < distance - 0.04) return false;
const sampleCount = Math.max(1, Math.ceil(distance / FLOOR_SAMPLE_SPACING));
@@ -54,7 +48,7 @@ export function createPartyDirectSegmentValidator(rapier: typeof RAPIER, world:
y: expectedY + PARTY_FLOOR_RAY_HEIGHT,
z: start[2] + dz * progress,
}, { x: 0, y: -1, z: 0 });
const floor = world.castRay(ray, PARTY_FLOOR_RAY_DEPTH, true, flags);
const floor = world.castRay(ray, PARTY_FLOOR_RAY_DEPTH, true, flags, ACTOR_TERRAIN_QUERY_GROUPS);
if (!floor || Math.abs(ray.origin.y - floor.timeOfImpact - expectedY) > MAX_FLOOR_DELTA) return false;
}
return true;
@@ -63,7 +57,7 @@ export function createPartyDirectSegmentValidator(rapier: typeof RAPIER, world:
/** Triangle corridors need wall/overhang validation, not a second radius erosion. */
export function createPartyRouteSegmentValidator(rapier: typeof RAPIER, world: World) {
const flags = partyTerrainQueryFlags(rapier);
const flags = rapier.QueryFilterFlags.EXCLUDE_SENSORS;
return (start: PartyWorldPosition, end: PartyWorldPosition): boolean => {
const dx = end[0] - start[0];
const dy = end[1] - start[1];
@@ -74,7 +68,7 @@ export function createPartyRouteSegmentValidator(rapier: typeof RAPIER, world: W
const ray = new rapier.Ray({
x: start[0], y: start[1] + 0.9, z: start[2],
}, { x: dx / distance, y: dy / distance, z: dz / distance });
const hit = world.castRay(ray, distance, true, flags);
const hit = world.castRay(ray, distance, true, flags, ACTOR_TERRAIN_QUERY_GROUPS);
return !hit || hit.timeOfImpact >= distance - 0.04;
};
}