Files
benilla-octo/crates/benilla-app/src/ui_script/instance_tests.rs
T
SamandClaude Fable 5.1 7308046d60 the screen warps underwater, and the ocean darkens with depth
- the screen warps underwater: submerged, the reference runs a second pass list whose third pass is `FFXGlowWave` (`0x6cb1f0`), binding a 128×128 two-channel sine bump map that displaces both the screen and the blur texcoords by 3.0 full-res pixels — uv rotated 10°, scaled W/128 × 0.88·H/128, two phases at 3174 and 2805 ms; wow-re had carried the swap as "GlowWave, or a duplicate Glow" and the cross-check settled it (the two arms are mutually exclusive and the plain-Glow arm is unreachable on both backends; lava and slime warp too, and a ghost's death pass replaces the glow outright); a dry frame binds the same pipeline object as before this existed, and the phases advance live at 0.313/s and 0.355/s against a predicted 0.315 and 0.357
- ocean is a fifth submersion state — 96.8% of every wet sub-tile in the shipped corpus, so essentially all open water — and it alone runs a depth ramp on the light: `t = clamp(eye.z, −30, 0)`, ambient at `(k+1)/2`, diffuse at `k/4 + 3/4`, exactly k = 0 at −30 yd, gated on the full dword `== 1` at `0x6d2821` (the ramp does NOT drive the fog colour — that store is dead, overwritten before submit); the sun and moon glare fade over a 10-yard depth ramp applied to the slew TARGET, not the drawn alpha — a read one indirection out that two notes had published a verified negative on; the MCLQ fishable bit (0x40) is deliberately unread, since `0x69b5d0` has zero callers in the image and fishability is the server's verdict
- the dropdown kit is the reference's own `UIDropDownMenu.xml` (one manifest line for 1150 lines of ours, `DropDownList3` gained, and two fixtures that only worked because our copy was more forgiving); `UnitFactionGroup` returns the English name AND the localized one — ours returned the localized string twice, and the first return names a TEXTURE in every stock consumer (`UI-PVP-`..factionGroup), so on a non-English client every one of them named a file that does not exist

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 17:05:57 +07:00

220 lines
7.8 KiB
Rust

//! The instance-lockout **Era surface** (decision 1748): the three engine bindings, and the one
//! place in the shipped UI that reads them — the SELF menu's "Reset all instances" row and the
//! `CONFIRM_RESET_INSTANCES` dialog behind it.
//!
//! The four chat lines the family's other packets raise are engine-composed and have no Lua at
//! all (no FrameXML file mentions `RAID_INSTANCE_WELCOME` or its siblings); they are tested at the
//! composer, in `crate::ui_instance`.
use benilla_ui::script::UiScript;
use super::test_ui::load_ui as load_xml;
/// The three bindings answer with the reference's own shapes — `IsInInstance` a PAIR, both
/// readers `1`/`nil` rather than `true`/`false` (the reference pushes the double 1.0), and
/// `ResetInstances` a queue.
#[test]
fn the_three_bindings_have_the_reference_shapes() {
let mut s = UiScript::new().unwrap();
// Nothing pushed yet: the app has not said where we are.
assert_eq!(
s.eval::<(Option<f64>, String)>("return IsInInstance()")
.unwrap(),
(None, "none".into()),
"no map pushed reads as not-an-instance"
);
for (ty, inside, name) in [
(0u32, None, "none"),
(1, Some(1.0), "party"),
(2, Some(1.0), "raid"),
(3, Some(1.0), "pvp"),
// Past the reference's own `cmp esi,4; jae` guard.
(4, Some(1.0), "none"),
] {
s.set_instance_type(Some(ty));
assert_eq!(
s.eval::<(Option<f64>, String)>("return IsInInstance()")
.unwrap(),
(inside, name.into()),
"InstanceType {ty}"
);
}
assert_eq!(
s.eval::<Option<f64>>("return CanShowResetInstances()")
.unwrap(),
None,
"false by default — no bind, no dungeon behind us"
);
s.set_can_reset_instances(true);
assert_eq!(
s.eval::<Option<f64>>("return CanShowResetInstances()")
.unwrap(),
Some(1.0)
);
assert_eq!(s.take_reset_instance_asks(), 0);
s.run("ResetInstances(); ResetInstances()").unwrap();
assert_eq!(s.take_reset_instance_asks(), 2, "each call is one send");
assert_eq!(s.take_reset_instance_asks(), 0, "the drain is a take");
}
/// The whole shipped path, through the real hit test: right-click your own portrait, the row is
/// there only while `CanShowResetInstances()` is true, clicking it raises the reference's confirm,
/// and Yes is the only thing that sends.
#[test]
fn the_self_menu_row_gates_on_the_binding_and_confirms_before_sending() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
// The row labels a bare harness has no GlobalStrings.lua for. Verbatim 1.12 values
// (`RESET_INSTANCES` l.3342, `CONFIRM_RESET_INSTANCES` l.851, `YES` l.5463, `NO` l.2794) —
// production runs the player's own string table at boot.
s.run(
r#"
RESET_INSTANCES = "Reset all instances"
CONFIRM_RESET_INSTANCES = "Do you really want to reset all of your instances?"
YES = "Yes"
NO = "No"
CANCEL = "Cancel"
"#,
)
.unwrap();
for file in [
"Fonts.xml",
"UIParent.xml",
"MoneyFrame.xml",
"UiPanels.xml",
"GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"UnitPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\CombatFeedback.xml",
"Interface\\FrameXML\\PlayerFrame.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\TargetFrame.xml",
"Interface\\FrameXML\\PetFrame.xml",
"RaidFrame.xml",
] {
load_xml(&s, file);
}
s.resolve();
assert!(s.errors().is_empty(), "load errors: {:?}", s.errors());
let open_self_menu = |s: &mut UiScript| {
s.run("CloseDropDownMenus()").unwrap();
s.run(r#"PlayerFrame_OnClick("RightButton")"#).unwrap();
s.resolve();
};
let row_labels = |s: &mut UiScript| -> Vec<String> {
let n = s.eval::<i64>("return DropDownList1.numButtons").unwrap();
(1..=n)
.map(|i| {
s.eval::<String>(&format!("return DropDownList1Button{i}:GetText() or \"\""))
.unwrap()
})
.collect()
};
// Off: the row is not in the menu at all — hidden, not greyed (the reference's
// `UnitPopupShown[index] = 0`). Solo, it is the ONLY row of the SELF menu that could show
// (the loot trio, Leave and the raid marks all need a party), so the menu's "nothing but
// CANCEL" early-out fires and no menu opens at all. That is the reference's behaviour too,
// and it is the sharpest possible assertion that the row is really gone.
open_self_menu(&mut s);
assert!(
s.eval::<bool>("return not DropDownList1:IsVisible()")
.unwrap(),
"solo with no lockout to reset, the SELF menu has nothing to show"
);
// On: the row appears, and with it the menu.
s.set_can_reset_instances(true);
open_self_menu(&mut s);
assert!(
s.eval::<bool>("return DropDownList1:IsVisible()").unwrap(),
"the one showable row is enough to open the SELF menu"
);
let labels = row_labels(&mut s);
let row = labels
.iter()
.position(|l| l == "Reset all instances")
.unwrap_or_else(|| panic!("the row shows once the binding says so: {labels:?}"));
// Clicking it sends NOTHING — it raises the confirm.
let button = format!("DropDownList1Button{}", row + 1);
let (cx, cy) = s
.eval::<(f64, f64)>(&format!("return {button}:GetCenter()"))
.unwrap();
s.mouse_button(cx as f32, cy as f32, "LeftButton", true);
s.mouse_button(cx as f32, cy as f32, "LeftButton", false);
s.resolve();
assert_eq!(
s.take_reset_instance_asks(),
0,
"the row itself never sends — it asks"
);
assert!(
s.eval::<bool>("return StaticPopup1:IsVisible()").unwrap(),
"the row raises CONFIRM_RESET_INSTANCES"
);
assert_eq!(
s.eval::<String>("return StaticPopup1Text:GetText()")
.unwrap(),
"Do you really want to reset all of your instances?"
);
assert_eq!(
s.eval::<String>("return StaticPopup1Button1:GetText()")
.unwrap(),
"Yes"
);
assert_eq!(
s.eval::<String>("return StaticPopup1Button2:GetText()")
.unwrap(),
"No"
);
// No sends nothing; Yes sends exactly one.
let (nx, ny) = s
.eval::<(f64, f64)>("return StaticPopup1Button2:GetCenter()")
.unwrap();
s.mouse_button(nx as f32, ny as f32, "LeftButton", true);
s.mouse_button(nx as f32, ny as f32, "LeftButton", false);
s.resolve();
assert_eq!(
s.take_reset_instance_asks(),
0,
"No is not an answer that sends"
);
open_self_menu(&mut s);
let labels = row_labels(&mut s);
let row = labels
.iter()
.position(|l| l == "Reset all instances")
.expect("still offered");
let button = format!("DropDownList1Button{}", row + 1);
let (cx, cy) = s
.eval::<(f64, f64)>(&format!("return {button}:GetCenter()"))
.unwrap();
s.mouse_button(cx as f32, cy as f32, "LeftButton", true);
s.mouse_button(cx as f32, cy as f32, "LeftButton", false);
s.resolve();
let (yx, yy) = s
.eval::<(f64, f64)>("return StaticPopup1Button1:GetCenter()")
.unwrap();
s.mouse_button(yx as f32, yy as f32, "LeftButton", true);
s.mouse_button(yx as f32, yy as f32, "LeftButton", false);
s.resolve();
assert_eq!(
s.take_reset_instance_asks(),
1,
"Yes is the one call that sends CMSG_RESET_INSTANCES"
);
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
}