fix(physics): AP-10 - restore retail's 0.1m dry-corner water sink-in; wire WATER_CONTACT_TS
Campaign P Slice P4 item 2. TerrainSurface.SampleWaterDepth now returns 0.1
(was collapsed to 0) for a partially-water cell's dry corner, matching
retail's ObjCell.get_water_depth / calc_water_depth (via ACE's unambiguous
C# port). ValidateWalkable's formula was already byte-for-byte verbatim
(ACE ObjectInfo.ValidateWalkable line 124); only the constant was collapsed.
The old collapse's justification ("0.1 destabilizes the feet-exactly-on-plane
contact-touch check because dist > EPSILON skips SetContactPlane that tick")
is structurally true of retail too - traced and confirmed this slice: in ALL
THREE implementations (retail, ACE, acdream) a skipped touch-reassertion is
NOT a fall, because Contact/OnWalkable are STICKY -
PhysicsEngine.ResolveWithTransition's onGround computation ORs the fresh
per-call ContactPlaneValid with the seeded, persistent
PhysicsBody.TransientState.OnWalkable bit (itself written back by the
caller's own sticky TransientState). PhysicsEngine.SampleTerrainWalkable's
isWater = waterDepth >= 0.45f threshold means the restore does not flip the
dry corner's water classification (0.1 still < 0.45) - only the sink-in
depth changes. Full Core.Tests suite green (4038/2 skips, up from 4026)
proves the sticky-bit argument held in practice.
WATER_CONTACT_TS (TransientStateFlags.WaterContact, declared but never
written) is now mirrored alongside CONTACT_TS/ON_WALKABLE_TS at every commit
point that writes them: PhysicsObjUpdate.ApplySetPositionContact (projectiles
+ remote teleport), PhysicsObjUpdate.CommitSetPositionTransition (remote
teleport placement), and PhysicsEngine's per-resolve body-state commit (local
player + remote dead-reckoning + ordinary movers via ResolveWithTransition -
the actual SetPositionInternal-equivalent path). No signature changes needed:
body.ContactPlaneIsWater is already fresh by the time each function runs.
CollisionShadowVerifier audit: no change needed. It diffs graph-vs-flat BSP
traversal outcomes (ObjectInfo/CollisionInfo/SpherePath fields already
including ContactPlaneIsWater); it never touches PhysicsBody.TransientState,
and the water-depth constant is computed identically upstream of both
traversal modes, so it cannot introduce a new graph/flat divergence.
Filed #264 for the three items research explicitly left open (none block
this port): no confirmed retail consumer of WATER_CONTACT_TS was found (an
xref scan wasn't attempted - bitmask reads aren't text-greppable); the
CLandCell ENTIRELY_WATER ethereal/swim exemption from terrain collision was
not cross-checked; jump-in-water/swim-animation effects were not
investigated (out of physics/collision scope).
Conformance: Ap10WaterSemanticsTests covers SampleWaterDepth golden values
(NotWater/EntirelyWater/PartiallyWater wet+dry corners), the isWater
threshold non-flip, WaterContact mirroring in both PhysicsObjUpdate
functions, and two settle-to-rest end-to-end PhysicsEngine.ResolveWithTransition
scenarios (water: sinks exactly waterDepth below the plane and sets
WaterContact; dry: rests exactly on the plane and clears any stale
WaterContact bit).
Register: retired AP-10 (92 active AP rows, down from 93).
AcDream.Core.Tests: 4038 passed, 2 skipped, 0 failed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
d6c3f8657a
commit
cc8d57a26e
7 changed files with 439 additions and 18 deletions
|
|
@ -147,6 +147,54 @@ regressing the #225 lifestone/candle compositing.
|
|||
|
||||
---
|
||||
|
||||
## #264 — Water semantics: WATER_CONTACT_TS consumer + two unverified swim behaviors
|
||||
|
||||
**Status:** OPEN (filed 2026-07-30, Campaign P Slice P4 AP-10 closeout)
|
||||
**Severity:** LOW (no confirmed divergence; research/verification follow-up)
|
||||
**Component:** physics / terrain / water
|
||||
|
||||
**Context:** AP-10 (dry-corner water sink-in) is retired and `WATER_CONTACT_TS`
|
||||
(`TransientStateFlags.WaterContact`) is now produced (mirrored alongside
|
||||
`Contact` by `PhysicsObjUpdate.ApplySetPositionContact`,
|
||||
`CommitSetPositionTransition`, and `PhysicsEngine`'s per-resolve body-state
|
||||
commit). Three items from
|
||||
`docs/research/2026-07-29-remote-and-world-specials-pseudocode.md` §5.3-5.4
|
||||
remain genuinely unresolved — none block the AP-10 port, but none are
|
||||
silently absorbed either:
|
||||
|
||||
1. **No confirmed retail CONSUMER of `WATER_CONTACT_TS` was found.** The
|
||||
write site (`CPhysicsObj::SetPositionInternal`, pc:283459-283483) is
|
||||
confirmed; a full xref scan for READS of bit 0x8 on `transient_state`
|
||||
was not attempted (bitmask reads are not text-greppable across the
|
||||
1.4M-line pseudo-C dump without high false-positive noise against
|
||||
unrelated 0x8 masks). Is it a pure reporting/query bit (e.g. an "is
|
||||
swimming" query for animation/sound/UI with no gameplay-feel
|
||||
consequence), or does something in the movement/friction/step chain
|
||||
branch on it? Next step: Ghidra MCP `/function_xrefs?name=CPhysicsObj::
|
||||
SetPositionInternal` once reachable, or a live cdb capture.
|
||||
2. **`CLandCell::find_env_collisions`'s ENTIRELY_WATER early-exit** (pc:317091:
|
||||
`if (block_water_type == ENTIRELY_WATER && !ethereal && !(state&0x40)) return;`
|
||||
— a swimming/ethereal exemption from terrain collision entirely) was
|
||||
**not cross-checked** against acdream's handling of this exact condition.
|
||||
Flagged as unverified, not asserted-divergent or asserted-matching.
|
||||
3. **Jump-in-water and movement-effects-in-water** (reduced jump height, swim
|
||||
animation triggers) were **not investigated** — out of the P4 physics/
|
||||
collision scope; would need a `MovementSystem`/animation-side read.
|
||||
|
||||
**Files:** `src/AcDream.Core/Physics/PhysicsBody.cs` (`TransientStateFlags
|
||||
.WaterContact`, `IsWaterContact`); `src/AcDream.Core/Physics/PhysicsObjUpdate.cs`;
|
||||
`src/AcDream.Core/Physics/TransitionTypes.cs` (outdoor `FindEnvCollisions`
|
||||
terrain branch — the ENTIRELY_WATER exemption's acdream-side home, if it
|
||||
exists at all).
|
||||
|
||||
**Acceptance:** either (a) a confirmed consumer of `WATER_CONTACT_TS` is
|
||||
found and ported (or confirmed absent, closing this cleanly), and (b) the
|
||||
ENTIRELY_WATER early-exit is cross-checked and either confirmed matching or
|
||||
filed as its own register row; or (c) this issue is re-scoped/split once one
|
||||
sub-item resolves.
|
||||
|
||||
---
|
||||
|
||||
## #262 — Run-on-the-spot at first login: no displacement until a recall reset
|
||||
|
||||
**Status:** OPEN
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue