From 911f974e098d6e8d7e97edfd954c349a58cdfc8d Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 17 Aug 2026 17:26:18 +0700 Subject: [PATCH] the Rookery eggs hatch, and the bubble finds its height MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - UBRS's Rookery eggs hatch on approach now: the trap's despawn-anim packet was silently dropped and the entity freed the instant the destroy landed — the packet is parsed, and the reference's refcount pin holds the egg alive through its 2.7 s burst before it goes - the AQ drakes' crawl is the server's doing: vmangos flies cyclic paths at walk speed, and the client's ride measures exact against the wire — the motion is inspectable now, down to a per-spline trace - the chat bubble sits at the height 1.12 gives it: a latched constant from the model's stand box, replacing the posed-attachment anchor the RE just refuted - the trigger-creature render gate folds back from the binary, byte citations corrected Co-Authored-By: Claude Fable 5 --- crates/benilla-app/src/chat_bubble.rs | 82 +++---- crates/benilla-app/src/debug_panel/inspect.rs | 42 +++- crates/benilla-app/src/entities.rs | 18 ++ crates/benilla-app/src/entities/attach/mod.rs | 13 +- crates/benilla-app/src/entities/display.rs | 12 ++ crates/benilla-app/src/go_anim.rs | 204 ++++++++++++++++-- crates/benilla-app/src/net/apply.rs | 3 + crates/benilla-app/src/net/apply/objects.rs | 38 +++- crates/benilla-app/src/net/motion/spline.rs | 84 +++++++- crates/benilla-formats/src/models/bounds.rs | 34 ++- .../tests/chat_bubble_anchor_height.rs | 77 +++++++ .../tests/m2_go_rookery_egg.rs | 95 ++++++++ crates/benilla-protocol/src/events.rs | 7 + crates/benilla-protocol/src/events/decode.rs | 3 + .../src/messages/gameobject.rs | 24 +++ .../benilla-protocol/src/messages/opcode.rs | 12 ++ .../benilla-protocol/src/messages/packet.rs | 9 + crates/benilla-protocol/src/messages/parse.rs | 4 + 18 files changed, 698 insertions(+), 63 deletions(-) create mode 100644 crates/benilla-formats/tests/chat_bubble_anchor_height.rs create mode 100644 crates/benilla-formats/tests/m2_go_rookery_egg.rs diff --git a/crates/benilla-app/src/chat_bubble.rs b/crates/benilla-app/src/chat_bubble.rs index 6a84c944..49364655 100644 --- a/crates/benilla-app/src/chat_bubble.rs +++ b/crates/benilla-app/src/chat_bubble.rs @@ -27,7 +27,11 @@ //! PLAIN (`||`→`|`, color/hyperlink escapes stripped — [`sanitize`]). //! - **Anchor** (`0x4b0c30`): `worldZ = unit.z + attachmentHeight·modelScale + 0.7`, projected //! by the plate/name projector, seated **BOTTOM at the point, growing upward** (the mirror -//! of the plate, which hangs down). +//! of the plate, which hangs down). `attachmentHeight` is `0x4b0e38 call 0x711a20` — a read of +//! the **MD20 header image**, i.e. the **Stand sequence CAaBox's Z extent**, a file constant +//! with no bone matrix anywhere in its call tree — and the scaled product is **latched** at +//! `bubble+0x354` behind a parity guard, so it is queried exactly **once per chat line** +//! ([`crate::entities::StandBoxHeight`], wow-re's anchor cross-check 2026-08-17; 1406). //! //! Named divergences (all deliberate, decisions 0598/0599): //! - **`ChatBubblesParty` defaults ON** (binary default "0") — the director asked for `/p` @@ -37,10 +41,14 @@ //! bubbles too — but that category claim is INFERRED on an OPEN wire-type remap //! (chat-bubble.md §1) and contradicts the remembered reference look, so the uncontested //! set ships and a capture can widen it ([`bubble_cvar`]). -//! - **The anchor height is the posed overhead attachment** ([`overhead_anchor`], the -//! `0x608640` chain) rather than the client's `0x711a20` model-attachment query — the -//! attachment behind `0x711a20` is not identified in the note (INFERRED equivalence; both -//! are "the head-region attachment height, model-scaled"). +//! - ~~**The anchor height is the posed overhead attachment**~~ — **REFUTED and removed (1406).** +//! This shipped as an INFERRED equivalence ("both are the head-region attachment height, +//! model-scaled") between the overhead-name chain `0x608640` and the bubble's `0x711a20`. They +//! are not equivalent, and they differ on exactly the axis that mattered: `0x608640` reads the +//! live posed palette and tracks the pose, `0x711a20` reads file bytes. The overhead *name* +//! keeps `0x608640`; the bubble now takes the Stand-box constant the bytes actually specify. It +//! sits **0.199 model units lower** on a human male (2.0128 vs the attachment's 2.2120) — a +//! deliberate, measured move toward the reference, not a regression. //! - **Sizes ride the plates' damped diagonal basis** ([`plate_basis`], decisions 0185/0186) //! so bubble text and plate text stay the same em at every window — the same director-pinned //! deviation from the unbounded byte law. @@ -60,7 +68,7 @@ use benilla_ui::layout::Rect as GxRect; use benilla_ui::script::{inset_atlas_bleed, pieces, Backdrop, Insets}; use benilla_ui::script::{JustifyH, JustifyV, Outline}; -use crate::entities::{overhead_anchor, BoneAttach, OverheadFallback}; +use crate::entities::StandBoxHeight; use crate::net::{Embodied, Guid, NetEntity, SelfGuid}; use crate::ui_chat::{default_color, ChatEventKind}; use crate::ui_pass::{UiQuad, UiQuadAppend, UiQuads, UvRect}; @@ -282,6 +290,11 @@ struct Bubble { born: f32, /// The steady window past the fade-in ([`duration_secs`]). duration: f32, + /// The **latched** anchor height above the speaker's feet: the Stand box's Z extent + /// ([`crate::entities::StandBoxHeight`]) already multiplied by the unit's model scale, queried + /// ONCE here and never re-read — the reference caches exactly this product at `bubble+0x354` + /// behind a parity guard, so it is one query per chat line (1406). + lift: f32, /// Current fade alpha 0..1 — ramped 250 ms linear toward the eligibility verdict. alpha: f32, } @@ -355,14 +368,8 @@ fn drive_bubbles( mut atlas: Option>, mut quads: ResMut, art: Option>, - // The overhead-anchor inputs ([`overhead_anchor`]). - anchor_q: ( - Query<&BoneAttach>, - Query<&benilla_world::rig_anim::RigPose>, - Query<&OverheadFallback>, - Query<&GlobalTransform>, - Query<(), With>, - ), + // The latched anchor height, read once per bubble at spawn ([`StandBoxHeight`]). + heights: Query<&StandBoxHeight>, time: Res