docs(B.4c): correct handoff fabrications surfaced by final review
Opus final review of B.4c flagged that Task 4's handoff doc invented implementation details that don't exist in the code: 1. IsDoorSpawn claimed to check "spawn.WeenieObj.WeenieType == 8 OR IsDoorName(spawn.Name)" — the actual code is just IsDoorName(spawn.Name) delegating to "name == "Door"". No WeenieType lookup exists. 2. A "_doorSequencers" per-door dict was referenced in three places — that dict doesn't exist. The actual code reuses the existing _animatedEntities[entity.Id] dict (same one that holds creatures + the player), with Animation = null! per the existing pattern at line 7885. 3. The UM dispatch path was described as a new B.4c-added branch with pseudocode — that's wrong. B.4c does NOT add a new dispatch path; OnLiveMotionUpdated's existing TryGetValue against _animatedEntities handles doors automatically once Task 1's spawn-time branch registers them. The only UM-dispatch B.4c contribution is the [door-cycle] diagnostic line, gated on IsDoorName. Corrects sections "At world load (spawn time)", "When the door opens", "Per-frame mesh rebuild", and "Door types covered" to reflect the actual shipped code. cmd→motion mapping (cmd=0x000C → open, cmd=0x000B → close) left as-is — it was correct. No code change. Verified by re-reading GameWindow.cs IsDoorSpawn / IsDoorName helpers, the Task 1 spawn-time branch body, and the TickAnimations sequencer dispatch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ebdbf821dc
commit
8bb81db659
1 changed files with 33 additions and 24 deletions
|
|
@ -66,9 +66,11 @@ happens inside `GameWindow.OnLiveEntitySpawnedLocked`, which branches on
|
|||
|
||||
### At world load (spawn time)
|
||||
|
||||
1. `IsDoorSpawn(spawn)` — checks `spawn.WeenieObj.WeenieType == 8` (the
|
||||
`Door` weenie type) OR `IsDoorName(spawn.Name)` (fallback for servers that
|
||||
tag door-weenies with non-8 types). If true, the entity is a door.
|
||||
1. `IsDoorSpawn(spawn)` — delegates to `IsDoorName(spawn.Name)`, which
|
||||
returns `name == "Door"`. Detection by server-sent name string only.
|
||||
Cheap, exact, no WeenieType lookup. If a future ACE localizes "Door"
|
||||
or sends a different name, those entities silently won't animate —
|
||||
acceptable per B.4c's "doors only at English Holtburg" scope.
|
||||
|
||||
2. **Initial state seed** — the door's `PhysicsState` from `spawn` carries the
|
||||
open/closed bit. The code reads `spawn.PhysicsState` (or
|
||||
|
|
@ -83,8 +85,13 @@ happens inside `GameWindow.OnLiveEntitySpawnedLocked`, which branches on
|
|||
var cycleCmd = isOpen ? MotionCommand.On : MotionCommand.Off;
|
||||
sequencer.SetCycle(style, (uint)cycleCmd, speed: 0f);
|
||||
```
|
||||
The sequencer is registered in a new per-door side-dict on `GameWindow`
|
||||
keyed by `entity.Id`. At first `Advance(dt)` call, it produces the correct
|
||||
The fully-initialized `AnimatedEntity` (with the seeded `Sequencer`) is
|
||||
registered into the existing `_animatedEntities` dict keyed by `entity.Id`
|
||||
— same dict that holds creatures and the player. `Animation = null!`
|
||||
(the null-forgiving suppression matches an existing pattern at
|
||||
`GameWindow.cs:7885` for sequencer-driven entities where the legacy
|
||||
`Animation` field is unused). At the first per-frame `Advance(dt)`
|
||||
call from `TickAnimations`, the sequencer produces the correct
|
||||
rest-pose frames for the door's current state.
|
||||
|
||||
4. **Log evidence at spawn:**
|
||||
|
|
@ -97,17 +104,17 @@ happens inside `GameWindow.OnLiveEntitySpawnedLocked`, which branches on
|
|||
### When the door opens (UpdateMotion arrives)
|
||||
|
||||
ACE broadcasts `UpdateMotion (0xF74D)` with `stance=0x003D` (NonCombat) and
|
||||
`cmd=0x000C` (On = open). The existing `OnLiveMotionUpdated` handler previously
|
||||
dropped this silently for non-creature entities. B.4c adds a `IsDoorName`-gated
|
||||
branch:
|
||||
wire `cmd=0x000C` (which `MotionCommandResolver.ReconstructFullCommand`
|
||||
maps to full motion `0x4000000B` = `MotionCommand.On` = door open).
|
||||
|
||||
```csharp
|
||||
if (_doorSequencers.TryGetValue(entity.Id, out var seq))
|
||||
{
|
||||
var style = 0x80000000u | (uint)um.Stance;
|
||||
seq.SetCycle(style, (uint)um.ForwardCommand, um.ForwardSpeed);
|
||||
}
|
||||
```
|
||||
B.4c does NOT add a new dispatch path here — the existing
|
||||
`OnLiveMotionUpdated` handler already routes via the `_animatedEntities`
|
||||
dict + per-entity `Sequencer`, the same code path creatures use. The
|
||||
only B.4c contribution at UM dispatch is the new `[door-cycle]`
|
||||
diagnostic gated on `IsDoorName(doorInfo.Name)`. Before B.4c, doors
|
||||
silently dropped at the `_animatedEntities.TryGetValue` check at
|
||||
`GameWindow.cs:3036` because doors weren't registered; B.4c's Task 1
|
||||
spawn-time branch fixed that.
|
||||
|
||||
The sequencer transitions from the `Off` cycle (static closed pose) through
|
||||
the door-swing link animation to the `On` cycle (static open pose).
|
||||
|
|
@ -148,13 +155,14 @@ UM guid=0x7A9B403A mt=... cmd=0x000B ... motion=0x4000000C
|
|||
### Per-frame mesh rebuild
|
||||
|
||||
The door sequencer integrates into `GameWindow.TickAnimations` via the same
|
||||
`_doorSequencers` dict. Each frame, `Advance(dt)` is called on the sequencer
|
||||
and the resulting `PartFrames` drive the same `MeshRefs` rebuild that creature
|
||||
entities use. This is the reason the stance-value bug produced underground doors:
|
||||
with the wrong style key (`0x80000001`) `HasCycle` returned false, the sequencer
|
||||
was empty, `Advance` returned no frames, and the per-frame part-matrix rebuild
|
||||
at `GameWindow.cs:7691` received zero frames — collapsing every part to the
|
||||
entity origin.
|
||||
`_animatedEntities` dict that holds creatures. Each frame, `ae.Sequencer.Advance(dt)`
|
||||
is called and the resulting per-part transforms drive the same `MeshRefs` rebuild
|
||||
that creature entities use (sequencer branch at `GameWindow.cs:7497`; doors
|
||||
never enter the legacy slerp `else` branch). This is the reason the stance-value
|
||||
bug produced underground doors: with the wrong style key (`0x80000001`)
|
||||
`HasCycle` returned false, the sequencer was empty at spawn, `Advance` returned
|
||||
identity frames, and the per-frame part-matrix rebuild received `Vector3.Zero /
|
||||
Quaternion.Identity` for every part — collapsing them all to the entity origin.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -244,8 +252,9 @@ Other interactable non-creature entities (chests, levers, traps) will still
|
|||
silently drop their `UpdateMotion` commands — they are not covered by B.4c and
|
||||
no issue has been filed for them yet. When those animations become relevant
|
||||
(M2/M3 inventory + dungeon content), the same spawn-time registration pattern
|
||||
can be extended by widening `IsDoorSpawn` and reusing the `_doorSequencers`
|
||||
infrastructure.
|
||||
can be extended: broaden the detection predicate beyond `name == "Door"` and
|
||||
register additional entity types in the existing `_animatedEntities` dict via
|
||||
the same sibling branch.
|
||||
|
||||
### Door toggle behavior
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue