the minimap and world map go stock, and the chat loses its white plate
- the minimap cluster and the battleground list are the reference's own `Minimap.xml` and `BattlefieldFrame.xml`, ours deleted, and the sixteen engine names the static probe found unbound are built, not stubbed: the battleground list and queue family (the as-group join refused client-side with no packet when the map's `MaxPlayers` is below the group), the bodyless `CMSG_BATTLEFIELD_STATUS` on world enter — benilla never sent it, so a queue joined before a reconnect was invisible — the 5.5556 yd `BATTLEFIELDS_CLOSED` leash, and the meeting-stone pair over the `0x295` five-way table with both asymmetries; the ping's lifetime is the stock Lua's now (held 5 s, faded 0.5 s), `GetPingPosition` answers two numbers always — our nil was a Lua error on every frame of the stock `Minimap_OnUpdate` — and the map-change drop the reference never had is gone (1974)
- the world map is the reference's own `WorldMapFrame.xml`, our transcription deleted; built for it: the arrow-frame family (an anonymous `Model` child at its 33.6 px footprint, drawn app-side as the minimap's own arrow sprite through one shared constant), the battleground position family over `MSG_BATTLEGROUND_PLAYER_POSITIONS` both ways (the reference's 5000 ms request throttle), and `GetPlayerMapPosition` resolving `raid1..raid40` where it knew only the party (B320); `SetupFullscreenScale` — the engine binding `0x48c270` the map's and the cinematic frame's OnShow call, which our map had stood in for with Lua — is bound to the carved law `min(0.75 · aspect, 1)` off the configured aspect, written through the frame's own `SetScale` (1.0 at 4:3 and wider, 0.9375 at 5:4); a hovered POI writes the map's own area label, not the tooltip; named gap: `WorldMapPing` draws nothing yet (1980, 1981)
- the tutorial frame is the reference's own `TutorialFrame.xml`, over a tutorial system benilla never had: two bit banks filled from `SMSG_TUTORIAL_FLAGS` — the fire-once bank `TriggerTutorial` reads and sets (never a send) and the acknowledged bank `FlagTutorial` writes and sends; there is no tutorial CVar in the binary (210 `CVar::Register` sites censused), so "disable tutorials" is every bit acknowledged; the sites this app can produce are wired (the world-enter Welcome cascade, the level-up arm, item pushes, the loot sparkle, the meeting-stone and battleground arms), the rest named; the loader learned `<TitleRegion>` — the stock frame's drag handle, a region that emits no quad; and the `TabardModel` widget kind arrives ahead of its window, five ints bounded by the `.rdata` table `{170, 17, 6, 17, 51}` and the constant 100 000 tabard cost (1976, 1977)
- the chat window drew as an opaque white plate: the chat-cache loader, gated on `InWorld` alone, restored into the boot VM 130 ms before the deferred entry load filled it, and its per-VM memo then blocked the restore that would have reached the real frames — the plate the stock Lua tints black stayed the XML's white; between the entry edge and the load there is now no VM in the world (the edge parks the boot VM, the load takes it back), so no in-world feed pushes into a VM with no interface; the perf pill reads `59 fps 7.0 ms 17.3 cpu` — the MAIN thread's milliseconds in full text and the process-wide sum dim, because the sum of every thread's CPU time had been read as a frame time (a raid read 17 on it at a solid 60 with the main thread at 7); and `WOW_PROBE_UI_ONE_TEX=1` is a pricing lever, never a look, for the draw-count ceiling a UI atlas would reach before one is built (1978, 1954)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
//! The stock `TutorialFrame.xml` (decision 1976) driven engine-only: an alert button per
|
||||
//! `TUTORIAL_TRIGGER`, the window a click opens over the published id's strings, the
|
||||
//! `FlagTutorial` it makes, the unticked checkbox's `ClearTutorials` on hide, and
|
||||
//! `CINEMATIC_STOP` clicking the Welcome alert.
|
||||
|
||||
use benilla_ui::script::{ScriptValue, UiScript};
|
||||
|
||||
use super::test_ui::load_ui as load_xml;
|
||||
|
||||
fn session() -> UiScript {
|
||||
let mut s = UiScript::new().unwrap();
|
||||
s.set_screen_size(1024.0, 768.0);
|
||||
s.run("function PlaySound() end").unwrap();
|
||||
for f in [
|
||||
"Interface\\FrameXML\\Fonts.xml",
|
||||
"Interface\\FrameXML\\GlobalStrings.lua",
|
||||
"Interface\\FrameXML\\Localization.xml",
|
||||
"Interface\\FrameXML\\LocaleProperties.lua",
|
||||
"Interface\\FrameXML\\BasicControls.xml",
|
||||
"UIParent.xml",
|
||||
r"Interface\FrameXML\MoneyFrame.lua",
|
||||
r"Interface\FrameXML\MoneyFrame.xml",
|
||||
"UiPanels.xml",
|
||||
"Interface\\FrameXML\\GameTooltip.xml",
|
||||
r"Interface\FrameXML\UIPanelTemplates.lua",
|
||||
r"Interface\FrameXML\UIPanelTemplates.xml",
|
||||
"Interface\\FrameXML\\TutorialFrame.xml",
|
||||
] {
|
||||
load_xml(&s, f);
|
||||
}
|
||||
s.resolve();
|
||||
s
|
||||
}
|
||||
|
||||
fn visible(s: &UiScript, frame: &str) -> bool {
|
||||
s.eval::<bool>(&format!("return {frame}:IsVisible()"))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn trigger(s: &mut UiScript, published: i64) {
|
||||
s.fire_event("TUTORIAL_TRIGGER", vec![ScriptValue::Int(published)]);
|
||||
}
|
||||
|
||||
/// A trigger queues an alert button; its click opens the window on the id's title and text and
|
||||
/// acknowledges the id (0-based on the drain); a second trigger queues a second button.
|
||||
#[test]
|
||||
fn a_trigger_queues_an_alert_whose_click_opens_the_window_and_flags_it() {
|
||||
let _data = benilla_formats::wow_data_or_skip!();
|
||||
let mut s = session();
|
||||
assert!(!visible(&s, "TutorialFrameAlertButton1"));
|
||||
assert!(!visible(&s, "TutorialFrame"));
|
||||
|
||||
trigger(&mut s, 41);
|
||||
assert!(
|
||||
visible(&s, "TutorialFrameAlertButton1"),
|
||||
"the alert button shows"
|
||||
);
|
||||
assert_eq!(
|
||||
s.eval::<String>("return TutorialFrameAlertButton1.tooltip")
|
||||
.unwrap(),
|
||||
"Elite Quests"
|
||||
);
|
||||
trigger(&mut s, 42);
|
||||
assert!(
|
||||
visible(&s, "TutorialFrameAlertButton2"),
|
||||
"a second id takes the next button"
|
||||
);
|
||||
|
||||
s.run("TutorialFrameAlertButton1:Click()").unwrap();
|
||||
assert!(visible(&s, "TutorialFrame"), "the click opens the window");
|
||||
assert_eq!(
|
||||
s.eval::<String>("return TutorialFrameTitle:GetText()")
|
||||
.unwrap(),
|
||||
"Elite Quests"
|
||||
);
|
||||
assert!(s
|
||||
.eval::<String>("return TutorialFrameText:GetText()")
|
||||
.unwrap()
|
||||
.starts_with("You have accepted an elite quest"));
|
||||
assert_eq!(
|
||||
s.take_tutorial_flag_requests(),
|
||||
vec![40],
|
||||
"FlagTutorial(41) → the 0-based id"
|
||||
);
|
||||
assert!(
|
||||
!visible(&s, "TutorialFrameAlertButton1"),
|
||||
"the clicked alert is spent; the other stays"
|
||||
);
|
||||
assert!(visible(&s, "TutorialFrameAlertButton2"));
|
||||
|
||||
// Okay hides it; the checkbox is ticked, so nothing is cleared.
|
||||
s.run("TutorialFrameOkayButton:Click()").unwrap();
|
||||
assert!(!visible(&s, "TutorialFrame"));
|
||||
assert_eq!(s.take_tutorial_clears(), 0);
|
||||
}
|
||||
|
||||
/// Unticking "Display Tips" and closing calls `ClearTutorials` and drops every alert.
|
||||
#[test]
|
||||
fn an_unticked_checkbox_clears_the_tutorials_on_hide() {
|
||||
let _data = benilla_formats::wow_data_or_skip!();
|
||||
let mut s = session();
|
||||
trigger(&mut s, 41);
|
||||
trigger(&mut s, 42);
|
||||
s.run("TutorialFrameAlertButton1:Click()").unwrap();
|
||||
let _ = s.take_tutorial_flag_requests();
|
||||
s.run("TutorialFrameCheckButton:SetChecked(nil) TutorialFrame:Hide()")
|
||||
.unwrap();
|
||||
assert_eq!(s.take_tutorial_clears(), 1, "ClearTutorials() on hide");
|
||||
assert!(
|
||||
!visible(&s, "TutorialFrameAlertButton2"),
|
||||
"every alert dropped"
|
||||
);
|
||||
}
|
||||
|
||||
/// `CINEMATIC_STOP` clicks the Welcome alert (id 42) if it is queued — the first thing a new
|
||||
/// character sees after the intro — and moves the window to the screen's centre.
|
||||
#[test]
|
||||
fn cinematic_stop_opens_the_welcome_window() {
|
||||
let _data = benilla_formats::wow_data_or_skip!();
|
||||
let mut s = session();
|
||||
trigger(&mut s, 42);
|
||||
trigger(&mut s, 1);
|
||||
s.fire_event("CINEMATIC_STOP", vec![]);
|
||||
assert!(visible(&s, "TutorialFrame"));
|
||||
assert_eq!(
|
||||
s.eval::<String>("return TutorialFrameTitle:GetText()")
|
||||
.unwrap(),
|
||||
"Welcome to World of Warcraft!"
|
||||
);
|
||||
assert_eq!(s.take_tutorial_flag_requests(), vec![41]);
|
||||
assert!(
|
||||
visible(&s, "TutorialFrameAlertButton2"),
|
||||
"the Questgivers alert stays queued"
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user