The slam macro was never ours, and a fixture I invented is why I said otherwise

grom reports `/cast [noslamclip] Slam; [slamclip] Heroic Strike` never picking
Slam. Yesterday I drove the whole chain in the harness, measured a 44% no-clip
window and called it healthy. The 44% came from a cast time I supplied:

    s.set_spell_tooltip(1464, … cast_time: Some("1.5 sec cast") …)

**OctoWoW's Slam is a 2.5 s cast.** `Spell.dbc` ids 1464/8820/11604/11605 all
carry `CastingTimeIndex` 20 and `SpellCastTimes.dbc` row 20 is 2500 ms, where
vanilla's Slam is 1500. SuperCleveRoidMacros' own
`DEFAULT_SLAM_CAST = 2.5 -- Turtle WoW` agrees independently. Against his 2.70 s
weapon the window is `(2.70 - 2.50) / 2.70` = 7.4%, 0.2 s wide — not something a
hand can hit, which is the whole report.

The same DBC gives every Slam rank `spellLevel` 54, and he is level 14. The
field alignment is checked against spells whose levels are known (Heroic Strike
rank 1/2/3 = 1/8/16, Charge 4, Shield Bash 12, Overpower 12, Thunder Clap 6),
so that reading is safe to act on: 477 Heroic Strikes in his combat log and zero
Slams, in any session since 10/12.

The fixtures now carry the realm's numbers and `WINDOW_PCT` carries where they
come from, including this mistake — a number I supply cannot test anything, and
a green test then argues against the player's own report.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
2026-10-30 09:02:47 -06:00
co-authored by Claude Opus 5
parent 89dc99f4d1
commit 11c01d07ad
@@ -24,6 +24,22 @@ use super::{
};
/// Plates a crowded pull shows; the nameplate CVar cap and `pfValidUnits`' own range.
/// `CleveRoids.GetSlamWindowPercent()` for grom's own numbers, as Lua prints it.
///
/// `(mainhand - slamCast) / mainhand * 100` = `(2.70 - 2.50) / 2.70 * 100`. **Both numbers are
/// the realm's, not vanilla's.** Slam on OctoWoW is a 2.5 s cast — `Spell.dbc` id 1464 (and 8820,
/// 11604, 11605) carries `CastingTimeIndex` 20, and `SpellCastTimes.dbc` row 20 is 2500 ms, where
/// vanilla's Slam is 1.5 s. SuperCleveRoidMacros' own `DEFAULT_SLAM_CAST = 2.5 -- Turtle WoW`
/// agrees independently.
///
/// So the no-clip window on a 2.70 s weapon is **0.2 s wide, 7.4% of the swing**, and a player
/// pressing the macro by hand will almost never land in it. That is the macro's arithmetic, not
/// a fault of this client — and it is worth a constant with this comment on it, because an
/// earlier revision of these tests invented a `1.5 sec cast` fixture, measured a 44% window off
/// it, and concluded the chain was healthy while the player's own sessions cast Heroic Strike 477
/// times and Slam never once.
const WINDOW_PCT: &str = "7.4074074074074";
const PLATES: u32 = 40;
/// Frames per timed window.
@@ -1587,7 +1603,7 @@ fn the_whole_slam_macro_line_picks_slam_early_and_heroic_strike_late() {
);
assert_eq!(
ask(&mut s, "CleveRoids.GetSlamCastTime()"),
"1.5",
"2.5",
"the cast time came off the scanning tooltip, not the addon's 2.5 s fallback — against a \
2.70 s swing the fallback leaves a 7% window instead of 44%, which in play reads as \
`[noslamclip]` never being true at all"
@@ -1599,14 +1615,15 @@ fn the_whole_slam_macro_line_picks_slam_early_and_heroic_strike_late() {
// `VANILLA_SWING_MS` stand-in — and `st_timer` is still 0, so the whole swing reads as
// elapsed:
//
// window = (2.0 - 1.5) / 2.0 = 25%, elapsed = 100% -> `[noslamclip]` false -> Heroic Strike.
// maxSlamStart = 2.0 - 2.50 <= 0 -> window 0%, elapsed 100% -> `[noslamclip]` false ->
// Heroic Strike.
//
// That is correct of the numbers it has and wrong about the weapon, and it heals on the first
// auto-attack that lands (below). It is also why the latch is worth a log line
// (`char_stats::with_unit_stats`): if the sheet never arrives, this *is* the session.
assert_eq!(ask(&mut s, "st_timerMax"), "2");
assert_eq!(ask(&mut s, "CleveRoids.GetSwingPercentElapsed()"), "100");
assert_eq!(ask(&mut s, "CleveRoids.GetSlamWindowPercent()"), "25");
assert_eq!(ask(&mut s, "CleveRoids.GetSlamWindowPercent()"), "0");
assert_eq!(
ask(&mut s, "CleveRoids.ValidateNoSlamClip()"),
"false",
@@ -1635,8 +1652,8 @@ fn the_whole_slam_macro_line_picks_slam_early_and_heroic_strike_late() {
assert_eq!(ask(&mut s, "CleveRoids.GetSwingPercentElapsed()"), "0");
assert_eq!(
ask(&mut s, "CleveRoids.GetSlamWindowPercent()"),
"44.444444444444",
"(2.70 - 1.50) / 2.70, off the real weapon this time"
WINDOW_PCT,
"(2.70 - 2.50) / 2.70, off the real weapon this time — 0.2 s of a 2.7 s swing"
);
let _ = s.take_spell_casts();
s.fire_event(
@@ -1650,12 +1667,12 @@ fn the_whole_slam_macro_line_picks_slam_early_and_heroic_strike_late() {
`GetSwingPercentElapsed` and `GetSlamWindowPercent` above before anything else"
);
// 1.6 s later the swing is 59% elapsed, past the window: the second clause takes it.
// 1.6 s later the swing is 59% elapsed, far past the window: the second clause takes it.
s.tick(1.6);
assert_eq!(
ask(&mut s, "CleveRoids.ValidateNoSlamClip()"),
"false",
"59% elapsed is past the 44% window, so casting Slam now would clip the auto-attack"
"59% elapsed is past the 7.4% window, so casting Slam now would clip the auto-attack"
);
let _ = s.take_spell_casts();
s.fire_event(
@@ -1745,7 +1762,7 @@ fn seat_a_warrior_mid_fight(s: &mut UiScript, offhand: bool) {
..Default::default()
}));
for (id, name, cast) in [
(1464u32, "Slam", Some("1.5 sec cast".to_string())),
(1464u32, "Slam", Some("2.5 sec cast".to_string())),
(78, "Heroic Strike", None),
(23922, "Shield Slam", None),
] {
@@ -1823,14 +1840,12 @@ fn seat_a_warrior_mid_fight(s: &mut UiScript, offhand: bool) {
/// * The spellbook walk `GetSpellName(i, BOOKTYPE_SPELL)` finding Slam.
/// * `GameTooltip:SetSpell` on a **nil-parent scanning tooltip built from
/// `GameTooltipTemplate`**, whose `<name>TextLeft<i>` the addon reads with `getglobal` looking
/// for `"%d+%.?%d* sec cast"`. This is the one that decides the size of the window: without it
/// the addon falls back to a 2.5 s constant, which against a 2.70 s swing leaves a 7% window
/// instead of 44% and would read in play as "Slam never fires".
/// for `"%d+%.?%d* sec cast"`. This is the one that decides the size of the window.
/// * The `<OnUpdate>` delta reaching `SP_ST_OnUpdate(arg1)` as seconds.
///
/// **All five answer correctly** once the sheet is pushed, with a 44.4% window off a 1.5 s
/// scanned cast time — and the asymmetry this test originally only *documented* turned out to be
/// the whole defect. It is the first bullet's edge: before the stats feed has pushed,
/// **All five answer correctly** once the sheet is pushed — see [`WINDOW_PCT`] for the window
/// they produce and for the fixture mistake that made an earlier revision of this test read as a
/// clean bill of health while the macro was still picking Heroic Strike every time. It is the first bullet's edge: before the stats feed has pushed,
/// `UnitAttackSpeed("player")` answered `0`, and SP_SwingTimer's `ADDON_LOADED` arm latches that
/// into `st_timerMax` behind `if not st_timerMax` — where `0` is truthy, so the guard never
/// re-fires. The first write to that global in a session is therefore always the pre-push answer.
@@ -1878,7 +1893,7 @@ fn the_slam_clip_conditional_answers_on_the_players_own_interface() {
rank: Some("Rank 1".into()),
cost: Some("15 Rage".into()),
range: Some("Melee Range".into()),
cast_time: Some("1.5 sec cast".into()),
cast_time: Some("2.5 sec cast".into()),
description: "Slams the opponent.".into(),
..Default::default()
},
@@ -1934,10 +1949,11 @@ fn the_slam_clip_conditional_answers_on_the_players_own_interface() {
// The scanning tooltip: a nil parent, the shipped template, and `getglobal` down the lines.
assert_eq!(
ask(&mut s, "CleveRoids.GetSlamCastTime()"),
"1.5",
"the cast time came off the scanning tooltip, not the addon's 2.5 s fallback — the \
fallback leaves a 7% window against a 2.70 s swing and reads as `[noslamclip]` never \
being true"
"2.5",
"the cast time came off the scanning tooltip. On this realm it happens to equal the \
addon's own 2.5 s fallback, so a scan that silently failed would read identically — what \
this pins is that the `sec cast` line is reachable at all through a nil-parent \
`GameTooltipTemplate`. [`WINDOW_PCT`] carries where the 2.5 comes from"
);
// The latch, before any swing. This loader runs the addon walk before the `set_*` calls
// above, exactly as `load_ingame_ui_on_world_entry` runs it before any feed system — so this
@@ -1984,8 +2000,9 @@ fn the_slam_clip_conditional_answers_on_the_players_own_interface() {
);
assert_eq!(
ask(&mut s, "CleveRoids.GetSlamWindowPercent()"),
"44.444444444444",
"(2.70 - 1.50) / 2.70 — the share of the swing in which Slam still beats the auto-attack"
WINDOW_PCT,
"(2.70 - 2.50) / 2.70 — the share of the swing in which Slam still beats the \
auto-attack: 0.2 s of 2.7, which is the whole story of this macro on this weapon"
);
assert_eq!(
ask(&mut s, "CleveRoids.ValidateNoSlamClip()"),