Files
benilla-octo/crates/benilla-formats/tests/m2_sequence_bounds.rs
T
Sam SungandClaude Opus 5.5 8952d590e6 comments cite the reference by address, not by private note (#30)
Comments that pointed into the maintainer's private reverse-engineering notes (a note by name, a
path, a section or finding id, the analysis's own name for a client function, a process word) now
carry the fact itself, cited by the reference client's address, by vmangos file and line, or as
"the reference". Nobody outside could follow those pointers.

Comment text only, plus the test-assert and log strings that carried the same pointers. No claim
changes: a comment the notes have since corrected keeps its wording here, and correcting it is
separate work.

The two reference generators, `scripts/gen-reference-globals.py` and
`scripts/gen-reference-verb-events.py`, named the private notes' layout to find their inputs. They
now take the input files as arguments (`--capture`, `--framexml`, `--names`, `--extents`,
`--disasm`). Run on the same inputs, both write the committed tables row for row; only the two
header lines that named the old environment variable change.

Checked per file:
- the code is identical: each file with its comments stripped compares equal before and after; a
  changed string literal is compared under a mask that proves only literal text moved and every
  literal kept its line count;
- no client address the old text cited was dropped;
- a second reviewer checked every added address against its derivation;
- a detector for the notes' names, paths, ids, function names and process words finds none left;
- `scripts/gates.sh` is green.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 12:14:08 +07:00

43 lines
2.0 KiB
Rust

//! Pins the per-sequence bounds-sphere parse (`M2Sequence` CAaBox @+0x24/+0x30, radius @+0x3c) on
//! real build-5875 unit models. This sphere is the mouse-pick **broad phase** for the model's
//! current animation (`0x7089c0`): if it parsed as
//! zero or a sliver, the faithful pick would reject clicks the reference accepts. Skips when the
//! gitignored client data isn't present.
use benilla_formats::{open_chain, parse_m2_animations};
#[test]
fn stand_sequence_bounds_sphere_is_body_scale() {
let data = benilla_formats::wow_data_or_skip!();
let chain = open_chain(&data).expect("open chain");
// (model, Stand bounds-sphere radius read off the real files). Note the chicken: its sphere
// (0.30) is *smaller* than its ring footprint (0.57) — the ring's nested-sqrt inflates small
// extents — so no ring-relative bound holds in general; the parsed values themselves are the pin.
for (path, radius) in [
("Creature\\Chicken\\Chicken.mdx", 0.304_f32),
("Creature\\Horse\\Horse.mdx", 2.019),
("Creature\\Wolf\\Wolf.mdx", 1.963),
("Creature\\Kobold\\Kobold.mdx", 0.970),
("Character\\Human\\Male\\HumanMale.mdx", 1.118),
] {
// The chain stores `.m2`; the DBC-style `.mdx` spelling normalizes (as the loaders do).
let bytes = chain
.read(&path.to_ascii_lowercase().replace(".mdx", ".m2"))
.expect("read m2");
let anims = parse_m2_animations(&bytes);
let stand = anims
.iter()
.find(|a| a.anim_id == 0)
.expect("Stand sequence");
assert!(
(stand.bounds_radius - radius).abs() < 5e-3,
"{path}: Stand bounds sphere {:.3}, expected {radius:.3}",
stand.bounds_radius
);
// The centre sits above the feet (positive raw-WoW Z), inside the sphere — a zeroed/garbage
// box would fail one of these.
assert!(stand.bounds_center[2] > 0.0 && stand.bounds_center[2] < stand.bounds_radius * 2.0);
}
}