adventure: show whether a backpack item is an upgrade over what's worn

On the owner's own page, each wearable backpack item now carries a compare
card: a verdict chip (upgrade / downgrade / sidegrade / new / inert / same),
the per-stat deltas, and the name of the worn item it's measured against.
gogobee computes all of it — the power math needs tempering and bond state,
which live in the engine — so Pete only colours the result and does no
arithmetic. It rides the owner-private inventory, so it never reaches the
public page; the item names are game-authored, so unlike the LLM dispatch
prose there's no injection surface.

The verdict chip is always visible (a phone has no hover to lean on) with
the deltas beside it. Chip colours mix a fixed hue into --ink for text and
--card for fill, so they land on the readable side of the card in all four
phases — the same by-construction contrast trick the dungeon map uses, not
a Tailwind dark: variant. Screenshot-verified day and night, all six
verdict states, including the purple 'new' chip that the theme-contrast
history warned about. output.css rebuilt and committed.
This commit is contained in:
prosolis
2026-07-17 10:04:38 -07:00
parent 3230939c51
commit 6c6de56539
5 changed files with 139 additions and 1 deletions

View File

@@ -48,6 +48,33 @@ type ItemView struct {
Effect string `json:"effect,omitempty"`
Attunement bool `json:"attunement,omitempty"`
Attuned bool `json:"attuned,omitempty"`
// Compare, set only on backpack magic items (the ones carrying an equip ID),
// pairs this item against what is worn in the slot it would equip into. gogobee
// computes the verdict and per-stat deltas (the power math needs tempering and
// bond state, which live in the engine); Pete only renders it. Owner-private,
// rides detail_json — no public exposure. Item names here are game-authored, so
// there is no injection surface like the LLM dispatch prose.
Compare *ItemCompare `json:"compare,omitempty"`
}
// ItemCompare is gogobee's verdict for equipping a backpack magic item over what
// is currently worn in its slot. Pete renders it verbatim and does no arithmetic.
type ItemCompare struct {
// Verdict: upgrade, downgrade, sidegrade, same, new, or inert.
Verdict string `json:"verdict"`
// VsName is the worn item being replaced; "" when Verdict is new (empty slot).
VsName string `json:"vs_name,omitempty"`
// VsSlot is the slot the item would land in (e.g. "ring_1").
VsSlot string `json:"vs_slot,omitempty"`
// Deltas is one entry per changed stat, each pre-flagged better/worse.
Deltas []ItemDelta `json:"deltas,omitempty"`
}
// ItemDelta is one stat's change between the candidate and the worn item.
type ItemDelta struct {
Label string `json:"label"`
Better bool `json:"better"`
Text string `json:"text"`
}
// HouseView is the owner's housing summary.