From a1359d8df138a9f57b163da3ed5d83f57a0db142 Mon Sep 17 00:00:00 2001 From: grom Date: Sat, 17 Oct 2026 19:00:59 -0600 Subject: [PATCH] gameobject: a nameless or modelless object says so, for the hardcore graves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "note that they are not corpses but actual grave stones from hardcore deaths, custom twow stuff" — so the corpse plate was never the path, and the three corpse legs added last commit cannot see this at all. A hardcore gravestone is one of the server's own GameObjects, which reaches a plate through `go_inputs.templates` and a mesh pick, not through `CORPSE_FIELD_OWNER`. Two lines, one per failure shape, each said once: - a display id that names no model (`entities::display`, built once per id and cached). This is the quiet one: a GameObject with no model draws nothing *and* cannot be hovered, because the pick set is built from its mesh parts — so a custom display whose `GameObjectDisplayInfo` row this chain's DBC does not carry has no tooltip for exactly the reason it has no art. - a hovered object with no template yet (`ui_tooltip`), the plate's only silent exit. A line with no sequel means the `SMSG_GAMEOBJECT_QUERY_RESPONSE` never came, and a server's own entry is where that is most likely. Neither line on the next grave he walks past would mean the object is picked and named, and the fault is in the plate itself rather than upstream of it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn --- crates/benilla-app/src/entities/display.rs | 9 +++++++++ crates/benilla-app/src/ui_tooltip/mod.rs | 12 +++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/benilla-app/src/entities/display.rs b/crates/benilla-app/src/entities/display.rs index 66bc19ba..c096a160 100644 --- a/crates/benilla-app/src/entities/display.rs +++ b/crates/benilla-app/src/entities/display.rs @@ -227,6 +227,15 @@ pub(super) fn new_gameobject_display( asset_server: &AssetServer, ) -> DisplayModel { let Some(path) = catalog.model_path(display_id) else { + // One line per display id, since a display is built once and cached. A GameObject with no + // model draws nothing *and* cannot be hovered — the pick set is built from mesh parts + // (`GoPickPart`), so there is nothing for the ray to hit and no plate can follow. That is + // the shape "mousing over it gives no tooltip" takes for a server's own GameObject whose + // `GameObjectDisplayInfo` row this chain's DBC does not carry, a hardcore gravestone + // included. + info!( + "gameobject display {display_id} names no model — it draws nothing and cannot be picked" + ); return empty_display(); }; let handle = if path.to_ascii_lowercase().ends_with(".wmo") { diff --git a/crates/benilla-app/src/ui_tooltip/mod.rs b/crates/benilla-app/src/ui_tooltip/mod.rs index 70f335f7..c5c83636 100644 --- a/crates/benilla-app/src/ui_tooltip/mod.rs +++ b/crates/benilla-app/src/ui_tooltip/mod.rs @@ -569,6 +569,8 @@ pub(crate) struct HoverMemo<'s> { /// The last `(corpse guid, reason)` the corpse plate gave up on, so a hover that cannot draw /// one says why **once** instead of every frame it is held. corpse_miss: Local<'s, Option<(u64, &'static str)>>, + /// The last GameObject guid whose plate waited on a template, same rule. + go_miss: Local<'s, Option>, } /// Report a corpse plate this hover could not build, once per corpse and reason. @@ -803,7 +805,15 @@ fn drive_mouseover_tooltip( ); } let Some(template) = go_inputs.templates.get(guid).cloned() else { - // Template in flight: ask once, and show it when it lands. + // Template in flight: ask once, and show it when it lands. Said out loud once per + // object, because this is the plate's only silent exit and the one place a server's + // own GameObject — a hardcore gravestone, say — can go nameless: no + // `SMSG_GAMEOBJECT_QUERY_RESPONSE`, no plate, however well the pick landed. A line + // that never gets a sequel means the query went unanswered. + if *memo.go_miss != Some(guid) { + *memo.go_miss = Some(guid); + info!("go plate: {guid:#x} has no template yet — asked, drawing nothing"); + } go_inputs.templates.request(guid, &commands); return; };