adventure: let a player act from the web, not just read about it
The equip queue proved the reverse pipe works. This gives it verbs that play the game: pull out of a run from the adventurer page, take today's bout from the war room. Its own table and its own poll, not more actions on equip_orders. Every column of that table is equip vocabulary (item, slot, tier) and these verbs act on the character rather than on something it is carrying. Nothing in a request names an adventurer. The session maps to one localpart and a localpart to one adventurer, so Pete resolves the character itself and there is no id on the wire to forge. The panel's copy is kept honest by the verdict: an applied action hides the offer it has just spent, a refusal puts the button back. Watching it run is what put that there, along with the strip's layout — gogobee answers a bout with a whole sentence of damage, which the equip strip's two-column row squeezed into a column and wrapped the verb. Claude-Session: https://claude.ai/code/session_012bxpQQJDjC1mTtLN3VVtBQ
This commit is contained in:
@@ -58,14 +58,46 @@
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- How to actually join in. The bout is a Matrix command today; saying so
|
||||
plainly beats a page that shows a fight nobody can tell how to enter. -->
|
||||
<div class="mt-6 rounded-3xl bg-[color:var(--card)] border-2 border-theme-adventure/30 p-5 shadow-pete">
|
||||
<p class="text-sm text-[color:var(--ink)]/75">
|
||||
<span class="font-semibold text-theme-adventure">Taking your bout:</span>
|
||||
say <code class="rounded bg-[color:var(--ink)]/8 px-1.5 py-0.5 font-mono text-xs">!adventure siege fight</code>
|
||||
to me in Matrix. One a day, each. Damage counts whether you win the fight or not — turning up is the mechanic.
|
||||
</p>
|
||||
<!-- How to actually join in. A signed-in adventurer can do it from here; the
|
||||
Matrix command stays on the page for everyone else, because it is still
|
||||
the only door for a visitor who isn't signed in — and the blow-by-blow of
|
||||
the fight arrives there whichever door you came through. -->
|
||||
<div id="adv-actions" class="adv-actions mt-6 rounded-3xl bg-[color:var(--card)] border-2 border-theme-adventure/30 p-5 shadow-pete">
|
||||
{{if .YouOnBoard}}
|
||||
{{if .YouFought}}
|
||||
<p class="text-sm text-[color:var(--ink)]/75">
|
||||
<span class="font-semibold text-theme-adventure">You've taken your bout today.</span>
|
||||
Come back tomorrow. One fight each, per day, and everyone in the right-hand column below still has theirs.
|
||||
</p>
|
||||
{{else}}
|
||||
{{/* data-offer marks the half of this panel that stops being true the
|
||||
moment the bout lands. The script hides it on an applied verdict, so
|
||||
the page can't go on saying "unspent" over a fight that just
|
||||
happened. */}}
|
||||
<div data-offer>
|
||||
<p class="text-sm text-[color:var(--ink)]/75 mb-3">
|
||||
<span class="font-semibold text-theme-adventure">Your bout is unspent.</span>
|
||||
Damage counts whether you win the fight or not. Turning up is the mechanic, and the blow-by-blow lands in Matrix.
|
||||
</p>
|
||||
<button type="button"
|
||||
class="adv-action-btn rounded-full bg-theme-adventure text-white px-4 py-1.5 text-sm font-semibold hover:opacity-90 transition"
|
||||
data-action="siege_join"
|
||||
data-label="Take your bout"
|
||||
data-confirm-label="Yes, take my bout"
|
||||
data-confirm="Take your bout against this boss now? It's the only one you get today, and it costs real HP, though you can't die from it. The damage comes off the pool whether you win or lose.">Take your bout</button>
|
||||
</div>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<p class="text-sm text-[color:var(--ink)]/75">
|
||||
<span class="font-semibold text-theme-adventure">Taking your bout:</span>
|
||||
say <code class="rounded bg-[color:var(--ink)]/8 px-1.5 py-0.5 font-mono text-xs">!adventure siege fight</code>
|
||||
to me in Matrix. One a day, each. Damage counts whether you win the fight or not; turning up is the mechanic.
|
||||
</p>
|
||||
{{end}}
|
||||
|
||||
<div id="adv-action-orders-box" class="mt-4 hidden">
|
||||
<ul id="adv-action-orders" class="space-y-1.5 text-xs"></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- The muster. Two columns, and the right-hand one is the point: a bout not
|
||||
@@ -206,3 +238,5 @@
|
||||
})();
|
||||
</script>
|
||||
{{end}}
|
||||
|
||||
{{define "scripts"}}<script src="/static/js/adventure-actions.js" defer></script>{{end}}
|
||||
|
||||
@@ -195,6 +195,42 @@
|
||||
</a>
|
||||
</section>
|
||||
|
||||
{{if .HasSelf}}
|
||||
<!-- Your call. The panels above are a spectator view of a run going well or
|
||||
badly; this is the one thing the watcher can do about it. Owner-only, and
|
||||
shown whether or not the mark is currently on a run — the board is up to
|
||||
two minutes stale, so hiding the button on a snapshot that says "in town"
|
||||
would be the page refusing an action the game would have allowed. gogobee
|
||||
answers rejected_not_running if it really has ended, and that answer shows
|
||||
up in the strip below. -->
|
||||
<section id="adv-actions" class="adv-actions mt-6 rounded-3xl bg-[color:var(--card)] border-2 border-[color:var(--ink)]/10 p-6 shadow-pete">
|
||||
<h2 class="font-display text-xl font-bold mb-1">Your call</h2>
|
||||
<p class="text-sm text-[color:var(--ink)]/60 mb-4">
|
||||
Asked for here, done on the game box. It picks these up within a few seconds.
|
||||
</p>
|
||||
{{/* data-offer marks what stops being true once the extraction lands: there
|
||||
is no run left to pull out of. Hidden by the script on an applied
|
||||
verdict, restored on a refusal, which is the one case where the reader
|
||||
still needs the retry. */}}
|
||||
<div data-offer>
|
||||
<button type="button"
|
||||
class="adv-action-btn rounded-full border border-theme-adventure/40 text-theme-adventure hover:bg-theme-adventure/10 px-4 py-1.5 text-sm font-semibold transition-colors"
|
||||
data-action="extract"
|
||||
data-label="Pull out of the run"
|
||||
data-confirm-label="Yes, pull out"
|
||||
data-confirm="Pull out of the dungeon now? You keep the loot, XP and coins you're carrying, and the run waits where you left it: you have seven days to go back in. If you're leading a party, it ends the day for all of you.">Pull out of the run</button>
|
||||
</div>
|
||||
|
||||
<!-- The queue is honest: an action lands on the game box's next poll, so a
|
||||
fresh one reads "asked for", never "done". JS fills this from
|
||||
/api/adventure/orders. -->
|
||||
<div id="adv-action-orders-box" class="mt-5 hidden">
|
||||
<h3 class="font-display text-base font-bold mb-2">What you've asked for</h3>
|
||||
<ul id="adv-action-orders" class="space-y-1.5 text-xs"></ul>
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
{{if .HasHistory}}
|
||||
<!-- The record. Public, like the dispatches it's counted from — this is the
|
||||
same information the /adventure feed already printed, only as numbers
|
||||
@@ -714,3 +750,5 @@
|
||||
})();
|
||||
</script>
|
||||
{{end}}
|
||||
|
||||
{{define "scripts"}}<script src="/static/js/adventure-actions.js" defer></script>{{end}}
|
||||
|
||||
Reference in New Issue
Block a user