your corpse answers the mouse, and a cinematic's last holes close

- a corpse is a body you can hover, cursor and click: it enters the same ray pass as units with the winner switched on type at publish (the reference's own shape — one trace over every object), the cursor classifier is transcribed whole (lootable-by-me → the pickup cursor, grayed by range; else the insignia leg behind the learned-skill latch; your own body falls through to the clear), and right-click is "not mounted AND lootable" → CMSG_LOOT; CORPSE_FIELD_FLAGS bit 5 is the PvP insignia flag, not "reclaimable" as an old note had it; the widening also caught that a GameObject anywhere on screen could steal the click from a nearer corpse, and that a left-click on a body cleared your target as if you had clicked ground
- the cinematic sweep closes eleven holes: a shot plays its sequence band's WIDTH, not its end — two shipped fly-bys band away from zero and ran long with their opening frames frozen (the Night Elf intro measured 102333 → 102000 ms); CMSG_NEXT_CINEMATIC_CAMERA announces every shot, the first included — the old "between shots" reading meant it was sent NEVER, since every 1.12 sequence row carries exactly one camera; the ack invariant is stated once (one CMSG_COMPLETE_CINEMATIC per accepted trigger, over-acking tolerated, under-acking never — a dropped ack despawns the world around you until relog); the hardware cursor hides for the shot; and the music cut lands in the frame that starts it — it was one frame late, exactly long enough for a first login's zone fanfare to start under the narration and be stamped as played
- RunBinding exists, and a fly-by stops handing the world its mouse: CinematicFrame's OnKeyDown hands the SCREENSHOT chord back to its binding through RunBinding, a global we never had, so every press during a fly-by raised and took no picture; and the mouse was fully live under a shot — right-drag turned the character, clicks picked targets through the flying camera, both buttons walked the body — so the pointer now reads as over the UI while a shot plays
- AdvanceTime and ReplaceIconTexture are carved off the bytes: AdvanceTime really is a no-op in the reference (its one reachable call is mov eax,1; ret), ReplaceIconTexture is a material swap over a model's type-14 texture slots that stores nothing on the widget, and SetModel(nil) RAISES — the "documented clear" our binding claimed was invented, not read; and the addon roster now says WHOSE package is short when a .toc names files the folder doesn't hold — nine of the corpus's twenty-nine load failures are the addon's own manifest, which the real client also shrugs off ("Couldn't open %s", carry on), so they stop reading as our defects

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Sam
2026-08-31 19:55:36 +07:00
co-authored by Claude Fable 5
parent f6f2af3da9
commit 6e3a67e039
28 changed files with 1237 additions and 130 deletions
@@ -127,3 +127,47 @@ fn the_host_has_a_reference_name_for_the_keys_it_now_delivers() {
);
}
}
/// **The one key a cinematic gives back.** The module doc above says the reference's `OnKeyDown`
/// calls `RunBinding("SCREENSHOT")` by hand *because* the walk's gate is existence — and benilla
/// shipped that transcribed line against a `RunBinding` that did not exist in the whole codebase.
/// Every press of the screenshot key during a fly-by raised `attempt to call global 'RunBinding'`
/// and took no picture, and the three tests above stayed green through all of it because they only
/// ever asked about keys the frame *swallows*.
#[test]
fn the_screenshot_key_is_handed_back_to_its_binding() {
let mut s = ui_with_the_cinematic_frame();
// The binding table the passthrough reads: `GetBindingKey("SCREENSHOT")` has to answer, or the
// arm is skipped and the test proves nothing.
s.register_bindings(&crate::bindings::registry_commands());
s.seed_binding_set(1, None);
s.load_binding_set(1);
let key = s
.keybind_snapshot()
.into_iter()
.find(|(name, _)| name == "SCREENSHOT")
.and_then(|(_, keys)| keys.into_iter().next())
.expect("SCREENSHOT ships a default chord");
start_cinematic(&mut s);
let _ = s.take_keybind_requests();
// Consumed like every other key — the frame is up, so the binding layer must not also see it.
assert!(
s.frame_key_input(&key),
"the frame consumes {key} like any other key"
);
// …and handed straight back to its command by hand. This is the whole point of the arm: the
// request is what the host runs, and an error here means no screenshot.
assert_eq!(
s.take_keybind_requests(),
vec![benilla_ui::script::keybind::KeybindRequest::Run(
"SCREENSHOT".into()
)],
"the screenshot key must reach its binding through RunBinding"
);
// ESCAPE is still the skip, and still queues nothing on the binding channel.
assert!(s.frame_key_input("ESCAPE"));
assert!(s.take_keybind_requests().is_empty());
}
+18 -1
View File
@@ -450,9 +450,26 @@ fn capture_ui_active(capture: Option<Res<crate::run_mode::CaptureMode>>) -> bool
fn arbitrate_pointer_over_ui(
egui: Option<Res<EguiPointerOver>>,
hover: Res<PlayerUiHover>,
cinematic: Option<Res<crate::cinematic::Cinematic>>,
mut over: ResMut<PointerOverUi>,
) {
over.0 = egui.is_some_and(|e| e.0) || hover.0.is_some();
// **A cinematic covers the screen with a frame, so the pointer is over the UI wherever it
// is.** That is a fact about the reference's own layout, not a special case: `CinematicFrame`
// is `setAllPoints` + `enableMouse="true"`, and while it is up it is the only mouse target the
// hit test can reach — because `UIParent:Hide()` has taken every other frame out of it.
//
// benilla cannot yet reach that answer through the hit test. `crate::cinematic` substitutes
// `UiHidden` for the reference's `UIParent:Hide()` (decision 1699, for want of a HUD parented
// to `UIParent`), and `UiHidden` also switches the whole mouse feed off — ALT-Z's meaning,
// where the world *should* take the mouse. So `feed_ui_input` never hit-tested
// `CinematicFrame` at all and the world took every click of a fly-by: right-drag turned the
// character, left-click picked targets through the flying camera, the wheel zoomed a rig
// nobody could see. **This line states the layout fact directly, and it is the interim, not
// the fix** — restoring the 32 dropped `parent="UIParent"` declarations lets the hit test
// reach the same answer on its own, and this argument (and this parameter) is then dead code
// to delete.
let in_cinematic = cinematic.is_some_and(|c| c.is_playing());
over.0 = in_cinematic || egui.is_some_and(|e| e.0) || hover.0.is_some();
}
/// The session lifecycle — the VM's birth, identity, death, and the reload. Every edge function