the mailbox takes typing again, and events carry their real arguments
- the mail window's send tab takes typing again: the subject, body and money boxes were taking no input while the recipient box swallowed every key, and a sent letter clears its subject and item icon instead of putting them straight back (2145) - seven events fire the way the reference does: UNIT_DYNAMIC_FLAGS fires at all, swapping two identical stacks between bank slots fires PLAYERBANKSLOTS_CHANGED twice, the pet sheet's training points repaint, and ITEM_LOCK_CHANGED loses its invented arguments (2140) - nine widget methods 1.12 addons probe for are in: ShaguTweaks stops recolouring textures the reference leaves alone, pfUI and _Nameplates stop raising on a tooltip's GetAnchorType, and 63 AceEvent addons get RegisterAllEvents (2142) - six post-1.12 methods leave the widget surface (SetSize, SetShown, HasFocus, SetFormattedText and two tooltip verbs), so an addon reaching for a later client's API finds what a real 1.12 client gives it (2142, 2146) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -3,11 +3,11 @@
|
||||
//! through the parent's `with_unit`/`pick_unit_token` helpers.
|
||||
//!
|
||||
//! **Every predicate here returns through one function** — [`super::unit_predicate`] when it reads
|
||||
//! a snapshot field, [`predicate`] when it computes its own bool. Neither ever hands mlua a Rust
|
||||
//! `bool`: all 29 of the reference's unit predicates push the constant double `1.0`
|
||||
//! (`lua_pushnumber 0x6f3810`) or `nil` (`lua_pushnil 0x6f37f0`), exactly one value at every live
|
||||
//! `ret`, and **no binding in the 83-entry table at `0x850438` calls `lua_pushboolean 0x6f39f0` at
|
||||
//! all** (decisions 1830, 2043, 2048). A new predicate that open-codes
|
||||
//! a snapshot field, [`flag`](super::super::binding_abi::flag) when it computes its own bool.
|
||||
//! Neither ever hands mlua a Rust `bool`: all 29 of the reference's unit predicates push the
|
||||
//! constant double `1.0` (`lua_pushnumber 0x6f3810`) or `nil` (`lua_pushnil 0x6f37f0`), one value
|
||||
//! at every live `ret`, and **no binding in the 83-entry table at `0x850438` calls
|
||||
//! `lua_pushboolean 0x6f39f0` at all** (decisions 1830, 2043, 2048). A new predicate that open-codes
|
||||
//! `Value::Integer(1)`/`Value::Nil`, or returns a `bool`, is the drift those records exist to stop.
|
||||
//!
|
||||
//! **The scope of that claim is the unit table, not "the binding surface"** — 2043 said the wider
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
use mlua::{Lua, Value};
|
||||
|
||||
use super::super::binding_abi::predicate;
|
||||
use super::super::binding_abi::flag;
|
||||
use super::super::Model;
|
||||
use super::{
|
||||
check_unit_token, classification_word, grey_band, level_reads_unknown, pick_unit_token,
|
||||
@@ -112,7 +112,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
})?;
|
||||
// One value, and it is the NUMBER 1 or nil — never a boolean, the same shape the
|
||||
// rest of this family answers in.
|
||||
Ok(predicate(hit))
|
||||
Ok(flag(hit))
|
||||
})?,
|
||||
)?;
|
||||
}
|
||||
@@ -154,7 +154,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
.as_ref()
|
||||
.and_then(|t| model.unit(t))
|
||||
.map_or(0, |u| u.guid);
|
||||
Ok(predicate(by_flag || guid == model.party.leader_guid))
|
||||
Ok(flag(by_flag || guid == model.party.leader_guid))
|
||||
})?,
|
||||
)?;
|
||||
|
||||
@@ -417,7 +417,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
)?);
|
||||
let token = pick_unit_token(&a, &b);
|
||||
let r = with_unit(lua, &token, 0u8, |u| u.reaction)?;
|
||||
Ok(predicate((1..=2).contains(&r)))
|
||||
Ok(flag((1..=2).contains(&r)))
|
||||
})?,
|
||||
)?;
|
||||
g.set(
|
||||
@@ -437,7 +437,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
)?);
|
||||
let token = pick_unit_token(&a, &b);
|
||||
let r = with_unit(lua, &token, 0u8, |u| u.reaction)?;
|
||||
Ok(predicate(r >= 5))
|
||||
Ok(flag(r >= 5))
|
||||
})?,
|
||||
)?;
|
||||
|
||||
@@ -467,7 +467,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
)?);
|
||||
let model = lua.app_data_ref::<Model>().expect("model app_data");
|
||||
let player_level = model.player_req.level;
|
||||
Ok(predicate(
|
||||
Ok(flag(
|
||||
unit.and_then(|u| model.unit(&u))
|
||||
.is_some_and(|u| super::is_civilian_kill(u, player_level)),
|
||||
))
|
||||
@@ -482,7 +482,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
"UnitPlayerControlled",
|
||||
lua.create_function(|lua, unit: Option<String>| {
|
||||
let model = lua.app_data_ref::<Model>().expect("model app_data");
|
||||
Ok(predicate(
|
||||
Ok(flag(
|
||||
unit.and_then(|u| model.unit(&u))
|
||||
.is_some_and(|u| u.player_controlled),
|
||||
))
|
||||
@@ -525,7 +525,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
if !ua.exists || !ub.exists {
|
||||
return Ok(Value::Nil);
|
||||
}
|
||||
Ok(predicate(a == b || (ua.guid != 0 && ua.guid == ub.guid)))
|
||||
Ok(flag(a == b || (ua.guid != 0 && ua.guid == ub.guid)))
|
||||
})?,
|
||||
)?;
|
||||
|
||||
@@ -549,7 +549,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
"Usage: UnitAffectingCombat(\"unit\")",
|
||||
)?;
|
||||
let hot = with_unit(lua, &Some(token), false, |u| u.exists && u.in_combat)?;
|
||||
Ok(predicate(hot))
|
||||
Ok(flag(hot))
|
||||
})?,
|
||||
)?;
|
||||
|
||||
@@ -578,7 +578,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
"HasFullControl",
|
||||
lua.create_function(|lua, ()| {
|
||||
let model = lua.app_data_ref::<Model>().expect("model app_data");
|
||||
Ok(predicate(model.player_control))
|
||||
Ok(flag(model.player_control))
|
||||
})?,
|
||||
)?;
|
||||
|
||||
@@ -617,7 +617,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
!model.party.members.is_empty()
|
||||
};
|
||||
let hit = grouped && (in_group(u.guid) || in_group(u.owner));
|
||||
Ok(predicate(hit))
|
||||
Ok(flag(hit))
|
||||
})?,
|
||||
)?;
|
||||
}
|
||||
@@ -638,7 +638,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
.iter()
|
||||
.any(|m| m.guid != 0 && m.guid == u.guid)
|
||||
});
|
||||
Ok(predicate(hit))
|
||||
Ok(flag(hit))
|
||||
})?,
|
||||
)?;
|
||||
|
||||
@@ -668,7 +668,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
.members
|
||||
.iter()
|
||||
.any(|m| m.guid != 0 && m.guid == u.guid)));
|
||||
Ok(predicate(hit))
|
||||
Ok(flag(hit))
|
||||
})?,
|
||||
)?;
|
||||
|
||||
@@ -695,7 +695,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
let ok = with_unit(lua, &token, false, |u| {
|
||||
u.exists && u.is_player && u.reaction >= 5
|
||||
})?;
|
||||
Ok(predicate(ok))
|
||||
Ok(flag(ok))
|
||||
})?,
|
||||
)?;
|
||||
|
||||
@@ -895,7 +895,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
r#"Usage: UnitHasRelicSlot("unit")"#,
|
||||
)?);
|
||||
let has = with_unit(lua, &token, false, |u| u.has_relic_slot)?;
|
||||
Ok(predicate(has))
|
||||
Ok(flag(has))
|
||||
})?,
|
||||
)?;
|
||||
|
||||
@@ -1210,7 +1210,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
"IsResting",
|
||||
lua.create_function(|lua, ()| {
|
||||
let model = lua.app_data_ref::<Model>().expect("model app_data");
|
||||
Ok(predicate(model.resting))
|
||||
Ok(flag(model.resting))
|
||||
})?,
|
||||
)?;
|
||||
// PartialPlayTime() / NoPlayTime() → 1/nil: the two anti-addiction play-time regimes, read
|
||||
@@ -1223,14 +1223,14 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
"PartialPlayTime",
|
||||
lua.create_function(|lua, ()| {
|
||||
let model = lua.app_data_ref::<Model>().expect("model app_data");
|
||||
Ok(predicate(model.partial_play_time))
|
||||
Ok(flag(model.partial_play_time))
|
||||
})?,
|
||||
)?;
|
||||
g.set(
|
||||
"NoPlayTime",
|
||||
lua.create_function(|lua, ()| {
|
||||
let model = lua.app_data_ref::<Model>().expect("model app_data");
|
||||
Ok(predicate(model.no_play_time))
|
||||
Ok(flag(model.no_play_time))
|
||||
})?,
|
||||
)?;
|
||||
// GetBillingTimeRested() → the account's rested billing MINUTES, as one number, always
|
||||
@@ -1456,7 +1456,7 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
if had {
|
||||
model.target_clear = true;
|
||||
}
|
||||
Ok(predicate(had))
|
||||
Ok(flag(had))
|
||||
})?,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
//!
|
||||
//! **Every predicate in this family answers the number `1` or `nil`, never a Lua boolean**, and it
|
||||
//! answers it through the one helper — [`unit_predicate`], over
|
||||
//! [`super::binding_abi::predicate`]. Decision 2043; the law is 1830's, which settled the same
|
||||
//! [`super::binding_abi::flag`]. Decision 2043; the law is 1830's, which settled the same
|
||||
//! question for the widget predicates a family earlier.
|
||||
//!
|
||||
//! v1 gaps, stated not hidden: the snapshot carries only the *active* power slot (see the
|
||||
@@ -217,6 +217,24 @@ pub struct UnitState {
|
||||
/// and `0x1000`/`0x2000` (the play-time regimes) all move without touching either. Firing off
|
||||
/// the decoded pair would silently under-announce every one of them.
|
||||
pub player_flags: u32,
|
||||
/// `UNIT_DYNAMIC_FLAGS` (descriptor index 143), raw — what **`UNIT_DYNAMIC_FLAGS`** the
|
||||
/// *event* fires on, the [`Self::flags`] pattern a hundred fields over.
|
||||
///
|
||||
/// The event is id **137**, and the id is not arbitrary: the reference's generic bridge
|
||||
/// `0x51bbb0` registers one watch per unit-window field whose name-table slot is non-NULL, and
|
||||
/// the id it dispatches is that field's own window index — `137 + 6 = 143`, this field.
|
||||
/// Byte-verified here rather than taken from the note: `0xbe1198 + 137*4 = 0xbe13bc` has
|
||||
/// exactly one writer image-wide (`0x51ad8b`), and the pointer it stores resolves to
|
||||
/// `"UNIT_DYNAMIC_FLAGS"`. The watch **length** is 4 — selector byte `[0x51bc98 + 137] = 4`,
|
||||
/// jump-table entry `0x51bbf9 mov eax,4` — so the gate is a `repe cmpsb` over exactly this one
|
||||
/// dword against the object's shadow copy (`0x4655bb`), and **any** bit moving fires it.
|
||||
///
|
||||
/// Raw for the same reason [`Self::player_flags`] is, and the cost of getting it wrong is
|
||||
/// larger here: this struct decodes four of its bits ([`Self::tapped`],
|
||||
/// [`Self::tapped_by_player`], and — through the store — lootable `0x1` and dead-looking
|
||||
/// `0x20`), while `0x2` (tracked, Hunter's Mark) and `0x10` moves without touching any of
|
||||
/// them. Firing off the decoded subset would silently under-announce those.
|
||||
pub dynamic_flags: u32,
|
||||
/// The unit's owner — `UNIT_FIELD_SUMMONEDBY`, else its charmer, else its creator; `0` for
|
||||
/// nobody's. What `UnitPlayerOrPetInParty`/`InRaid` read for the "or pet" half (1958).
|
||||
pub owner: u64,
|
||||
@@ -757,7 +775,7 @@ fn with_unit<T>(
|
||||
/// Rust `bool`, and mlua pushes tag 1. That is the one shape 1.12 cannot produce: `UnitExists`
|
||||
/// (`0x515fb0`) pushes `lua_pushnumber` (`0x6f3810`, tag 3, the double `1.0`) or `lua_pushnil`
|
||||
/// (`0x6f37f0`, tag 0) and nothing else, and so does every other predicate in the family. So the
|
||||
/// whole family goes through [`super::binding_abi::predicate`] — 1830's widget law, which is the
|
||||
/// whole family goes through [`super::binding_abi::flag`] — 1830's widget law, which is the
|
||||
/// *same* law, finally applied to the unit surface (decision 2043). A predicate that hand-computes
|
||||
/// its own bool calls that helper directly; one that reads a snapshot field calls this. Both end at
|
||||
/// the one push site, which is what stops the family drifting apart again.
|
||||
@@ -770,9 +788,7 @@ fn unit_predicate(
|
||||
token: &Option<String>,
|
||||
f: impl FnOnce(&UnitState) -> bool,
|
||||
) -> mlua::Result<mlua::Value> {
|
||||
Ok(super::binding_abi::predicate(with_unit(
|
||||
lua, token, false, f,
|
||||
)?))
|
||||
Ok(super::binding_abi::flag(with_unit(lua, token, false, f)?))
|
||||
}
|
||||
|
||||
/// The `Unit*`/`GetQuestGreenRange` Lua binding registrations — split from this module's
|
||||
|
||||
Reference in New Issue
Block a user