- a player build ships beside the dev one — dev chords and probe surfaces go dark, and a gate enforces what a player can still reach, by medium not by module - the binary carries its own shaders and its shipped UI, finds the WoW folder by itself, and keeps its local state in one benilla-config folder - the glue screens get a capture shutter, and the engine stops depending on the protocol crate Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
51 lines
2.4 KiB
Rust
51 lines
2.4 KiB
Rust
//! `emdump <internal\path.m2>` — every particle emitter one model authors, one line each.
|
|
//!
|
|
//! The per-emitter counterpart to `benilla-extract partcensus`, which answers "which models in the
|
|
//! corpus carry emitters matching this flag mask?" but never what an individual emitter *is*. B16
|
|
//! needed the other direction — the voidwalker's eye glow is emitters 1 and 2 of four, bone 60/61,
|
|
//! flags `0x0001` (plain anchored), `Add`/`GLOWBALL.BLP` — and reading that off a hex dump by hand
|
|
//! is exactly the kind of asset fact that should be one command.
|
|
//!
|
|
//! The header line carries the model's **reach** (how far its own transparent-pass batches sort
|
|
//! from its origin — `m2_owner_reach`) and the `Transparent3d` draw-order rung it produces
|
|
//! (`owner_last_rung`): the rung is what keeps a model's effects drawing after its own transparent
|
|
//! batches, and it is sized from that number, so the two belong on screen together.
|
|
|
|
fn main() -> anyhow::Result<()> {
|
|
let virt = std::env::args().nth(1).unwrap();
|
|
let data = benilla_formats::wow_data().expect("no WoW install found (set $WOW_DATA)");
|
|
let mut chain = benilla_formats::open_chain(&data)?;
|
|
let bytes = chain.read_file(&virt)?;
|
|
let dir = virt.rsplit_once('\\').map_or("", |(d, _)| d);
|
|
let subs = benilla_formats::parse_m2_render_submeshes(&bytes, dir, &[]).unwrap_or_default();
|
|
// The renderer's own bound and rung, not a re-derivation of them: a survey tool has to print
|
|
// what the renderer will actually do.
|
|
let reach = benilla_formats::m2_owner_reach(&subs);
|
|
let rung = benilla_formats::owner_last_rung(reach);
|
|
println!("{virt}: reach {reach:.3} yd -> draw-order rung {rung:.0}");
|
|
for (i, e) in benilla_formats::parse_m2_particle_emitters(&bytes)?
|
|
.iter()
|
|
.enumerate()
|
|
{
|
|
let now = e.params.sample(None, 0.0, 0.0);
|
|
println!(
|
|
"emitter {i}: bone {:>3} flags {:#06x} model_space={} pos ({:.4},{:.4},{:.4}) blend {:?} \
|
|
shape {:?} speed {:.4}±{:.4} grav {:.4} life {:.4} tex {:?}",
|
|
e.bone,
|
|
e.flags,
|
|
e.model_space(),
|
|
e.position[0],
|
|
e.position[1],
|
|
e.position[2],
|
|
e.blend,
|
|
e.shape,
|
|
now.emission_speed,
|
|
now.speed_variation,
|
|
now.gravity,
|
|
now.lifespan,
|
|
e.texture,
|
|
);
|
|
}
|
|
Ok(())
|
|
}
|