adventure: show the party, the pets, and what you missed

Four small surfaces the game has had all along and the web has never shown.

The party roster on the adventurer page is the one with a bug behind it. The
board resolved an expedition by owner id, so a player seated on somebody else's
run has been reading as "idle in town" while standing in a tier-4 dungeon.
Seats now ride the roster detail beside the supply and threat numbers, and an
opted-out player's seat is anonymised rather than dropped: a party of three
rendered as a pair contradicts everything printed next to it.

Pets show their levelling. They have earned XP from every won fight since that
wiring was fixed and the only place a level ever appeared was a Matrix line
that scrolled away. The threshold comes from the engine, in the engine's own
centi-XP, because a copy of the curve here would drift the first time a band
moved.

"While you were away" is the one panel on the site about the reader rather than
the realm. Two stamps behind it, not one: a single column would show the news,
move the clock, and render an empty box over the same events on the reader's
first refresh.

And the story permalink names its region, which has been hardcoded empty behind
a `// reserved` comment since the page shipped.
This commit is contained in:
prosolis
2026-07-24 20:26:19 -07:00
parent 868a29e992
commit c2a40dad64
15 changed files with 935 additions and 9 deletions
+32
View File
@@ -14,6 +14,38 @@
</section>
{{if .ShowRoster}}
{{/* While you were away. First thing on the page when it renders at all, and it
renders for exactly one reader: the signed-in owner of an adventurer something
has happened to since their last visit. Above the Siege because everything
below this line is the realm's news and this is the reader's own. */}}
{{if .Away.Has}}
<section class="mb-6 rounded-3xl bg-[color:var(--card)] border-2 border-theme-adventure/30 p-5 sm:p-6 shadow-pete">
<div class="flex items-baseline justify-between gap-3 flex-wrap">
<h2 class="font-display text-xl font-bold">While you were away</h2>
<span class="text-xs uppercase tracking-wider text-[color:var(--ink)]/45">{{.Away.Name}} · past {{.Away.Since}}</span>
</div>
<ul class="mt-3 space-y-2">
{{range .Away.Lines}}
<li class="away-line{{if .Notable}} away-line-notable{{end}}">
<a href="{{.Permalink}}" class="flex items-baseline gap-2.5 group">
<span class="shrink-0" aria-hidden="true">{{.Emoji}}</span>
<span class="flex-1 text-sm">
<span class="font-semibold group-hover:text-theme-adventure group-hover:underline">{{.Label}}</span>
{{if .Line}}<span class="text-[color:var(--ink)]/60"> — {{.Line}}</span>{{end}}
</span>
<span class="text-xs text-[color:var(--ink)]/40 shrink-0 tabular-nums">{{.When}}</span>
</a>
</li>
{{end}}
</ul>
{{if .Away.Token}}
<a href="/adventure/who/{{.Away.Token}}" class="mt-3 inline-flex items-center gap-1.5 text-sm font-semibold text-theme-adventure hover:opacity-80 transition">
{{if .Away.HasMore}}More, and the rest of the trail{{else}}Your adventurer{{end}} <span aria-hidden="true"></span>
</a>
{{end}}
</section>
{{end}}
{{/* The Siege strip. Above the board on purpose: the board is where everyone is,
the Siege is where everyone should be. When one is camped this is a live bar
and a door into the war room; when none is, it stays as the quiet doorway to
+47 -6
View File
@@ -115,6 +115,33 @@
{{if .Detail.ThreatLevel}}<div class="flex justify-between"><span class="text-[color:var(--ink)]/50">Threat</span><span class="font-semibold" id="who-threat">{{.Detail.ThreatLevel}}</span></div>{{end}}
</div>
{{end}}
{{/* The party. Absent on a solo run, so this block answers "is anybody else
down there" rather than drawing a chair count. Server-rendered only: a
roster is settled before a party leaves town, so unlike the HP and
supply numbers above it there is nothing here for the poll to move.
An unnamed seat is an opted-out player, kept on purpose — see
partySeat.Anonymous for why it is not simply dropped. */}}
{{if .Detail.Party}}
<div class="mt-5 pt-4 border-t border-[color:var(--ink)]/10">
<h3 class="text-sm uppercase tracking-wider text-[color:var(--ink)]/50 mb-1">Down there together</h3>
<ul>
{{range .Detail.Party}}
<li class="party-seat">
<span class="party-seat-role{{if eq .Kind "leader"}} party-seat-leader{{end}}">{{.Kind}}</span>
{{if .Anonymous}}
<span class="party-seat-anon flex-1 text-sm">an adventurer who keeps out of the news</span>
{{else if .Token}}
<a href="/adventure/who/{{.Token}}" class="flex-1 text-sm font-semibold hover:text-theme-adventure hover:underline">{{.Name}}</a>
{{else}}
<span class="flex-1 text-sm font-semibold">{{.Name}}</span>
{{end}}
{{if .Level}}<span class="text-xs text-[color:var(--ink)]/50 shrink-0">lv {{.Level}}</span>{{end}}
</li>
{{end}}
</ul>
</div>
{{end}}
</div>
{{/* Public gear list. Hidden only when the owner's "Equipment" panel below will
@@ -519,13 +546,27 @@
{{if .Self.House.Autopay}}<div class="flex justify-between"><span class="text-[color:var(--ink)]/50">Autopay</span><span class="font-semibold">on</span></div>{{end}}
</div>
{{/* Pets, with their levelling shown. They have been earning XP from every
won fight since that wiring was fixed, and until now the only place a
level appeared was a Matrix line that scrolled away. Ranges over
.PetRows, not .Self.Pets: the progress figures are worked out in Go
from the centi-XP gogobee sends, because the curve behind the target
is the engine's and there is no copy of it here. */}}
<h3 class="font-display text-lg font-bold mt-6 mb-3">Pets</h3>
{{if .Self.Pets}}
<ul class="space-y-2 text-sm">
{{range .Self.Pets}}
<li class="flex items-baseline justify-between gap-3">
<span class="font-semibold flex-1">{{if .Name}}{{.Name}}{{else}}your {{.Type}}{{end}} <span class="text-[color:var(--ink)]/45 font-normal">{{.Type}}</span></span>
<span class="text-xs text-[color:var(--ink)]/50 shrink-0">lv {{.Level}}{{if .ArmorTier}} · barding T{{.ArmorTier}}{{end}}</span>
{{if .PetRows}}
<ul class="space-y-3 text-sm">
{{range .PetRows}}
<li>
<div class="flex items-baseline justify-between gap-3">
<span class="font-semibold flex-1">{{if .Name}}{{.Name}}{{else}}your {{.Type}}{{end}} <span class="text-[color:var(--ink)]/45 font-normal">{{.Type}}</span></span>
<span class="text-xs text-[color:var(--ink)]/50 shrink-0">lv {{.Level}}{{if .ArmorTier}} · barding T{{.ArmorTier}}{{end}}</span>
</div>
<div class="pet-xp-track mt-1.5">
<div class="pet-xp-fill{{if .Capped}} pet-xp-capped{{end}}" style="width: {{if .Capped}}100{{else}}{{.Percent}}{{end}}%"></div>
</div>
<p class="mt-1 text-xs text-[color:var(--ink)]/45">
{{if .Capped}}fully grown{{else}}{{.Progress}} to level {{.NextLevel}}{{end}}
</p>
</li>
{{end}}
</ul>