corpse: each way a grave can draw no plate now says which one it was
He hovered a grave for the instrumentation and the log has **no** corpse line at all — which, as the earlier note said, means the question is now a different one: either no corpse object arrived, or the pick never landed on it, or the plate refused it silently. Two of those were still silent. The bone-pile refusal now logs too, though it is the reference's own answer (`0x5d76d0`: bones with `CORPSE_FIELD_DYNAMIC_FLAGS` bit 0 clear shows no name) — from the player's chair it looks identical to a miss, and it is the likeliest shape for a grave. A picked corpse with no fields logs as well. `log_new_corpses` is the third leg: one line per corpse object the server sends, with its flags, owner and chosen model, on `Added<ObjectStore>` so it touches only the frame's new arrivals. It answers whether the grave he hovered was a body or a bone pile without asking him to hover anything, and separates "nothing arrived" from the two plate-side misses. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
@@ -672,7 +672,11 @@ impl Plugin for EntitiesPlugin {
|
||||
(spell_fx::fire_fx_anim_events, spell_fx::advance_fx_anim),
|
||||
// A gear change re-dresses the standing visual in place, every attachment left
|
||||
// alone as in the reference; a new corpse arms its Dead or Drowned pose.
|
||||
(attach::redress_player_looks, corpse::pose_corpses),
|
||||
(
|
||||
attach::redress_player_looks,
|
||||
corpse::pose_corpses,
|
||||
corpse::log_new_corpses,
|
||||
),
|
||||
// A mount change re-seats the rig on the mount's attachment 0 or back, as the
|
||||
// reference re-parents the body model (`0x712f70`, `0x713020`).
|
||||
reseat_mounts,
|
||||
|
||||
@@ -102,6 +102,36 @@ pub(in crate::entities) fn ensure_bones_display(
|
||||
bones.0.insert(key, dm);
|
||||
}
|
||||
|
||||
/// Say, once per corpse the server sends, what a plate over it would have to work with.
|
||||
///
|
||||
/// "Mousing over a grave gives no tooltip" has three shapes and only the last is a bug in the
|
||||
/// plate: no corpse object arrived at all, the mouse pick never landed on it, or the plate refused
|
||||
/// it. The plate's own misses already log (`ui_tooltip::note_corpse_miss`, which now covers the
|
||||
/// bone-pile refusal too), so one line per corpse object is what separates the first shape from
|
||||
/// the other two — and it tells us whether the grave he hovered was a body or a bone pile, which
|
||||
/// is the whole question (`0x5d76d0` shows no name over a bone pile with nothing to take).
|
||||
///
|
||||
/// On `Added<ObjectStore>`, so this touches only the frame's new arrivals; a later field delta
|
||||
/// re-inserts the store and may say it again, which is worth having when a flag flips.
|
||||
pub(super) fn log_new_corpses(
|
||||
corpses: Query<(&NetEntity, &crate::net::Guid, &ObjectStore), Added<ObjectStore>>,
|
||||
) {
|
||||
for (net, guid, store) in &corpses {
|
||||
if net.kind != EntityKind::Corpse {
|
||||
continue;
|
||||
}
|
||||
let s = &store.0;
|
||||
info!(
|
||||
"corpse: {:#x} arrives — bones={} lootable={} owner={:#x} model={:?}",
|
||||
guid.0,
|
||||
s.corpse_is_bones(),
|
||||
s.corpse_lootable(),
|
||||
s.corpse_owner().unwrap_or(0),
|
||||
corpse_model(net, Some(store)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// The corpse's pose is armed, once: `0x5d6260` caches the verdict at `[corpse+0x2ac]` and nothing
|
||||
/// recomputes it.
|
||||
#[derive(Component)]
|
||||
|
||||
@@ -847,7 +847,12 @@ pub(crate) mod schedule_tests {
|
||||
/// unit it picks is then committed **by GUID**, so a stale yard or two cannot select something
|
||||
/// else. The pairs that would matter — its order against the script tick that reads what it
|
||||
/// publishes — are declared (`UnitFeed`, `.before(UnitFeedDispatch)`).
|
||||
const UPDATE_ACTIONABLE_CEILING: usize = 4_972;
|
||||
/// +1 for `entities::corpse::log_new_corpses`, which reads three components and writes
|
||||
/// nothing: its one pair is against the collider finisher, an exclusive `&mut World` system
|
||||
/// that pairs with everything it has no declared order against. The order can only decide
|
||||
/// which frame the line prints in, and `Added<ObjectStore>` still fires exactly once either
|
||||
/// way.
|
||||
const UPDATE_ACTIONABLE_CEILING: usize = 4_973;
|
||||
const UPDATE_ACTIONABLE_SLACK: usize = 40;
|
||||
|
||||
fn ratchet(what: &str, n: usize, ceiling: usize, slack: usize) {
|
||||
|
||||
@@ -693,10 +693,24 @@ fn drive_mouseover_tooltip(
|
||||
.filter(|_| go.is_none())
|
||||
{
|
||||
let Some(store) = stores.get(entity).ok() else {
|
||||
note_corpse_miss(
|
||||
&mut memo.corpse_miss,
|
||||
guid,
|
||||
"the picked corpse carries no fields",
|
||||
);
|
||||
return;
|
||||
};
|
||||
// A bone pile with nothing to take publishes no mouseover: no plate, no brighten.
|
||||
if !crate::target::corpse_mouseover_eligible(store) {
|
||||
// Logged too, though it is the reference's own answer (`0x5d76d0`: bones, and
|
||||
// `CORPSE_FIELD_DYNAMIC_FLAGS` bit 0 clear, so nothing to take). "No tooltip on a
|
||||
// grave" looks identical to the two misses below from the player's chair, and this
|
||||
// line is what tells them apart.
|
||||
note_corpse_miss(
|
||||
&mut memo.corpse_miss,
|
||||
guid,
|
||||
"a bone pile with no loot, which the reference refuses too (`0x5d76d0`)",
|
||||
);
|
||||
if !matches!(*last, LastHover::None) {
|
||||
script.world_tooltip_fade();
|
||||
*last = LastHover::None;
|
||||
|
||||
Reference in New Issue
Block a user