the world map blips are the reference's, and particles go untinted
- the world map speaks the reference's names: WorldMapTooltip is declared (six corpus addons index it; pfUI dies on it at file scope), the blackout frame takes the reference's spelling BlackoutWorld, and the four hand-written party blips become the reference's own unit-blip templates — all 44 blips as instances, each with its published $parentIcon, the name pfUI recolours group blips by class through; the 40 raid ones are declared but not positioned yet, named in the OUT list rather than faked
- the templates addons build their own buttons from are published: ItemButtonTemplate, ContainerFrameItemButtonTemplate and the bag-slot chain — most of the handler scripts were live the whole time (this client executes the reference's own container and paper-doll code off the player's patch chain), so what was missing was mostly declarations, not behaviour — the bank arm stays out and is named as the omission it is; OptionsFrameSliders becomes real, with the three Graphics rows reading it and re-reading on show, so an addon's write to a slider's bounds actually moves the slider; and the template census that had ranked these at "zero demand" learns to see a local bound to a literal — its table went from 3 rows to 7
- the bindings answer in 1.12's own shapes: Button:IsEnabled() answers the NUMBER 1 or 0 (0 is truthy in Lua, so the reference's own == 0 tests got false forever, and three of our files had hand-worked around the divergence rather than fixed it); the constructors' string arguments are four shapes, not one rule — pfUI passes a Button where a template name goes and the reference constructs the FontString and ignores it; SetInventoryItem returns THREE values, the reference's own paper doll destructuring repairCost; UnitIsVisible is object presence and nothing else (57 bytes, one branch, no distance — an out-of-range party member is exists-yes, visible-nil); the tapped pair reads the two dynamic-flags bits, and its repaint wire fires UNIT_FACTION on the tap bit — the half a passing predicate test never sees; UnitIsPartyLeader is two ORed legs covering disjoint failures (a held stranger leading their own party, and an out-of-range member with no object to read a flag from); and the four nameplate verbs take no argument and return zero values
- the ghost's wisps compose onto its body instead of over it — the four emitters drew at full strength over a body at alpha 0.5, and now inherit the instance alpha down the attachment chain the way the reference recomposes it per frame; the residual we had parked ("the wisps should inherit the tint too") is REFUTED at the bytes: a particle batch commits hardcoded white RGB, and even that never reaches the fragment — particles are never tinted, only the alpha crosses, applied to the alpha byte alone — so the shipped shader split was already right and no code changes
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -133,7 +133,7 @@ fn resurrect_request_picks_variant_and_answers() {
|
||||
"the offerer name formats into the no-sickness text"
|
||||
);
|
||||
assert!(s
|
||||
.eval::<bool>("return StaticPopup1Button1:IsEnabled()")
|
||||
.eval::<bool>("return StaticPopup1Button1:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
s.run("StaticPopup_OnClick(StaticPopup1, 1)").unwrap();
|
||||
assert_eq!(s.take_death_actions(), vec![DeathAction::AcceptResurrect]);
|
||||
@@ -341,7 +341,7 @@ fn corpse_range_events_drive_recover_corpse() {
|
||||
"RECOVER_CORPSE"
|
||||
);
|
||||
assert!(
|
||||
!s.eval::<bool>("return StaticPopup1Button1:IsEnabled()")
|
||||
!s.eval::<bool>("return StaticPopup1Button1:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"Accept is delay-gated"
|
||||
);
|
||||
@@ -358,7 +358,7 @@ fn corpse_range_events_drive_recover_corpse() {
|
||||
"Resurrect now?"
|
||||
);
|
||||
assert!(s
|
||||
.eval::<bool>("return StaticPopup1Button1:IsEnabled()")
|
||||
.eval::<bool>("return StaticPopup1Button1:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
s.run("StaticPopup_OnClick(StaticPopup1, 1)").unwrap();
|
||||
assert_eq!(s.take_death_actions(), vec![DeathAction::RetrieveCorpse]);
|
||||
|
||||
@@ -91,12 +91,12 @@ fn a_fresh_faux_frame_loads_at_the_top_with_no_range() {
|
||||
.unwrap();
|
||||
assert_eq!((lo, hi), (0.0, 0.0));
|
||||
assert!(
|
||||
!s.eval::<bool>("return TestScrollScrollBarScrollUpButton:IsEnabled()")
|
||||
!s.eval::<bool>("return TestScrollScrollBarScrollUpButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"up arrow greyed at load (ref UIPanelTemplates.lua l.245-246)"
|
||||
);
|
||||
assert!(!s
|
||||
.eval::<bool>("return TestScrollScrollBarScrollDownButton:IsEnabled()")
|
||||
.eval::<bool>("return TestScrollScrollBarScrollDownButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
}
|
||||
|
||||
@@ -132,12 +132,12 @@ fn more_rows_than_fit_raise_the_bar_over_the_overflow_range() {
|
||||
"the frame itself too — the ref's own frame:Show(), which is what an addon reads back"
|
||||
);
|
||||
assert!(
|
||||
!s.eval::<bool>("return TestScrollScrollBarScrollUpButton:IsEnabled()")
|
||||
!s.eval::<bool>("return TestScrollScrollBarScrollUpButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"at the top: up greyed"
|
||||
);
|
||||
assert!(s
|
||||
.eval::<bool>("return TestScrollScrollBarScrollDownButton:IsEnabled()")
|
||||
.eval::<bool>("return TestScrollScrollBarScrollDownButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
}
|
||||
|
||||
|
||||
@@ -186,12 +186,6 @@ const KNOWN: &[Known] = &[
|
||||
why: "the reference's /who sort dropdown carries its own handlers over the shared \
|
||||
UIDropDownMenuTemplate; ours takes the template alone.",
|
||||
},
|
||||
Known {
|
||||
frame: "WorldMapPlayer",
|
||||
flag: Flag::Mouse,
|
||||
why: "the reference's map dot has OnEnter -> WorldMapUnit_OnEnter, the name-on-hover \
|
||||
tooltip. Wants that handler, not the flag.",
|
||||
},
|
||||
Known {
|
||||
frame: "WorldStateAlwaysUpFrame",
|
||||
flag: Flag::Mouse,
|
||||
|
||||
@@ -216,8 +216,10 @@ fn the_friend_buttons_follow_the_selection() {
|
||||
push(&mut s, SocialState::default(), "FRIENDLIST_UPDATE");
|
||||
for button in ["SendMessage", "GroupInvite", "RemoveFriend"] {
|
||||
assert!(
|
||||
!s.eval::<bool>(&format!("return FriendsFrame{button}Button:IsEnabled()"))
|
||||
.unwrap(),
|
||||
!s.eval::<bool>(&format!(
|
||||
"return FriendsFrame{button}Button:IsEnabled() ~= 0"
|
||||
))
|
||||
.unwrap(),
|
||||
"{button} is disabled with no friends"
|
||||
);
|
||||
}
|
||||
@@ -232,12 +234,12 @@ fn the_friend_buttons_follow_the_selection() {
|
||||
"FRIENDLIST_UPDATE",
|
||||
);
|
||||
assert!(
|
||||
s.eval::<bool>("return FriendsFrameRemoveFriendButton:IsEnabled()")
|
||||
s.eval::<bool>("return FriendsFrameRemoveFriendButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"an offline friend can still be removed"
|
||||
);
|
||||
assert!(
|
||||
!s.eval::<bool>("return FriendsFrameSendMessageButton:IsEnabled()")
|
||||
!s.eval::<bool>("return FriendsFrameSendMessageButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"…but not whispered"
|
||||
);
|
||||
@@ -459,14 +461,14 @@ fn the_who_buttons_need_a_selected_row() {
|
||||
"WHO_LIST_UPDATE",
|
||||
);
|
||||
assert!(
|
||||
!s.eval::<bool>("return WhoFrameAddFriendButton:IsEnabled()")
|
||||
!s.eval::<bool>("return WhoFrameAddFriendButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"nothing selected yet"
|
||||
);
|
||||
|
||||
s.run("WhoFrameButton2:Click()").unwrap();
|
||||
assert!(s
|
||||
.eval::<bool>("return WhoFrameAddFriendButton:IsEnabled()")
|
||||
.eval::<bool>("return WhoFrameAddFriendButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
let _ = s.take_social_requests();
|
||||
s.run("WhoFrameAddFriendButton:Click()").unwrap();
|
||||
@@ -485,7 +487,7 @@ fn the_who_buttons_need_a_selected_row() {
|
||||
"WHO_LIST_UPDATE",
|
||||
);
|
||||
assert!(
|
||||
!s.eval::<bool>("return WhoFrameAddFriendButton:IsEnabled()")
|
||||
!s.eval::<bool>("return WhoFrameAddFriendButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"a fresh answer drops the old selection"
|
||||
);
|
||||
@@ -663,7 +665,7 @@ fn right_clicking_a_who_row_opens_the_friend_menu() {
|
||||
);
|
||||
// …and a right-click must NOT also select the row (the ref's two branches are exclusive).
|
||||
assert!(
|
||||
!s.eval::<bool>("return WhoFrameAddFriendButton:IsEnabled()")
|
||||
!s.eval::<bool>("return WhoFrameAddFriendButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"right-click does not select"
|
||||
);
|
||||
|
||||
@@ -131,7 +131,7 @@ fn the_unbacked_entries_are_disabled_and_the_rest_are_live() {
|
||||
|
||||
for name in ["GameMenuButtonEditMode", "GameMenuButtonSupport"] {
|
||||
assert!(
|
||||
!s.eval::<bool>(&format!("return {name}:IsEnabled()"))
|
||||
!s.eval::<bool>(&format!("return {name}:IsEnabled() ~= 0"))
|
||||
.unwrap(),
|
||||
"{name} has no panel behind it and must read that way"
|
||||
);
|
||||
@@ -144,7 +144,7 @@ fn the_unbacked_entries_are_disabled_and_the_rest_are_live() {
|
||||
"GameMenuButtonContinue",
|
||||
] {
|
||||
assert!(
|
||||
s.eval::<bool>(&format!("return {name}:IsEnabled()"))
|
||||
s.eval::<bool>(&format!("return {name}:IsEnabled() ~= 0"))
|
||||
.unwrap(),
|
||||
"{name} is live"
|
||||
);
|
||||
@@ -468,12 +468,12 @@ fn logout_and_exit_read_disabled_while_a_countdown_runs() {
|
||||
s.fire_event("PLAYER_CAMPING", vec![]);
|
||||
s.run("ToggleGameMenu(1)").unwrap();
|
||||
assert!(
|
||||
!s.eval::<bool>("return GameMenuButtonLogout:IsEnabled()")
|
||||
!s.eval::<bool>("return GameMenuButtonLogout:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"Logout is dead while the camp timer runs"
|
||||
);
|
||||
assert!(!s
|
||||
.eval::<bool>("return GameMenuButtonQuit:IsEnabled()")
|
||||
.eval::<bool>("return GameMenuButtonQuit:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
|
||||
// With the countdown gone, a re-opened menu has them back.
|
||||
@@ -481,7 +481,7 @@ fn logout_and_exit_read_disabled_while_a_countdown_runs() {
|
||||
s.fire_event("LOGOUT_CANCEL", vec![]);
|
||||
s.run("ToggleGameMenu(1)").unwrap();
|
||||
assert!(s
|
||||
.eval::<bool>("return GameMenuButtonLogout:IsEnabled()")
|
||||
.eval::<bool>("return GameMenuButtonLogout:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
|
||||
}
|
||||
@@ -690,7 +690,7 @@ fn the_bag_row_greys_under_the_menu_without_any_of_it_disappearing() {
|
||||
"closing the menu restores full colour: {toggle:?}"
|
||||
);
|
||||
assert!(
|
||||
s.eval::<bool>("return MainMenuBarBackpackButton:IsEnabled()")
|
||||
s.eval::<bool>("return MainMenuBarBackpackButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"…and the button works again"
|
||||
);
|
||||
|
||||
@@ -273,7 +273,7 @@ fn visible(s: &UiScript, frame: &str) -> bool {
|
||||
}
|
||||
|
||||
fn enabled(s: &UiScript, button: &str) -> bool {
|
||||
s.eval::<bool>(&format!("return {button}:IsEnabled()"))
|
||||
s.eval::<bool>(&format!("return {button}:IsEnabled() ~= 0"))
|
||||
.unwrap_or_else(|e| panic!("{button}:IsEnabled() — {e}"))
|
||||
}
|
||||
|
||||
|
||||
@@ -479,7 +479,7 @@ fn the_active_tab_is_inert_and_toggle_inspect_closes() {
|
||||
|
||||
// NB this engine's `IsEnabled` returns a plain bool, not the live API's 1/nil.
|
||||
assert!(
|
||||
!s.eval::<bool>("return BenillaInspectFrameTab1:IsEnabled()")
|
||||
!s.eval::<bool>("return BenillaInspectFrameTab1:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"the selected tab is disabled (PanelTemplates_SelectTab), so its click is inert"
|
||||
);
|
||||
|
||||
@@ -101,12 +101,12 @@ fn the_page_is_an_options_category_with_the_collapsed_honest_tree() {
|
||||
"Unbind Key exists on this page"
|
||||
);
|
||||
assert!(
|
||||
!s.eval::<bool>("return OptionsFrameContainerUnbind:IsEnabled()")
|
||||
!s.eval::<bool>("return OptionsFrameContainerUnbind:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"…disabled until a capsule is selected"
|
||||
);
|
||||
assert!(s
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled()")
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
// The section tree: the registry's category tokens, first-appearance order — exactly
|
||||
// 1.12's file order — every section a COLLAPSED header row (the era default).
|
||||
@@ -196,7 +196,7 @@ fn the_capture_flow_binds_steals_and_refuses_like_112() {
|
||||
"a selected capsule arms the capture"
|
||||
);
|
||||
assert!(
|
||||
s.eval::<bool>("return OptionsFrameContainerUnbind:IsEnabled()")
|
||||
s.eval::<bool>("return OptionsFrameContainerUnbind:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"Unbind arms with the selection"
|
||||
);
|
||||
|
||||
@@ -94,7 +94,7 @@ fn new_then_pick_an_icon_then_okay_creates_the_macro() {
|
||||
.eval::<bool>("return BenillaMacroPopupFrame:IsVisible()")
|
||||
.unwrap());
|
||||
assert!(
|
||||
!s.eval::<bool>("return BenillaMacroPopupOkayButton:IsEnabled()")
|
||||
!s.eval::<bool>("return BenillaMacroPopupOkayButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"a nameless, iconless macro cannot be created"
|
||||
);
|
||||
@@ -104,7 +104,7 @@ fn new_then_pick_an_icon_then_okay_creates_the_macro() {
|
||||
s.run("BenillaMacroPopupButton_OnClick(BenillaMacroPopupButton1)")
|
||||
.unwrap();
|
||||
assert!(
|
||||
s.eval::<bool>("return BenillaMacroPopupOkayButton:IsEnabled()")
|
||||
s.eval::<bool>("return BenillaMacroPopupOkayButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"a name and an icon enable OKAY"
|
||||
);
|
||||
|
||||
@@ -974,7 +974,8 @@ fn merchant_tabs_drive_buyback_page_and_repair_pair() {
|
||||
.unwrap());
|
||||
assert!(s
|
||||
.eval::<bool>(
|
||||
"return MerchantRepairAllButton:IsShown() and MerchantRepairAllButton:IsEnabled()"
|
||||
"return MerchantRepairAllButton:IsShown() and \
|
||||
MerchantRepairAllButton:IsEnabled() ~= 0"
|
||||
)
|
||||
.unwrap());
|
||||
assert!(s
|
||||
|
||||
@@ -24,7 +24,7 @@ fn load_xml(s: &UiScript, file: &str) {
|
||||
}
|
||||
|
||||
fn enabled(s: &UiScript, button: &str) -> bool {
|
||||
s.eval::<bool>(&format!("return {button}:IsEnabled()"))
|
||||
s.eval::<bool>(&format!("return {button}:IsEnabled() ~= 0"))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
|
||||
@@ -808,7 +808,7 @@ fn the_audio_page_reads_the_cvar_table_on_select() {
|
||||
.eval::<bool>("return OptionsFrameContainerBodyAudio:IsVisible()")
|
||||
.unwrap());
|
||||
assert!(s
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled()")
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
// The music slider holds the stored 0.7 (f32 wobble tolerated), readout "70%".
|
||||
assert!(s
|
||||
@@ -894,10 +894,12 @@ fn the_checkbox_rows_write_flags_and_the_master_greys_ambience() {
|
||||
vec![("MasterSoundEffects".to_string(), "0".to_string())]
|
||||
);
|
||||
assert!(!s
|
||||
.eval::<bool>("return OptionsFrameContainerBodyAudioRowEnableAmbienceCheck:IsEnabled()")
|
||||
.eval::<bool>(
|
||||
"return OptionsFrameContainerBodyAudioRowEnableAmbienceCheck:IsEnabled() ~= 0"
|
||||
)
|
||||
.unwrap());
|
||||
assert!(s
|
||||
.eval::<bool>("return OptionsFrameContainerBodyAudioRowEnableMusicCheck:IsEnabled()")
|
||||
.eval::<bool>("return OptionsFrameContainerBodyAudioRowEnableMusicCheck:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
assert!(s
|
||||
.take_sounds()
|
||||
@@ -911,7 +913,9 @@ fn the_checkbox_rows_write_flags_and_the_master_greys_ambience() {
|
||||
vec![("MasterSoundEffects".to_string(), "1".to_string())]
|
||||
);
|
||||
assert!(s
|
||||
.eval::<bool>("return OptionsFrameContainerBodyAudioRowEnableAmbienceCheck:IsEnabled()")
|
||||
.eval::<bool>(
|
||||
"return OptionsFrameContainerBodyAudioRowEnableAmbienceCheck:IsEnabled() ~= 0"
|
||||
)
|
||||
.unwrap());
|
||||
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
|
||||
}
|
||||
@@ -969,7 +973,7 @@ fn the_graphics_page_reads_the_cvar_table_on_select() {
|
||||
.eval::<bool>("return OptionsFrameContainerBodyGraphics:IsVisible()")
|
||||
.unwrap());
|
||||
assert!(s
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled()")
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
assert!(s
|
||||
.eval::<bool>(
|
||||
@@ -1216,7 +1220,7 @@ fn the_nameplates_page_toggles_the_unit_name_cvars() {
|
||||
.eval::<bool>("return OptionsFrameContainerBodyNameplates:IsVisible()")
|
||||
.unwrap());
|
||||
assert!(s
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled()")
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
// The plate pair leads the page and rides `VPlateMode::default()`: enemy on (the 0167 boot
|
||||
// divergence), friendly off (faithful, 0599).
|
||||
@@ -1321,7 +1325,7 @@ fn the_ui_scale_slider_defers_to_the_apply_button() {
|
||||
.eval::<bool>("return OptionsFrameApplyButton:IsVisible()")
|
||||
.unwrap());
|
||||
assert!(s
|
||||
.eval::<bool>("return OptionsFrameApplyButton:IsEnabled()")
|
||||
.eval::<bool>("return OptionsFrameApplyButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
|
||||
// A second move re-stages the pending value — still nothing queues (0989: the steppers
|
||||
@@ -1600,7 +1604,7 @@ fn the_controls_page_reads_flags_with_the_sticky_inversion() {
|
||||
.eval::<bool>("return OptionsFrameContainerBodyControls:IsVisible()")
|
||||
.unwrap());
|
||||
assert!(s
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled()")
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
assert!(
|
||||
s.eval::<bool>("return OptionsFrameContainerBodyControlsRowStickyTargetCheck:GetChecked()")
|
||||
@@ -2274,7 +2278,7 @@ fn the_combat_page_writes_saved_variable_globals_and_applies_them() {
|
||||
.eval::<bool>("return OptionsFrameContainerBodyCombat:IsVisible()")
|
||||
.unwrap());
|
||||
assert!(s
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled()")
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
|
||||
// Read: each box shows its global, at CombatText.xml's own file-scope value.
|
||||
@@ -2351,7 +2355,7 @@ fn the_combat_master_greys_the_family_and_combo_points_is_class_gated() {
|
||||
|
||||
let enabled = |s: &mut UiScript, row: &str, control: &str| -> bool {
|
||||
s.eval::<bool>(&format!(
|
||||
"return OptionsFrameContainerBodyCombat{row}{control}:IsEnabled() and true or false"
|
||||
"return OptionsFrameContainerBodyCombat{row}{control}:IsEnabled() ~= 0"
|
||||
))
|
||||
.unwrap()
|
||||
};
|
||||
@@ -2575,7 +2579,7 @@ fn the_interface_page_writes_the_three_stock_globals() {
|
||||
.eval::<bool>("return OptionsFrameContainerBodyInterface:IsVisible()")
|
||||
.unwrap());
|
||||
assert!(s
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled()")
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
|
||||
// Read: all three ship on — QuestFrame.xml's "1" (the director's pin), QuestLogFrame.xml's "1"
|
||||
@@ -2657,7 +2661,7 @@ fn the_target_of_target_rows_gate_each_other_and_write_their_globals() {
|
||||
assert!(
|
||||
!s.eval::<bool>(
|
||||
"return OptionsFrameContainerBodyInterfaceRowTargetOfTargetModeDropdownButton \
|
||||
:IsEnabled() and true or false"
|
||||
:IsEnabled() ~= 0"
|
||||
)
|
||||
.unwrap(),
|
||||
"the picker is dead while the switch is off"
|
||||
@@ -2678,7 +2682,7 @@ fn the_target_of_target_rows_gate_each_other_and_write_their_globals() {
|
||||
assert!(
|
||||
s.eval::<bool>(
|
||||
"return OptionsFrameContainerBodyInterfaceRowTargetOfTargetModeDropdownButton \
|
||||
:IsEnabled() and true or false"
|
||||
:IsEnabled() ~= 0"
|
||||
)
|
||||
.unwrap(),
|
||||
"and the picker wakes with it"
|
||||
@@ -3055,7 +3059,7 @@ fn the_defaults_button_is_armed_by_rows_not_by_a_category() {
|
||||
s.run(&format!("OptionsFrameCategoryListRow{key}:Click()"))
|
||||
.unwrap();
|
||||
assert!(
|
||||
s.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled()")
|
||||
s.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"{key}: Defaults is live on a page that has something to reset"
|
||||
);
|
||||
@@ -3065,7 +3069,7 @@ fn the_defaults_button_is_armed_by_rows_not_by_a_category() {
|
||||
s.run("OptionsFrame_SelectCategory(\"NotACategory\")")
|
||||
.unwrap();
|
||||
assert!(
|
||||
!s.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled()")
|
||||
!s.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"Defaults is dead when the selected page has no rows"
|
||||
);
|
||||
@@ -3093,7 +3097,7 @@ fn the_chat_page_toggles_the_chat_bubble_cvars() {
|
||||
.eval::<bool>("return OptionsFrameContainerBodyChat:IsVisible()")
|
||||
.unwrap());
|
||||
assert!(s
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled()")
|
||||
.eval::<bool>("return OptionsFrameContainerDefaults:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
// Read from the table, not from a restated default: bubbles on, party bubbles off.
|
||||
assert!(s
|
||||
@@ -3579,8 +3583,11 @@ fn the_action_bars_page_toggles_the_real_bars() {
|
||||
// Bar 4's row is DEAD while bar 3's is unticked — MultiBarLeft cannot stand without
|
||||
// MultiBarRight (the reference's own rule for this pair, UIOptionsFrame.lua l.722-726).
|
||||
assert!(
|
||||
!s.eval::<bool>(&format!("return {}:IsEnabled()", box_of("RowMultiBar4")))
|
||||
.unwrap(),
|
||||
!s.eval::<bool>(&format!(
|
||||
"return {}:IsEnabled() ~= 0",
|
||||
box_of("RowMultiBar4")
|
||||
))
|
||||
.unwrap(),
|
||||
"Show Right ActionBar 2 is disabled until Show Right ActionBar is on"
|
||||
);
|
||||
|
||||
@@ -3607,8 +3614,11 @@ fn the_action_bars_page_toggles_the_real_bars() {
|
||||
s.run(&format!("{}:Click()", box_of("RowMultiBar3")))
|
||||
.unwrap();
|
||||
assert!(
|
||||
s.eval::<bool>(&format!("return {}:IsEnabled()", box_of("RowMultiBar4")))
|
||||
.unwrap(),
|
||||
s.eval::<bool>(&format!(
|
||||
"return {}:IsEnabled() ~= 0",
|
||||
box_of("RowMultiBar4")
|
||||
))
|
||||
.unwrap(),
|
||||
"bar 3 on wakes bar 4's row"
|
||||
);
|
||||
assert!(shown(&s, "MultiBarRight"));
|
||||
@@ -3630,8 +3640,11 @@ fn the_action_bars_page_toggles_the_real_bars() {
|
||||
assert!(!shown(&s, "MultiBarLeft"), "MultiBarLeft rides on bar 3");
|
||||
assert_eq!(s.eval::<i64>("return SHOW_MULTI_ACTIONBAR_4").unwrap(), 1);
|
||||
assert!(
|
||||
!s.eval::<bool>(&format!("return {}:IsEnabled()", box_of("RowMultiBar4")))
|
||||
.unwrap(),
|
||||
!s.eval::<bool>(&format!(
|
||||
"return {}:IsEnabled() ~= 0",
|
||||
box_of("RowMultiBar4")
|
||||
))
|
||||
.unwrap(),
|
||||
"…and its row goes back to sleep"
|
||||
);
|
||||
|
||||
|
||||
@@ -343,7 +343,7 @@ fn a_scroll_frame_from_the_template_wires_its_bar_two_parents_deep() {
|
||||
(0.0, 0.0)
|
||||
);
|
||||
assert!(!s
|
||||
.eval::<bool>("return MyScrollScrollBarScrollUpButton:IsEnabled()")
|
||||
.eval::<bool>("return MyScrollScrollBarScrollUpButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
assert_eq!(s.eval::<i64>("return MyScroll.offset").unwrap(), 0);
|
||||
|
||||
@@ -369,7 +369,7 @@ fn a_scroll_frame_from_the_template_wires_its_bar_two_parents_deep() {
|
||||
"192px of content in an 80px window — the bar's range is the overflow"
|
||||
);
|
||||
assert!(
|
||||
s.eval::<bool>("return MyScrollScrollBarScrollDownButton:IsEnabled()")
|
||||
s.eval::<bool>("return MyScrollScrollBarScrollDownButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"there is somewhere to scroll to, so the down arrow woke"
|
||||
);
|
||||
@@ -382,7 +382,7 @@ fn a_scroll_frame_from_the_template_wires_its_bar_two_parents_deep() {
|
||||
48.0
|
||||
);
|
||||
assert!(s
|
||||
.eval::<bool>("return MyScrollScrollBarScrollUpButton:IsEnabled()")
|
||||
.eval::<bool>("return MyScrollScrollBarScrollUpButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
|
||||
}
|
||||
|
||||
@@ -111,8 +111,8 @@ fn shipped_gossip_frame_drives_end_to_end() {
|
||||
// so the shared pool starts filling from option 1 at row 1 — decision 0088 §3).
|
||||
let states: (bool, bool, bool, bool) = s
|
||||
.eval(
|
||||
"return GossipRow1:IsVisible(), GossipRow1:IsEnabled(),\n\
|
||||
GossipRow2:IsEnabled(), GossipRow3:IsVisible()",
|
||||
"return GossipRow1:IsVisible(), GossipRow1:IsEnabled() ~= 0,\n\
|
||||
GossipRow2:IsEnabled() ~= 0, GossipRow3:IsVisible()",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
|
||||
@@ -255,7 +255,7 @@ fn request_signature_disables_at_the_wires_requirement_not_at_nine() {
|
||||
.unwrap();
|
||||
show_petition(&mut s);
|
||||
assert!(
|
||||
s.eval::<bool>("return PetitionFrameRequestButton:IsEnabled() and true or false")
|
||||
s.eval::<bool>("return PetitionFrameRequestButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"three of four signatures — still asking"
|
||||
);
|
||||
@@ -264,7 +264,7 @@ fn request_signature_disables_at_the_wires_requirement_not_at_nine() {
|
||||
.unwrap();
|
||||
show_petition(&mut s);
|
||||
assert!(
|
||||
!s.eval::<bool>("return PetitionFrameRequestButton:IsEnabled() and true or false")
|
||||
!s.eval::<bool>("return PetitionFrameRequestButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"four of four — the charter is full, though only four of nine rows are used"
|
||||
);
|
||||
@@ -282,13 +282,13 @@ fn the_sign_button_follows_can_sign_petition() {
|
||||
let mut s = setup();
|
||||
show_petition(&mut s);
|
||||
assert!(s
|
||||
.eval::<bool>("return PetitionFrameSignButton:IsEnabled() and true or false")
|
||||
.eval::<bool>("return PetitionFrameSignButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
|
||||
s.run("BenillaPetitionFixture.canSign = nil").unwrap();
|
||||
show_petition(&mut s);
|
||||
assert!(
|
||||
!s.eval::<bool>("return PetitionFrameSignButton:IsEnabled() and true or false")
|
||||
!s.eval::<bool>("return PetitionFrameSignButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"nil, the era false, disables it"
|
||||
);
|
||||
|
||||
@@ -434,7 +434,7 @@ fn detail_panel_action_buttons_resolve_to_real_onscreen_rects() {
|
||||
"instant text keeps the writing sound: one scratch on the wake tick"
|
||||
);
|
||||
assert!(s
|
||||
.eval::<bool>("return QuestAcceptButton:IsEnabled()")
|
||||
.eval::<bool>("return QuestAcceptButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
assert_eq!(
|
||||
s.eval::<f32>("return QuestDetailTextAlphaFrame:GetAlpha()")
|
||||
@@ -494,7 +494,7 @@ fn write_on_still_fades_when_instant_text_is_off() {
|
||||
"the write-on scratches the WriteQuest quill each tick"
|
||||
);
|
||||
assert!(!s
|
||||
.eval::<bool>("return QuestAcceptButton:IsEnabled()")
|
||||
.eval::<bool>("return QuestAcceptButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
|
||||
// Half a second more runs the 13-char gradient off (40 chars/s): Accept wakes and the block
|
||||
@@ -502,7 +502,7 @@ fn write_on_still_fades_when_instant_text_is_off() {
|
||||
s.tick(0.5);
|
||||
assert!(s.errors().is_empty(), "tick errors: {:?}", s.errors());
|
||||
assert!(s
|
||||
.eval::<bool>("return QuestAcceptButton:IsEnabled()")
|
||||
.eval::<bool>("return QuestAcceptButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
let alpha = s
|
||||
.eval::<f32>("return QuestDetailTextAlphaFrame:GetAlpha()")
|
||||
|
||||
@@ -598,7 +598,7 @@ fn empty_quest_log_hides_rows_and_disables_abandon() {
|
||||
);
|
||||
assert!(!s.eval::<bool>("return QuestLogTitle1:IsVisible()").unwrap());
|
||||
assert!(!s
|
||||
.eval::<bool>("return QuestLogAbandonButton:IsEnabled()")
|
||||
.eval::<bool>("return QuestLogAbandonButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
// The Description header is now Lua-managed (BenillaQuestLogDetail_Clear blanks it) rather than
|
||||
// a static `text=` — it used to float "Description" over the empty-log parchment with no
|
||||
@@ -1226,7 +1226,7 @@ fn share_quest_needs_both_a_sharable_selection_and_a_party() {
|
||||
"quest 1 carries the sharable bit"
|
||||
);
|
||||
assert!(
|
||||
!s.eval::<bool>("return QuestLogPushQuestButton:IsEnabled()")
|
||||
!s.eval::<bool>("return QuestLogPushQuestButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"solo: sharable is not enough"
|
||||
);
|
||||
@@ -1235,7 +1235,7 @@ fn share_quest_needs_both_a_sharable_selection_and_a_party() {
|
||||
s.set_party(party(2));
|
||||
s.fire_event("PARTY_MEMBERS_CHANGED", vec![]);
|
||||
assert!(
|
||||
s.eval::<bool>("return QuestLogPushQuestButton:IsEnabled()")
|
||||
s.eval::<bool>("return QuestLogPushQuestButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"PARTY_MEMBERS_CHANGED alone re-tests the button"
|
||||
);
|
||||
@@ -1249,7 +1249,7 @@ fn share_quest_needs_both_a_sharable_selection_and_a_party() {
|
||||
"quest 2 has no sharable bit"
|
||||
);
|
||||
assert!(
|
||||
!s.eval::<bool>("return QuestLogPushQuestButton:IsEnabled()")
|
||||
!s.eval::<bool>("return QuestLogPushQuestButton:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"in a party: an unsharable selection is still dark"
|
||||
);
|
||||
@@ -1258,12 +1258,12 @@ fn share_quest_needs_both_a_sharable_selection_and_a_party() {
|
||||
s.run("SelectQuestLogEntry(1)").unwrap();
|
||||
s.run("BenillaQuestLogFrame_Update()").unwrap();
|
||||
assert!(s
|
||||
.eval::<bool>("return QuestLogPushQuestButton:IsEnabled()")
|
||||
.eval::<bool>("return QuestLogPushQuestButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
s.set_party(PartyState::default());
|
||||
s.fire_event("PARTY_MEMBERS_CHANGED", vec![]);
|
||||
assert!(!s
|
||||
.eval::<bool>("return QuestLogPushQuestButton:IsEnabled()")
|
||||
.eval::<bool>("return QuestLogPushQuestButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
}
|
||||
|
||||
@@ -1284,7 +1284,7 @@ fn share_quest_is_dark_on_an_empty_log_even_in_a_party() {
|
||||
s.set_party(party(4));
|
||||
s.run("ToggleQuestLog()").unwrap();
|
||||
assert!(!s
|
||||
.eval::<bool>("return QuestLogPushQuestButton:IsEnabled()")
|
||||
.eval::<bool>("return QuestLogPushQuestButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ fn push_raid(s: &mut UiScript, raid: Vec<RaidMemberInfo>) {
|
||||
s.set_party(PartyState {
|
||||
members,
|
||||
leader_index: 0,
|
||||
leader_guid: 0, // the player leads; their guid is unset in this fixture
|
||||
raid,
|
||||
loot_method: "group".into(),
|
||||
master_looter: None,
|
||||
@@ -218,7 +219,7 @@ fn convert_to_raid_is_live_only_for_a_party_leader() {
|
||||
assert!(visible(&s, "RaidFrameRaidDescription"), "solo: the blurb");
|
||||
assert!(visible(&s, "RaidFrameConvertToRaidButton"));
|
||||
assert_eq!(
|
||||
s.eval::<i64>("return RaidFrameConvertToRaidButton:IsEnabled() and 1 or 0")
|
||||
s.eval::<i64>("return RaidFrameConvertToRaidButton:IsEnabled()")
|
||||
.unwrap(),
|
||||
0,
|
||||
"solo there is no party to convert"
|
||||
@@ -240,7 +241,7 @@ fn convert_to_raid_is_live_only_for_a_party_leader() {
|
||||
});
|
||||
s.fire_event("PARTY_MEMBERS_CHANGED", Vec::new());
|
||||
assert_eq!(
|
||||
s.eval::<i64>("return RaidFrameConvertToRaidButton:IsEnabled() and 1 or 0")
|
||||
s.eval::<i64>("return RaidFrameConvertToRaidButton:IsEnabled()")
|
||||
.unwrap(),
|
||||
1,
|
||||
"a party leader can convert"
|
||||
@@ -263,7 +264,7 @@ fn convert_to_raid_is_live_only_for_a_party_leader() {
|
||||
});
|
||||
s.fire_event("PARTY_LEADER_CHANGED", Vec::new());
|
||||
assert_eq!(
|
||||
s.eval::<i64>("return RaidFrameConvertToRaidButton:IsEnabled() and 1 or 0")
|
||||
s.eval::<i64>("return RaidFrameConvertToRaidButton:IsEnabled()")
|
||||
.unwrap(),
|
||||
0,
|
||||
"a party member cannot"
|
||||
@@ -714,7 +715,7 @@ fn the_raid_info_panel_lists_the_saved_lockouts() {
|
||||
]);
|
||||
s.fire_event("UPDATE_INSTANCE_INFO", Vec::new());
|
||||
assert_eq!(
|
||||
s.eval::<i64>("return RaidFrameRaidInfoButton:IsEnabled() and 1 or 0")
|
||||
s.eval::<i64>("return RaidFrameRaidInfoButton:IsEnabled()")
|
||||
.unwrap(),
|
||||
1
|
||||
);
|
||||
@@ -743,7 +744,7 @@ fn the_raid_info_panel_lists_the_saved_lockouts() {
|
||||
s.set_saved_instances(Vec::new());
|
||||
s.fire_event("UPDATE_INSTANCE_INFO", Vec::new());
|
||||
assert_eq!(
|
||||
s.eval::<i64>("return RaidFrameRaidInfoButton:IsEnabled() and 1 or 0")
|
||||
s.eval::<i64>("return RaidFrameRaidInfoButton:IsEnabled()")
|
||||
.unwrap(),
|
||||
0
|
||||
);
|
||||
@@ -781,7 +782,7 @@ fn a_player_with_no_lockouts_loses_the_raid_info_button_on_the_second_answer() {
|
||||
// Answer two, saying the same nothing.
|
||||
s.fire_event("UPDATE_INSTANCE_INFO", Vec::new());
|
||||
assert_eq!(
|
||||
s.eval::<i64>("return RaidFrameRaidInfoButton:IsEnabled() and 1 or 0")
|
||||
s.eval::<i64>("return RaidFrameRaidInfoButton:IsEnabled()")
|
||||
.unwrap(),
|
||||
0,
|
||||
"an empty lockout list is a dead button"
|
||||
|
||||
@@ -64,7 +64,28 @@ use bevy::prelude::*;
|
||||
/// are a *contract addons call by name* AND benilla has no reason to compute them differently.
|
||||
/// Anything we want to own — because our own windows are the consumer — belongs in `assets/ui` as
|
||||
/// our own code, under the reference's names (`BagFrame.xml`'s `ToggleBackpack` is the pattern).
|
||||
pub(crate) const SOURCED: &[&str] = &["Interface\\FrameXML\\ContainerFrame.lua"];
|
||||
pub(crate) const SOURCED: &[&str] = &[
|
||||
"Interface\\FrameXML\\ContainerFrame.lua",
|
||||
// PaperDollFrame.lua earns its place for ONE family: `PaperDollItemSlotButton_OnLoad`/
|
||||
// `_OnEvent`/`_OnClick`/`_Update`/`_UpdateLock`/`_OnEnter`/`_OnUpdate`. Every one of them is
|
||||
// frame-agnostic in exactly the sense rule 2 above means — it acts on `this` and `this:GetID()`
|
||||
// through live APIs, never on a named reference window — which is what makes it safe to hand
|
||||
// an addon's own button. `PaperDollItemSlotButtonTemplate` and `BagSlotButtonTemplate` are
|
||||
// declared over them (CharacterFrame.xml, BagFrame.xml), and pfUI builds its bag bar from the
|
||||
// latter.
|
||||
//
|
||||
// Checked before adding, because this list is a decision:
|
||||
// · TOP-LEVEL is four constants (NUM_RESISTANCE_TYPES, NUM_STATS, NUM_SHOPPING_TOOLTIPS,
|
||||
// ATTACK_POWER_MAGIC_NUMBER). Nothing touches a frame at load, so sourcing cannot raise.
|
||||
// · 18 of its 29 functions COLLIDE with ours (the PaperDollFrame_Set* stat family, the two
|
||||
// damage-frame hovers, PaperDollFormatStat, PaperDollStatTooltip). Order settles all of
|
||||
// them the documented way: this runs before assets/ui, so OUR bodies overwrite the
|
||||
// reference's and keep driving our character sheet. Not one of the seven names we are here
|
||||
// for is in that overlap.
|
||||
// · Our own doll slots keep calling `BenillaPaperDollSlot_*` and are untouched — the sourced
|
||||
// family is new surface for addons, not a replacement for ours.
|
||||
"Interface\\FrameXML\\PaperDollFrame.lua",
|
||||
];
|
||||
|
||||
/// Execute every [`SOURCED`] file into `script`, read off the install's patch chain.
|
||||
///
|
||||
|
||||
@@ -467,7 +467,7 @@ fn clicking_a_bar_opens_the_detail_popup_on_that_faction() {
|
||||
"at war, so the box is ticked"
|
||||
);
|
||||
assert!(
|
||||
!s.eval::<bool>("return ReputationDetailAtWarCheckBox:IsEnabled() and true or false")
|
||||
!s.eval::<bool>("return ReputationDetailAtWarCheckBox:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"peace-forced, so the box is dead"
|
||||
);
|
||||
|
||||
@@ -171,7 +171,8 @@ fn shipped_spellbook_drives_end_to_end() {
|
||||
"Fire Blast"
|
||||
);
|
||||
assert!(
|
||||
!s.eval::<bool>("return SpellButton2:IsEnabled()").unwrap(),
|
||||
!s.eval::<bool>("return SpellButton2:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"book id 7 is past the 2-spell Fire tab — disabled"
|
||||
);
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ fn start_delay_gates_button1_then_swaps_the_text_in() {
|
||||
.unwrap();
|
||||
assert!(s.eval::<bool>("return StaticPopup1:IsVisible()").unwrap());
|
||||
assert!(
|
||||
!s.eval::<bool>("return StaticPopup1Button1:IsEnabled()")
|
||||
!s.eval::<bool>("return StaticPopup1Button1:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"button1 starts disabled under StartDelay"
|
||||
);
|
||||
@@ -102,7 +102,7 @@ fn start_delay_gates_button1_then_swaps_the_text_in() {
|
||||
"delay expiry swaps the real text in"
|
||||
);
|
||||
assert!(
|
||||
s.eval::<bool>("return StaticPopup1Button1:IsEnabled()")
|
||||
s.eval::<bool>("return StaticPopup1Button1:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"delay expiry enables button1"
|
||||
);
|
||||
|
||||
@@ -252,7 +252,7 @@ fn shipped_trainer_frame_drives_end_to_end() {
|
||||
"Cost:"
|
||||
);
|
||||
assert!(s
|
||||
.eval::<bool>("return BenillaTrainerTrainButton:IsEnabled()")
|
||||
.eval::<bool>("return BenillaTrainerTrainButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
|
||||
// Train buys the selected service — the row's spell id reaches the app's drain.
|
||||
@@ -266,7 +266,7 @@ fn shipped_trainer_frame_drives_end_to_end() {
|
||||
s.run("SelectTrainerService(6); BenillaTrainerFrame_Update()")
|
||||
.unwrap();
|
||||
assert!(!s
|
||||
.eval::<bool>("return BenillaTrainerTrainButton:IsEnabled()")
|
||||
.eval::<bool>("return BenillaTrainerTrainButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
s.resolve();
|
||||
assert!(
|
||||
@@ -293,7 +293,7 @@ fn shipped_trainer_frame_drives_end_to_end() {
|
||||
"a known prerequisite shows white with its rank: {reqs}"
|
||||
);
|
||||
assert!(!s
|
||||
.eval::<bool>("return BenillaTrainerTrainButton:IsEnabled()")
|
||||
.eval::<bool>("return BenillaTrainerTrainButton:IsEnabled() ~= 0")
|
||||
.unwrap());
|
||||
|
||||
// The app's client-side close: clear the snapshot + fire TRAINER_CLOSED → the window hides.
|
||||
|
||||
@@ -421,6 +421,9 @@ fn left_clicking_the_player_frame_targets_self() {
|
||||
guid: 0xA11CE,
|
||||
}],
|
||||
leader_index: 0, // we lead
|
||||
// The player's own guid, which this fixture leaves unset — spelled out because a bare 0
|
||||
// is also the reference's "ungrouped" sentinel and this party has a member.
|
||||
leader_guid: 0,
|
||||
raid: Vec::new(),
|
||||
loot_method: "group".into(),
|
||||
master_looter: None,
|
||||
@@ -510,6 +513,7 @@ fn raid_mark_clicks_through_the_nested_level() {
|
||||
guid: 0xA11CE,
|
||||
}],
|
||||
leader_index: 0, // we lead — the mark rows are leader-gated
|
||||
leader_guid: 0, // the player's own guid; this fixture leaves it unset
|
||||
raid: Vec::new(),
|
||||
loot_method: "group".into(),
|
||||
master_looter: None,
|
||||
@@ -1791,6 +1795,8 @@ fn the_player_frame_wears_the_leader_and_master_looter_icons() {
|
||||
guid: 0x7A17,
|
||||
}],
|
||||
leader_index,
|
||||
// Follows `leader_index`: 0 = the player (unset here), else the member who leads.
|
||||
leader_guid: if leader_index == 0 { 0 } else { 0x7A17 },
|
||||
raid: Vec::new(),
|
||||
loot_method: method.into(),
|
||||
master_looter,
|
||||
|
||||
@@ -828,7 +828,7 @@ fn an_idle_unit_popup_driver_parks_itself_off_the_tick() {
|
||||
"an open menu ticks the enable pass"
|
||||
);
|
||||
assert!(
|
||||
!s.eval::<bool>("return DropDownList1Button2:IsEnabled()")
|
||||
!s.eval::<bool>("return DropDownList1Button2:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"Whisper greys against a disconnected target"
|
||||
);
|
||||
@@ -851,7 +851,7 @@ fn an_idle_unit_popup_driver_parks_itself_off_the_tick() {
|
||||
s.tick(0.016);
|
||||
s.resolve();
|
||||
assert!(
|
||||
s.eval::<bool>("return DropDownList1Button2:IsEnabled()")
|
||||
s.eval::<bool>("return DropDownList1Button2:IsEnabled() ~= 0")
|
||||
.unwrap(),
|
||||
"Whisper enables the frame the target reconnects"
|
||||
);
|
||||
|
||||
@@ -20,6 +20,10 @@ fn harness() -> UiScript {
|
||||
"GameTooltip.xml",
|
||||
"UIDropDownMenu.xml", // the map's continent/zone pickers initialize into it at OnLoad
|
||||
"ScrollTemplates.xml",
|
||||
// The blip templates, which WorldMapFrame.xml instantiates with inherits=. Not
|
||||
// optional: an unknown template is a loader WARNING, not an error, so leaving this
|
||||
// out loads clean and then hands every blip a sizeless, anchorless frame.
|
||||
"WorldMapFrameTemplates.xml",
|
||||
"WorldMapFrame.xml",
|
||||
] {
|
||||
let text = std::fs::read_to_string(
|
||||
|
||||
Reference in New Issue
Block a user