Return numeric flags from spell-targeting predicates (#764)

Use binding_abi::flag for SpellIsTargeting and SpellCanTargetUnit so addons
can compare their results with 1, as in 1.12.1. Keep nil for false.

Verified on Windows with Rust 1.98.1: three regression failures before
the fix, all 35 focused spell tests passing after it, formatting and
render-pass lint clean. The full UI run passed 1677 tests, with one
ignored and one traceback-name failure reproduced on untouched main.

Fixes #711
This commit is contained in:
Andrew Barnes
2026-10-02 13:45:16 +07:00
committed by GitHub
parent 4fd0c643a6
commit c627483a85
4 changed files with 21 additions and 19 deletions
@@ -800,7 +800,7 @@ mod tests {
.expect("the feed runs");
world
.non_send_resource::<UiScript>()
.eval::<bool>(&format!("return SpellCanTargetUnit({token:?}) == true"))
.eval::<bool>(&format!("return SpellCanTargetUnit({token:?}) == 1"))
.expect("a boolean")
};
for token in ["pettarget", "playertarget", "PETTARGET", "target"] {
@@ -988,7 +988,7 @@ mod tests {
.expect("the feed runs");
let hover = world
.non_send_resource::<UiScript>()
.eval::<bool>(&format!("return SpellCanTargetUnit({token:?}) == true"))
.eval::<bool>(&format!("return SpellCanTargetUnit({token:?}) == 1"))
.expect("a boolean");
assert_eq!(hover, binds, "{label}: the hover verdict");
@@ -1226,7 +1226,7 @@ mod tests {
.expect("the feed runs");
let hover = world
.non_send_resource::<UiScript>()
.eval::<bool>(&format!("return SpellCanTargetUnit({token:?}) == true"))
.eval::<bool>(&format!("return SpellCanTargetUnit({token:?}) == 1"))
.expect("a boolean");
assert_eq!(hover, binds, "{label}: the hover verdict");
@@ -1279,7 +1279,7 @@ mod tests {
.expect("the feed runs");
world
.non_send_resource::<UiScript>()
.eval::<bool>(&format!("return SpellCanTargetUnit({token:?}) == true"))
.eval::<bool>(&format!("return SpellCanTargetUnit({token:?}) == 1"))
.expect("a boolean")
};
assert!(can(10.0, HEAL, "target"), "in range");
+14 -12
View File
@@ -604,23 +604,19 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> {
})?,
)?;
// SpellIsTargeting() (`0x6e6cd0`): true while the targeting cursor is up, else nil.
// SpellIsTargeting() (`0x6e6cd0`): 1 while the targeting cursor is up, else nil.
g.set(
"SpellIsTargeting",
lua.create_function(|lua, ()| {
let model = lua.app_data_ref::<Model>().expect("model app_data");
if model.spell_targeting {
Ok(Value::Boolean(true))
} else {
Ok(Value::Nil)
}
Ok(flag(model.spell_targeting))
})?,
)?;
// SpellCanTargetUnit("unit") (`0x6e6d00`): the argument is a string or a number (`0x6e6d0e`,
// else `Usage:`), resolved through `0x515970` (`0x6e6d3a`), which raises for a token it does
// not know; a token naming nobody answers nil (`0x6e6d43`), and a guid asks `0x6e6460`'s unit
// leg whether the standing word clears against it.
// leg whether the standing word clears against it, answering 1 or nil.
g.set(
"SpellCanTargetUnit",
lua.create_function(|lua, unit: Value| {
@@ -634,11 +630,7 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> {
.unit_guids
.guid_of(&token)?
.is_some_and(|guid| model.spell_targetable_units.contains(&guid));
if can {
Ok(Value::Boolean(true))
} else {
Ok(Value::Nil)
}
Ok(flag(can))
})?,
)?;
@@ -667,6 +659,16 @@ mod tests {
use crate::script::cursor::{CursorAction, CursorPayload};
use crate::script::UiScript;
#[test]
fn spell_is_targeting_answers_one_or_nil() {
let mut s = UiScript::new().unwrap();
assert!(s.eval::<bool>("return SpellIsTargeting() == nil").unwrap());
s.set_spell_targeting(true);
assert!(s.eval::<bool>("return SpellIsTargeting() == 1").unwrap());
s.set_spell_targeting(false);
assert!(s.eval::<bool>("return SpellIsTargeting() == nil").unwrap());
}
/// Two tabs: Fire (Fireball, and Fire Blast marked passive) and Frost (Frost Armor).
fn book() -> SpellBookState {
SpellBookState {
@@ -272,7 +272,7 @@ fn spell_can_target_unit_answers_the_verdict_of_the_unit_the_token_names() {
let mut s = world();
s.set_spell_targetable_units([BOSS, P1]);
let can = |s: &UiScript, token: &str| {
s.eval::<bool>(&format!("return SpellCanTargetUnit({token:?}) == true"))
s.eval::<bool>(&format!("return SpellCanTargetUnit({token:?}) == 1"))
.unwrap()
};
let refused = |s: &UiScript, token: &str| {
+2 -2
View File
@@ -69,10 +69,10 @@ fn spell_can_target_unit_answers_per_validated_token() {
});
s.set_spell_targetable_units([0x10, 0x21]);
assert!(s
.eval::<bool>(r#"return SpellCanTargetUnit("player") == true"#)
.eval::<bool>(r#"return SpellCanTargetUnit("player") == 1"#)
.unwrap());
assert!(s
.eval::<bool>(r#"return SpellCanTargetUnit("PARTY1") == true"#)
.eval::<bool>(r#"return SpellCanTargetUnit("PARTY1") == 1"#)
.unwrap());
assert!(s
.eval::<bool>(r#"return SpellCanTargetUnit("target") == nil"#)