ui_tooltip: the corpse plate says why it drew none
"Mousing over player graves provides no tooltip" could have been any of three silent `return`s on a path a player can see, and the log said nothing at all. Each now reports itself once per corpse and reason: an empty `CORPSE_FIELD_OWNER`, an owner name that has not answered its `CMSG_NAME_QUERY`, or a missing `CORPSE_TOOLTIP` global. The third is already ruled out by probe — `CORPSE_TOOLTIP` reads "Corpse of %s" on this chain — and the gate above them is correct for a grave (`corpse_mouseover_eligible`: a body always, a bone pile only while lootable, and a grave is not bones). So this is the measurement, not the fix: a hover with no `corpse plate:` line at all would mean the pick is not landing on the corpse, which is a different bug in a different file. The name case is normally transient, the query being a round trip away, and is logged anyway: if it never answers, that one line is the whole diagnosis. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
@@ -566,6 +566,22 @@ pub(crate) struct HoverMemo<'s> {
|
||||
last_lines: Local<'s, crate::ui_script::VmMemo<Option<UnitState>>>,
|
||||
/// The hover probe's last trace line, so a stationary probe logs it once.
|
||||
trace: Local<'s, String>,
|
||||
/// 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)>>,
|
||||
}
|
||||
|
||||
/// Report a corpse plate this hover could not build, once per corpse and reason.
|
||||
///
|
||||
/// Each of the three ways out below is a silent `return` on a path a player can see: hovering a
|
||||
/// grave and getting nothing. "Mousing over player graves provides no tooltip" could be any of
|
||||
/// them and the log said nothing at all, so the first thing to fix was the silence.
|
||||
fn note_corpse_miss(last: &mut Option<(u64, &'static str)>, guid: u64, why: &'static str) {
|
||||
if *last == Some((guid, why)) {
|
||||
return;
|
||||
}
|
||||
*last = Some((guid, why));
|
||||
info!("corpse plate: {guid:#x} draws none — {why}");
|
||||
}
|
||||
|
||||
fn lines_view(s: &UnitState) -> UnitState {
|
||||
@@ -692,9 +708,17 @@ fn drive_mouseover_tooltip(
|
||||
}
|
||||
// A corpse carries `CORPSE_FIELD_OWNER`, not a name; the plate waits for the name query.
|
||||
let Some(owner) = store.0.corpse_owner() else {
|
||||
note_corpse_miss(&mut memo.corpse_miss, guid, "CORPSE_FIELD_OWNER is empty");
|
||||
return;
|
||||
};
|
||||
let Some(name) = names.resolve(owner, &commands).map(str::to_string) else {
|
||||
// Normally transient — the query is in flight and the next frame has it. Logged once
|
||||
// per corpse all the same: if it never answers, this line is the whole diagnosis.
|
||||
note_corpse_miss(
|
||||
&mut memo.corpse_miss,
|
||||
guid,
|
||||
"the owner's name has not answered a CMSG_NAME_QUERY yet",
|
||||
);
|
||||
return;
|
||||
};
|
||||
// `CORPSE_TOOLTIP`, the builder's key; no string, no plate.
|
||||
@@ -703,6 +727,11 @@ fn drive_mouseover_tooltip(
|
||||
"CORPSE_TOOLTIP",
|
||||
&[Arg::S(&name)],
|
||||
) else {
|
||||
note_corpse_miss(
|
||||
&mut memo.corpse_miss,
|
||||
guid,
|
||||
"the CORPSE_TOOLTIP global is missing from this chain's FrameXML",
|
||||
);
|
||||
return;
|
||||
};
|
||||
// No object id: a corpse is not a GameObject, it only borrows this plate's one gold line.
|
||||
|
||||
Reference in New Issue
Block a user