From a893a7205cf7e8f1dbeb239f2ab8cd113f932884 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 17 Sep 2026 16:40:49 +0700 Subject: [PATCH] meeting stones join, the claw trail draws, and the gun flashes - a right-click on a meeting stone joins its queue: the stone's own join packet with its four refusals, and the stone you are queued at goes dark on the minimap frame (2283) - the druid's Swipe draws its claw trail: spell effects run their authored texture scroll, each on its own cast's clock (2282) - a gun's muzzle blast plays: the weapon model runs its own release animation, whose emitters were authored on the rifle and never had a clock (2281, 2286) - README: battlegrounds are the one big feature left on the roadmap, now that meeting stones are in Co-Authored-By: Claude Fable 5.1 --- README.md | 4 +- crates/benilla-app/src/bowstring.rs | 39 +- crates/benilla-app/src/capture/fxview.rs | 12 +- crates/benilla-app/src/capture/mod.rs | 2 + crates/benilla-app/src/capture/probe_env.rs | 5 + crates/benilla-app/src/capture/probe_stone.rs | 432 +++++++++ crates/benilla-app/src/creature_anim.rs | 23 + .../benilla-app/src/creature_anim/events.rs | 10 + .../benilla-app/src/creature_anim/impact.rs | 1 + crates/benilla-app/src/debug_panel/inspect.rs | 8 +- crates/benilla-app/src/dev.rs | 7 + crates/benilla-app/src/entities.rs | 4 + .../benilla-app/src/entities/attach/dress.rs | 4 + .../benilla-app/src/entities/attach/merge.rs | 4 + .../src/entities/attach/redress.rs | 4 + crates/benilla-app/src/entities/dest_fx.rs | 12 +- crates/benilla-app/src/entities/display.rs | 25 + .../src/entities/equipment/spawn.rs | 277 +++++- crates/benilla-app/src/entities/item_glow.rs | 12 +- crates/benilla-app/src/entities/missile.rs | 16 +- .../benilla-app/src/entities/spell_fx/mod.rs | 126 ++- crates/benilla-app/src/game_plugins.rs | 51 +- crates/benilla-app/src/go_templates.rs | 41 +- crates/benilla-app/src/lib.rs | 1 + crates/benilla-app/src/net.rs | 5 + crates/benilla-app/src/net/io.rs | 1 + crates/benilla-app/src/ranged_flex.rs | 627 +++++++++++++ crates/benilla-app/src/target/click.rs | 132 ++- crates/benilla-app/src/target/cursor_mode.rs | 51 +- crates/benilla-app/src/target/hover.rs | 42 +- crates/benilla-app/src/ui_dialog_verbs.rs | 357 +++++++- crates/benilla-app/tests/ui_script_wall.rs | 19 +- crates/benilla-app/tests/world_api_wall.rs | 24 +- .../src/bin/benilla-extract/main.rs | 38 + .../src/bin/benilla-extract/scan/material.rs | 845 +++++++++++++++++- .../src/bin/benilla-extract/scan/mod.rs | 7 +- .../tests/m2_swipe_claw_trail.rs | 105 +++ .../src/messages/meeting_stone.rs | 36 +- crates/benilla-protocol/src/messages/mod.rs | 4 +- .../benilla-protocol/src/messages/opcode.rs | 10 + .../src/world/writer/meeting_stone.rs | 13 +- .../benilla-world/src/doodad_anim/mat_anim.rs | 519 +++++++++-- crates/benilla-world/src/doodad_anim/mod.rs | 5 +- crates/benilla-world/src/particles.rs | 11 + crates/benilla-world/src/rig_anim/compose.rs | 24 +- crates/benilla-world/src/rig_palette.rs | 12 +- crates/benilla-world/src/rig_rider.rs | 129 ++- 47 files changed, 3946 insertions(+), 190 deletions(-) create mode 100644 crates/benilla-app/src/capture/probe_stone.rs create mode 100644 crates/benilla-app/src/ranged_flex.rs create mode 100644 crates/benilla-formats/tests/m2_swipe_claw_trail.rs diff --git a/README.md b/README.md index 6fd67597..aa6f4c9d 100644 --- a/README.md +++ b/README.md @@ -51,8 +51,8 @@ benilla is done when a 1.12.1 player can do everything here that they could in t client, it looks and feels the same, and it runs from a download on Windows, Linux and macOS. No dates; the order is what is likely, not a promise. -- Battlegrounds and meeting stones, then the long tail of small features that separates a - working client from a finished one. +- Battlegrounds, then the long tail of small features that separates a working client from a + finished one. - Addons, options and performance, ongoing. - The no-brainer fixes from VanillaFixes, SuperWoW and the like. - Playable downloads for Windows, Linux and macOS. Linux first. diff --git a/crates/benilla-app/src/bowstring.rs b/crates/benilla-app/src/bowstring.rs index c8068a47..617a477d 100644 --- a/crates/benilla-app/src/bowstring.rs +++ b/crates/benilla-app/src/bowstring.rs @@ -7,10 +7,14 @@ //! //! Benilla's transcription draws the two segments through Bevy's gizmo lines — the same //! immediate-mode screen-space-width primitive class as the client's GX lines. Named -//! deviations (decision record): the string color/width are INFERRED (the callback emits a -//! packed vertex color the round didn't decode — a dark cord is used); the bow prop is not yet -//! animated (BowPull/BowRelease bend the limbs and carry the tips with them in the ref — our -//! anchors ride the static prop frame, so the limbs stay straight while the middle draws). +//! deviation (decision record): the string color/width are INFERRED (the callback emits a +//! packed vertex color the round didn't decode — a dark cord is used). +//! +//! **The tips are POSED** (decision 2281). The bow prop animates — `$BWP` arms BowPull(160) on the +//! prop's own model and `$BWR` returns it to Stand(0) — so the `$WTT`/`$WTB` markers ride limb +//! bones that bend through the draw. Composing them through the prop's rigid root frame instead +//! (which is all this file could do while the prop rested at bind pose) leaves the chord pinned to +//! the un-bent limb tips while the mesh around it moves: the string would visibly leave the bow. use bevy::prelude::*; @@ -28,15 +32,21 @@ const HAND_ARROW: u16 = 0x23; pub(crate) struct Bowstring { /// The unit wearing the bow — the HandArrow middle vertex and nock latch live on it. pub(crate) owner: Entity, - /// The `$WTT` top / `$WTB` bottom anchors, model-local Bevy space (the prop root's frame). - pub(crate) top: Vec3, - pub(crate) bottom: Vec3, + /// The `$WTT` top / `$WTB` bottom anchors as `(bone, model-local Bevy offset)` — the bone is + /// load-bearing on an animated prop (see the module note): the limb tips move with the draw. + pub(crate) top: (u16, Vec3), + pub(crate) bottom: (u16, Vec3), } /// Draw every visible bow's string (per frame, post-propagation so the prop/joint frames are /// this frame's). Two segments: tip → middle → tip. fn draw_bowstrings( - bows: Query<(&Bowstring, &GlobalTransform, &InheritedVisibility)>, + bows: Query<( + &Bowstring, + &GlobalTransform, + &InheritedVisibility, + Option<&benilla_world::rig_anim::RigPose>, + )>, owners: Query<( &BoneAttach, &benilla_world::rig_anim::RigPose, @@ -47,12 +57,19 @@ fn draw_bowstrings( ) { // A dark waxed-cord tone; the ref's packed vertex color is not decoded (INFERRED, §G2). const STRING_COLOR: Color = Color::srgb(0.12, 0.10, 0.08); - for (bs, prop, vis) in &bows { + for (bs, prop, vis, flex) in &bows { if !vis.get() { continue; } - let top = prop.transform_point(bs.top); - let bottom = prop.transform_point(bs.bottom); + // The prop's own pose when it flexes (`joints_root` IS this entity, so its + // `GlobalTransform` is the frame `posed_point` wants); its rigid frame otherwise, which is + // the same answer for a bow standing at bind pose. + let tip = |(bone, offset): (u16, Vec3)| { + flex.and_then(|p| p.posed_point(prop, bone, offset)) + .unwrap_or_else(|| prop.transform_point(offset)) + }; + let top = tip(bs.top); + let bottom = tip(bs.bottom); // The middle control point: the owner's HandArrow attach world position while the nock // latch holds (the drawn string follows the hand), else the relaxed straight chord. let middle = owners diff --git a/crates/benilla-app/src/capture/fxview.rs b/crates/benilla-app/src/capture/fxview.rs index b23e661e..2d6d59cb 100644 --- a/crates/benilla-app/src/capture/fxview.rs +++ b/crates/benilla-app/src/capture/fxview.rs @@ -12,7 +12,7 @@ use super::{FxViewRequest, FxViewState, FXVIEW_POS}; use crate::creature_anim::FxStage; use crate::entities::display::{empty_shell, ModelHandle}; use crate::entities::spell_fx::{ - attach_effect_visuals, EffectHost, FxTintAnims, SpellFx, FALLBACK_SPAN, + attach_effect_visuals, EffectHost, FxMaterials, FxTintAnims, SpellFx, FALLBACK_SPAN, }; /// The `fxview` unit lane's synthetic guid (`WOW_FX_DISPLAY`) — a high-word `0xF130` creature guid @@ -38,6 +38,8 @@ pub(crate) fn drive_fx_view( time: Res