diff --git a/crates/benilla-ui/src/script/chat_window.rs b/crates/benilla-ui/src/script/chat_window.rs index 6a19f5eb..297e605e 100644 --- a/crates/benilla-ui/src/script/chat_window.rs +++ b/crates/benilla-ui/src/script/chat_window.rs @@ -1,4 +1,4 @@ -//! The chat window settings bindings: `GetChatWindowInfo`, its setters and `ChatFrame_OpenChat`. +//! The chat window settings bindings: `GetChatWindowInfo` and its setters. //! //! The reference keeps one record per window (`0xb4fe50`, stride 0x98, 10 slots), loaded from and //! saved to `chat-cache.txt`: name `+0x00`, message-group flags `+0x20`, channel names and ids @@ -331,13 +331,6 @@ impl super::UiScript { } } -impl super::UiScript { - /// Drains the texts `ChatFrame_OpenChat` queued since the last call. - pub fn take_open_chat_requests(&mut self) -> Vec { - std::mem::take(&mut self.model_mut().open_chat_requests) - } -} - pub(super) fn install(lua: &Lua) -> mlua::Result<()> { // GetChatWindowInfo(id) → name, fontSize, r, g, b, a, shown, locked, docked. lua.globals().set( @@ -470,19 +463,6 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { })?, )?; - // ChatFrame_OpenChat(text, chatFrame) queues `text` for the host to open the chat box with. The - // frame is inert: in 1.12 every chat frame's `editBox` is the one `ChatFrameEditBox` - // (FloatingChatFrame.lua:30, FloatingChatFrame.xml:742). The stock ChatFrame.lua:1545 defines - // the same global and replaces this one when it loads. - lua.globals().set( - "ChatFrame_OpenChat", - lua.create_function(|lua, (text, _chat_frame): (Option, Value)| { - let mut model = lua.app_data_mut::().expect("model app_data"); - model.open_chat_requests.push(text.unwrap_or_default()); - Ok(()) - })?, - )?; - // ── The rest of the record: name, shown, message groups, channels ────────────────────── // // `SetChatWindowName` `0x4a13f0`, `SetChatWindowShown` `0x4a1730`, @@ -930,21 +910,6 @@ mod tests { s.run("SetChatWindowSize(1, 0)").unwrap(); assert!(s.take_chat_window_changes().is_empty()); } - - #[test] - fn chat_frame_open_chat_queues_its_text_and_ignores_the_frame() { - let mut s = UiScript::new().unwrap(); - s.run("ChatFrame_OpenChat('/w Bob ')").unwrap(); - s.run("ChatFrame_OpenChat('', 'not even a frame')").unwrap(); - assert_eq!( - s.take_open_chat_requests(), - vec!["/w Bob ".to_string(), String::new()] - ); - assert!( - s.take_open_chat_requests().is_empty(), - "the drain is a take" - ); - } } #[cfg(test)] diff --git a/crates/benilla-ui/src/script/craft.rs b/crates/benilla-ui/src/script/craft.rs index 34d98f14..19a74b3d 100644 --- a/crates/benilla-ui/src/script/craft.rs +++ b/crates/benilla-ui/src/script/craft.rs @@ -9,7 +9,7 @@ use mlua::{Lua, MultiValue, Value, Variadic}; -use super::binding_abi::number_arg; +use super::binding_abi::{self, number_arg}; use super::item_stats::item_link; use super::Model; @@ -177,15 +177,6 @@ fn opt_str(lua: &Lua, s: Option<&String>) -> mlua::Result { }) } -/// A `bool` as the reference's `1` or nil. -fn era_bool(b: bool) -> Value { - if b { - Value::Integer(1) - } else { - Value::Nil - } -} - /// Register the craft globals. pub(super) fn install(lua: &Lua) -> mlua::Result<()> { let g = lua.globals(); @@ -362,7 +353,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { if let Some(r) = recipe(&model, index) { for (name, have) in &r.tools { out.push(Value::String(lua.create_string(name)?)); - out.push(era_bool(*have)); + out.push(binding_abi::flag(*have)); } } Ok(MultiValue::from_vec(out)) diff --git a/crates/benilla-ui/src/script/editbox/tests.rs b/crates/benilla-ui/src/script/editbox/tests.rs index e5168dde..8aedec31 100644 --- a/crates/benilla-ui/src/script/editbox/tests.rs +++ b/crates/benilla-ui/src/script/editbox/tests.rs @@ -178,15 +178,16 @@ fn click_focuses_regardless_of_autofocus_and_transition_order_is_lost_then_gaine s.run( r#" log = {} - local function wire(name, y) + local function wire(name, y, autoFocus) local f = CreateFrame("EditBox", name) + f:SetAutoFocus(autoFocus) f:SetPoint("BOTTOMLEFT", nil, "BOTTOMLEFT", 0, y) f:SetWidth(100); f:SetHeight(20) f:SetScript("OnEditFocusGained", function() table.insert(log, "gained"..name) end) f:SetScript("OnEditFocusLost", function() table.insert(log, "lost"..name) end) end - wire("A", 0) -- rect bottom 0..20 - wire("B", 100) -- rect bottom 100..120 + wire("A", 0, true) -- rect bottom 0..20 + wire("B", 100, false) -- rect bottom 100..120: a click focuses it without autoFocus "#, ) .unwrap(); diff --git a/crates/benilla-ui/src/script/guild.rs b/crates/benilla-ui/src/script/guild.rs index b53b4e6b..ff8f9ab4 100644 --- a/crates/benilla-ui/src/script/guild.rs +++ b/crates/benilla-ui/src/script/guild.rs @@ -9,6 +9,7 @@ use mlua::{Lua, MultiValue, Value}; +use super::binding_abi; use super::Model; /// The thirteen rank rights in `GuildControlGetRankFlags`' return order, which is also the @@ -258,16 +259,6 @@ fn truthy(value: &Value) -> bool { } } -/// The 1.12 boolean, `1` or `nil`: the FrameXML stores what it tests, so a `false` would survive -/// where the reference's `nil` does not. -fn era_bool(on: bool) -> Value { - if on { - Value::Integer(1) - } else { - Value::Nil - } -} - /// Whether the player's own rank holds right `index`, 1-based into [`RANK_RIGHT_BITS`]. fn has_right(model: &Model, index: usize) -> bool { model.guild.in_guild && model.guild.rights & RANK_RIGHT_BITS[index - 1] != 0 @@ -305,7 +296,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { "IsInGuild", lua.create_function(|lua, ()| { let model = lua.app_data_ref::().expect("model app_data"); - Ok(era_bool(model.guild.in_guild)) + Ok(binding_abi::flag(model.guild.in_guild)) })?, )?; @@ -314,7 +305,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { "IsGuildLeader", lua.create_function(|lua, ()| { let model = lua.app_data_ref::().expect("model app_data"); - Ok(era_bool(model.guild.is_leader)) + Ok(binding_abi::flag(model.guild.is_leader)) })?, )?; @@ -375,7 +366,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { Value::String(lua.create_string(&m.zone)?), Value::String(lua.create_string(&m.note)?), Value::String(lua.create_string(&m.officer_note)?), - era_bool(m.online), + binding_abi::flag(m.online), Value::String(lua.create_string(&m.status)?), ])) })?, @@ -444,7 +435,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { "GetGuildRosterShowOffline", lua.create_function(|lua, ()| { let model = lua.app_data_ref::().expect("model app_data"); - Ok(era_bool(model.guild.show_offline)) + Ok(binding_abi::flag(model.guild.show_offline)) })?, )?; // With no argument it turns show-offline on, unlike an explicit `nil`, hence `MultiValue`. @@ -593,7 +584,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { global, lua.create_function(move |lua, ()| { let model = lua.app_data_ref::().expect("model app_data"); - Ok(era_bool(has_right(&model, index))) + Ok(binding_abi::flag(has_right(&model, index))) })?, )?; } @@ -653,7 +644,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { Ok(MultiValue::from_vec( RANK_RIGHT_BITS .iter() - .map(|bit| era_bool(rights & bit != 0)) + .map(|bit| binding_abi::flag(rights & bit != 0)) .collect(), )) })?, diff --git a/crates/benilla-ui/src/script/item_stats.rs b/crates/benilla-ui/src/script/item_stats.rs index cbd3bc73..bc78124e 100644 --- a/crates/benilla-ui/src/script/item_stats.rs +++ b/crates/benilla-ui/src/script/item_stats.rs @@ -448,39 +448,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { })?, )?; - // BenillaGetItemStats(itemId) → name, quality, invType, class, subclass, dmgMin, dmgMax, - // dmgType, delayMs, armor, block, sellPrice, or nil and an ask. - lua.globals().set( - "BenillaGetItemStats", - lua.create_function(|lua, item_id: u32| { - let view = { - let mut model = lua.app_data_mut::().expect("model app_data"); - let v = model.item_templates.get(&item_id).cloned(); - if v.is_none() && item_id != 0 { - model.item_stat_asks.insert(item_id); - } - v - }; - let Some(v) = view else { - return Ok(MultiValue::from_vec(vec![Value::Nil])); - }; - let (dmg_min, dmg_max, dmg_type) = v.damages.first().copied().unwrap_or_default(); - Ok(MultiValue::from_vec(vec![ - Value::String(lua.create_string(&v.name)?), - Value::Integer(i64::from(v.quality)), - Value::Integer(i64::from(v.inventory_type)), - Value::Integer(i64::from(v.class)), - Value::Integer(i64::from(v.subclass)), - Value::Number(f64::from(dmg_min)), - Value::Number(f64::from(dmg_max)), - Value::Integer(i64::from(dmg_type)), - Value::Integer(i64::from(v.delay_ms)), - Value::Integer(i64::from(v.armor)), - Value::Integer(i64::from(v.block)), - Value::Integer(i64::from(v.sell_price)), - ])) - })?, - ) + Ok(()) } #[cfg(test)] @@ -580,9 +548,7 @@ mod tests { #[test] fn miss_records_ask_and_push_serves_the_stats() { let mut s = UiScript::new().unwrap(); - assert!(s - .eval::("return BenillaGetItemStats(25) == nil") - .unwrap()); + assert!(s.eval::("return GetItemInfo(25) == nil").unwrap()); assert_eq!(s.take_item_stat_asks(), vec![25]); s.set_item_template( @@ -598,14 +564,13 @@ mod tests { ..Default::default() }, ); - let (name, quality, inv): (String, i64, i64) = - s.eval("return BenillaGetItemStats(25)").unwrap(); - assert_eq!((name.as_str(), quality, inv), ("Worn Shortsword", 1, 21)); + let (name, quality): (String, i64) = s + .eval("local n, _, q = GetItemInfo(25) return n, q") + .unwrap(); + assert_eq!((name.as_str(), quality), ("Worn Shortsword", 1)); assert!(s.take_item_stat_asks().is_empty(), "push cleared the ask"); // Id 0 records no ask. - assert!(s - .eval::("return BenillaGetItemStats(0) == nil") - .unwrap()); + assert!(s.eval::("return GetItemInfo(0) == nil").unwrap()); assert!(s.take_item_stat_asks().is_empty()); } } diff --git a/crates/benilla-ui/src/script/layout.rs b/crates/benilla-ui/src/script/layout.rs index b8faa294..cd35cfff 100644 --- a/crates/benilla-ui/src/script/layout.rs +++ b/crates/benilla-ui/src/script/layout.rs @@ -403,8 +403,6 @@ struct PreambleProf { scroll: u128, /// `region_resolved`'s liveness retain. retain: u128, - /// Never set, so always 0: the frame roster is built inside `fp_frames`. - plan: u128, /// `LayoutScope::begin_full`. begin: u128, /// The fingerprint and scope walk over every live frame. @@ -447,14 +445,13 @@ impl PreambleProf { + self.ids + self.scroll + self.retain - + self.plan + self.begin + self.fp_frames + self.fp_regions + self.seed; eprintln!( "[layout-pre] skips={} incr={} frames={frames} anchored={regions} total_us={total} \ - tooltip={} watched={} ids={} scroll={} retain={} plan={} begin={} \ + tooltip={} watched={} ids={} scroll={} retain={} begin={} \ fp_frames={} fp_regions={} seed={}", u8::from(skips), u8::from(self.incremental), @@ -463,7 +460,6 @@ impl PreambleProf { self.ids, self.scroll, self.retain, - self.plan, self.begin, self.fp_frames, self.fp_regions, diff --git a/crates/benilla-ui/src/script/messageframe/mod.rs b/crates/benilla-ui/src/script/messageframe/mod.rs index f23c9419..76d610e0 100644 --- a/crates/benilla-ui/src/script/messageframe/mod.rs +++ b/crates/benilla-ui/src/script/messageframe/mod.rs @@ -10,6 +10,7 @@ use crate::layout::Rect; use crate::order::ZTarget; +use crate::script::object::frame_handle_of; use crate::widget::{FrameHandle, InsertMode, KindState, MessageLine}; use super::layout::FramePaint; @@ -38,8 +39,6 @@ pub(super) fn message_text(lua: &mlua::Lua, v: &mlua::Value) -> Option { /// Install `SetJustifyH`, `GetJustifyH`, `SetJustifyV` and `GetJustifyV`, which both classes carry, /// under [`crate::justify`]'s rules: an unknown token raises the usage line, and a token of the /// other axis clears this one, so `GetJustifyH()` then answers `"UNKNOWN"`. -use crate::script::object::frame_handle_of; - pub(super) fn install_justify( lua: &mlua::Lua, m: &mlua::Table, diff --git a/crates/benilla-ui/src/script/model.rs b/crates/benilla-ui/src/script/model.rs index f8e1761a..0ffc0597 100644 --- a/crates/benilla-ui/src/script/model.rs +++ b/crates/benilla-ui/src/script/model.rs @@ -280,10 +280,6 @@ pub(crate) struct Model { pub(crate) petition: petition::PetitionState, /// Charter calls (`BuyGuildCharter`, `SignPetition`, `TurnInGuildCharter`, …) queued. pub(crate) petition_requests: Vec, - /// Names `ChatFrame_SendTell` queued; the app opens the chat box prefilled `/w `. - pub(crate) tell_requests: Vec, - /// Draft lines `ChatFrame_OpenChat` queued, for the app to prefill the chat box. - pub(crate) open_chat_requests: Vec, /// Per chat window from `ChatFrame1`, the tint, alpha and font size its tab menu can change. pub(crate) chat_window_looks: [chat_window::ChatWindowLook; chat_window::NUM_CHAT_WINDOWS], /// 0-based windows whose look Lua changed, the persist cue. @@ -1080,8 +1076,6 @@ impl Model { guild_requests: Vec::new(), petition: petition::PetitionState::default(), petition_requests: Vec::new(), - tell_requests: Vec::new(), - open_chat_requests: Vec::new(), // Per window, as the stock dock differs: 1 and 2 are the dock, the rest undocked. chat_window_looks: std::array::from_fn(chat_window::ChatWindowLook::stock), chat_window_changes: HashSet::new(), diff --git a/crates/benilla-ui/src/script/party.rs b/crates/benilla-ui/src/script/party.rs index 3c3200de..e346eb23 100644 --- a/crates/benilla-ui/src/script/party.rs +++ b/crates/benilla-ui/src/script/party.rs @@ -232,12 +232,6 @@ impl super::UiScript { pub fn set_saved_instances(&mut self, saved: Vec) { self.model_mut().saved_instances = saved; } - - /// Drain the names `ChatFrame_SendTell` queued; the app opens the chat edit box on - /// `/w ` for each. - pub fn take_tell_requests(&mut self) -> Vec { - std::mem::take(&mut self.model_mut().tell_requests) - } } /// Whether the player leads the group. `IsRaidLeader` (`0x4bb8c0`) and `IsPartyLeader` @@ -703,18 +697,6 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { })?, )?; - // ChatFrame_SendTell(name) is FrameXML in the reference (`ChatFrame.lua:1606`, opening the - // edit box on `/w name `); the chat edit box is app-side here, so this queues the name for - // `UiScript::take_tell_requests`. - g.set( - "ChatFrame_SendTell", - lua.create_function(|lua, name: String| { - let mut model = lua.app_data_mut::().expect("model app_data"); - model.tell_requests.push(name); - Ok(()) - })?, - )?; - Ok(()) } @@ -1167,15 +1149,6 @@ mod tests { assert!(s.eval::("return IsRaidOfficer() == nil").unwrap()); } - #[test] - fn chat_frame_send_tell_queues_the_name() { - let mut s = UiScript::new().unwrap(); - assert!(s.take_tell_requests().is_empty()); - s.run(r#"ChatFrame_SendTell("Alice")"#).unwrap(); - assert_eq!(s.take_tell_requests(), vec!["Alice".to_string()]); - assert!(s.take_tell_requests().is_empty()); - } - // ── The identity predicates ───────────────────────────────────────────── fn unit(exists: bool, guid: u64) -> crate::script::UnitState { diff --git a/crates/benilla-ui/src/script/petition.rs b/crates/benilla-ui/src/script/petition.rs index 03a8e0c6..3c918d51 100644 --- a/crates/benilla-ui/src/script/petition.rs +++ b/crates/benilla-ui/src/script/petition.rs @@ -6,6 +6,7 @@ use mlua::{Lua, MultiValue, Value}; +use super::binding_abi; use super::Model; /// `GetPetitionInfo`'s first return when the record's charter bit is set (`0x84cf8c`, selected at @@ -131,15 +132,6 @@ pub fn validate_guild_name(name: &str) -> Result<(), &'static str> { Ok(()) } -/// 1.12's `1` or nil, never `true`/`false`: this client has no `lua_pushboolean`. -fn era_bool(on: bool) -> Value { - if on { - Value::Integer(1) - } else { - Value::Nil - } -} - /// A cached name as a string, an uncached one as nil. fn name_value(lua: &Lua, name: Option<&String>) -> mlua::Result { match name { @@ -176,7 +168,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { Value::String(lua.create_string(&r.body_text)?), Value::Integer(i64::from(r.max_signatures)), name_value(lua, r.originator.as_ref())?, - era_bool(r.is_originator), + binding_abi::flag(r.is_originator), ])) })?, )?; @@ -215,7 +207,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { "CanSignPetition", lua.create_function(|lua, ()| { let model = lua.app_data_ref::().expect("model app_data"); - Ok(era_bool(model.petition.can_sign)) + Ok(binding_abi::flag(model.petition.can_sign)) })?, )?; diff --git a/crates/benilla-ui/src/script/quest_log.rs b/crates/benilla-ui/src/script/quest_log.rs index e0e91efa..805bf010 100644 --- a/crates/benilla-ui/src/script/quest_log.rs +++ b/crates/benilla-ui/src/script/quest_log.rs @@ -379,7 +379,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { Value::Integer(i64::from(it.count)), Value::Integer(i64::from(it.quality)), Value::Boolean(it.usable), - // The item id, `BenillaGetItemStats`'s key, a sixth return that is not 1.12's. + // The item id, a sixth return that is not 1.12's. Value::Integer(i64::from(it.item_id)), ])) })?, diff --git a/crates/benilla-ui/src/script/reputation.rs b/crates/benilla-ui/src/script/reputation.rs index 6da59f20..414e3d20 100644 --- a/crates/benilla-ui/src/script/reputation.rs +++ b/crates/benilla-ui/src/script/reputation.rs @@ -12,6 +12,7 @@ use std::collections::HashMap; use mlua::{Lua, MultiValue, Value}; +use super::binding_abi; use super::Model; /// The synthetic header key for factions the player moved to the inactive bucket. @@ -146,15 +147,6 @@ fn collate(a: &str, b: &str) -> std::cmp::Ordering { .then_with(|| a.as_bytes().cmp(b.as_bytes())) } -/// `1` or nil, never `0`: `0` is truthy in Lua, and the stock pane tests `if ( atWarWith )`. -fn era_bool(b: bool) -> Value { - if b { - Value::Integer(1) - } else { - Value::Nil - } -} - /// Build the header groups: the visible non-header rows by [`header_key`], sorted by name. A group /// is named by its pushed header row (the reference synthesizes a missing one, `0x4d5a70`), or left /// empty for a synthetic key; a childless header is no group, as the client's count drops it. @@ -305,7 +297,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { Value::Nil, // atWarWith Value::Nil, // canToggleAtWar Value::Integer(1), // isHeader - era_bool(collapsed), // isCollapsed + binding_abi::flag(collapsed), // isCollapsed Value::Nil, // isWatched ])) } @@ -318,11 +310,11 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { Value::Integer(i64::from(e.bar_min)), Value::Integer(i64::from(e.bar_max)), Value::Integer(i64::from(e.standing)), - era_bool(e.at_war), - era_bool(e.can_toggle_at_war), + binding_abi::flag(e.at_war), + binding_abi::flag(e.can_toggle_at_war), Value::Nil, // isHeader Value::Nil, // isCollapsed - era_bool(model.reputation.watched == Some(e.rep_list_id)), + binding_abi::flag(model.reputation.watched == Some(e.rep_list_id)), ])) } } @@ -412,7 +404,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { "IsFactionInactive", lua.create_function(|lua, index: usize| { let model = lua.app_data_ref::().expect("model app_data"); - Ok(era_bool( + Ok(binding_abi::flag( entry_at(&model, index).is_some_and(|e| e.inactive), )) })?, diff --git a/crates/benilla-ui/src/script/skills.rs b/crates/benilla-ui/src/script/skills.rs index 9f639f6a..978fe5f1 100644 --- a/crates/benilla-ui/src/script/skills.rs +++ b/crates/benilla-ui/src/script/skills.rs @@ -16,6 +16,7 @@ use std::collections::HashMap; use mlua::{Lua, MultiValue, Value}; +use super::binding_abi; use super::Model; /// One known skill line off the player's `PLAYER_SKILL_INFO` block, resolved by the app. @@ -261,15 +262,6 @@ fn displayed_ranks(e: &SkillEntry) -> (i64, i64) { (rank, max) } -/// A `bool` as the 1.12 `1`/nil shape. -fn era_bool(b: bool) -> Value { - if b { - Value::Integer(1) - } else { - Value::Nil - } -} - /// Register the skills-pane globals. pub(super) fn install(lua: &Lua) -> mlua::Result<()> { let g = lua.globals(); @@ -303,7 +295,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { Ok(MultiValue::from_vec(vec![ Value::String(lua.create_string(&grp.name)?), Value::Integer(1), // isHeader - era_bool(expanded), + binding_abi::flag(expanded), Value::Integer(0), // skillRank Value::Integer(0), // numTempPoints Value::Integer(0), // skillModifier @@ -326,7 +318,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { Value::Integer(0), // numTempPoints Value::Integer(i64::from(e.temp_bonus)), // skillModifier: temp only Value::Integer(max), - era_bool(e.abandonable), // isAbandonable + binding_abi::flag(e.abandonable), // isAbandonable // stepCost, rankCost: nil, since Lua reads `0` as true. Value::Nil, Value::Nil, diff --git a/crates/benilla-ui/src/script/social.rs b/crates/benilla-ui/src/script/social.rs index 8b58504a..0e80379c 100644 --- a/crates/benilla-ui/src/script/social.rs +++ b/crates/benilla-ui/src/script/social.rs @@ -95,11 +95,6 @@ impl super::UiScript { pub fn take_social_requests(&mut self) -> Vec { std::mem::take(&mut self.model_mut().social_requests) } - - /// Queue an intent from the app side. - pub fn queue_social_request(&mut self, request: SocialRequest) { - self.model_mut().social_requests.push(request); - } } /// Register the social globals against the snapshot store. diff --git a/crates/benilla-ui/src/script/tooltip_item/mod.rs b/crates/benilla-ui/src/script/tooltip_item/mod.rs index 02dc756e..bc0614e2 100644 --- a/crates/benilla-ui/src/script/tooltip_item/mod.rs +++ b/crates/benilla-ui/src/script/tooltip_item/mod.rs @@ -846,7 +846,6 @@ pub(super) fn install_methods(lua: &Lua, m: &Table) -> mlua::Result<()> { render_view(lua, &this, &v, BuilderFlags::default(), None)?; // Nothing to arm: the vendor tab's row seats `ShoppingTooltip1/2` itself // (`MerchantFrame.xml:67-80`), and the buyback tab seats none. - if buyback {} } None => { // Template in flight: the row's own stat head as a minimal view, the diff --git a/crates/benilla-ui/src/script/tradeskill/api.rs b/crates/benilla-ui/src/script/tradeskill/api.rs index 03eb2134..194aa18e 100644 --- a/crates/benilla-ui/src/script/tradeskill/api.rs +++ b/crates/benilla-ui/src/script/tradeskill/api.rs @@ -2,7 +2,7 @@ use mlua::{Lua, MultiValue, Value}; -use crate::script::binding_abi::number_arg; +use crate::script::binding_abi::{self, number_arg}; use crate::script::item_stats::item_link; use crate::script::Model; @@ -19,15 +19,6 @@ fn opt_str(lua: &Lua, s: Option<&String>) -> mlua::Result { }) } -/// A `bool` as the 1.12 API's `1` or `nil`. -fn era_bool(b: bool) -> Value { - if b { - Value::Integer(1) - } else { - Value::Nil - } -} - /// Register the tradeskill globals. pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> { let g = lua.globals(); @@ -139,7 +130,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> { Value::String(lua.create_string(&name)?), Value::String(lua.create_string("header")?), Value::Integer(0), - era_bool(expanded), + binding_abi::flag(expanded), ])) } Row::Entry(ei) => { @@ -276,7 +267,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> { if let Some(r) = recipe_at(&model, index) { for (name, have) in &r.tools { out.push(Value::String(lua.create_string(name)?)); - out.push(era_bool(*have)); + out.push(binding_abi::flag(*have)); } } Ok(MultiValue::from_vec(out)) @@ -349,16 +340,16 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> { lua.create_function(|lua, index: usize| { let model = lua.app_data_ref::().expect("model app_data"); let Some(t) = model.trade_skill.as_ref() else { - return Ok(era_bool(false)); + return Ok(binding_abi::flag(false)); }; let groups = build_groups(&t.recipes); Ok(match index.checked_sub(1) { - None => era_bool( + None => binding_abi::flag( !groups .iter() .any(|g| model.trade_skill_subclass_hidden.contains(&g.key)), ), - Some(n) => era_bool( + Some(n) => binding_abi::flag( groups .get(n) .is_some_and(|g| !model.trade_skill_subclass_hidden.contains(&g.key)), @@ -425,16 +416,16 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> { lua.create_function(|lua, index: usize| { let model = lua.app_data_ref::().expect("model app_data"); if model.trade_skill.is_none() { - return Ok(era_bool(false)); + return Ok(binding_abi::flag(false)); } let bits = present_inv_slots(&model); Ok(match index.checked_sub(1) { // Everything shown: (present & mask) == present (`0x4fffd0`). - None => era_bool( + None => binding_abi::flag( bits.iter() .all(|&b| model.trade_skill_invslot_mask & (1 << b) != 0), ), - Some(n) => era_bool( + Some(n) => binding_abi::flag( bits.get(n) .is_some_and(|&b| model.trade_skill_invslot_mask & (1 << b) != 0), ), diff --git a/crates/benilla-ui/src/script/trainer/mod.rs b/crates/benilla-ui/src/script/trainer/mod.rs index 070b1f75..f8117bf1 100644 --- a/crates/benilla-ui/src/script/trainer/mod.rs +++ b/crates/benilla-ui/src/script/trainer/mod.rs @@ -6,6 +6,7 @@ use mlua::{Lua, MultiValue, Value}; +use super::binding_abi; use super::Model; /// A service's state (the wire's `TrainerSpellState`): green learnable, red gated, gray known. @@ -424,15 +425,6 @@ fn opt_str(lua: &Lua, s: Option<&String>) -> mlua::Result { }) } -/// A `bool` as the reference's `1` or nil. -fn era_bool(b: bool) -> Value { - if b { - Value::Integer(1) - } else { - Value::Nil - } -} - /// Register the trainer globals. pub(super) fn install(lua: &Lua) -> mlua::Result<()> { let g = lua.globals(); @@ -468,7 +460,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { Value::String(lua.create_string(&g.name)?), Value::Nil, Value::String(lua.create_string("header")?), - era_bool(expanded), + binding_abi::flag(expanded), ])) } Row::Service(si) => { @@ -560,7 +552,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { Ok(MultiValue::from_vec(vec![ Value::String(lua.create_string(&req.name)?), Value::Integer(i64::from(req.rank)), - era_bool(req.met), + binding_abi::flag(req.met), ])) })?, )?; @@ -584,7 +576,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { }; Ok(MultiValue::from_vec(vec![ Value::String(lua.create_string(&req.name)?), - era_bool(req.met), + binding_abi::flag(req.met), ])) })?, )?; @@ -599,7 +591,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { "IsTrainerServiceTradeSkill", lua.create_function(|lua, index: usize| { let model = lua.app_data_ref::().expect("model app_data"); - Ok(era_bool( + Ok(binding_abi::flag( service(&model, index).is_some_and(|s| s.is_trade_skill), )) })?, @@ -612,7 +604,10 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { lua.create_function(|lua, index: usize| { let model = lua.app_data_ref::().expect("model app_data"); let learn = service(&model, index).is_some_and(|s| !s.is_trade_skill); - Ok(MultiValue::from_vec(vec![era_bool(learn), Value::Nil])) + Ok(MultiValue::from_vec(vec![ + binding_abi::flag(learn), + Value::Nil, + ])) })?, )?; @@ -621,7 +616,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { "IsTradeskillTrainer", lua.create_function(|lua, ()| { let model = lua.app_data_ref::().expect("model app_data"); - Ok(era_bool(model.trainer.as_ref().is_some_and(|t| { + Ok(binding_abi::flag(model.trainer.as_ref().is_some_and(|t| { t.trainer_type == TRAINER_TYPE_TRADESKILL }))) })?, @@ -632,7 +627,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { "IsTalentTrainer", lua.create_function(|lua, ()| { let model = lua.app_data_ref::().expect("model app_data"); - Ok(era_bool( + Ok(binding_abi::flag( model.trainer.as_ref().is_some_and(|t| t.trainer_type == 1), )) })?, @@ -656,7 +651,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> { lua.create_function(|lua, kind: String| { let model = lua.app_data_ref::().expect("model app_data"); Ok(match TrainerServiceCategory::from_filter_str(&kind) { - Some(c) => era_bool(model.trainer_filter[c.filter_slot()]), + Some(c) => binding_abi::flag(model.trainer_filter[c.filter_slot()]), None => Value::Nil, }) })?, diff --git a/crates/benilla-ui/src/widget/tests.rs b/crates/benilla-ui/src/widget/tests.rs index 3dcbfdc0..523d2e8d 100644 --- a/crates/benilla-ui/src/widget/tests.rs +++ b/crates/benilla-ui/src/widget/tests.rs @@ -114,10 +114,10 @@ fn level_shift_saturates_at_zero() { let root = a.create(FrameKind::Frame, None, None); let child = a.create(FrameKind::Frame, None, Some(root)); a.set_frame_level(root, 10, true); - a.set_frame_level(child, 12, true); - // Root drops by 10, taking the child from 12 to 2. + a.set_frame_level(child, 3, true); + // Root drops by 10, which would take the child to -7: it stops at 0. a.set_frame_level(root, 0, true); - assert_eq!(a.frame(child).unwrap().level, 2); + assert_eq!(a.frame(child).unwrap().level, 0); } // ── Scale ────────────────────────────────────────────────────────────────────────────────────