The instant replay: a chronicle line's eye relives the turn, firsthand
The dream feature lands, behind a preference that ships off for now. The chronicle's lines grow structure — each knows its turn, counted by the same boundary events on both ends of the wire (the server counts the deal's own events too, or every number would sit one turn behind). The first notable line of a turn — combat, spectacle, a targeted cast — wears a small eye; clicking it asks the server for that one turn's steps, rebuilt and redacted like any reel, and the replay opens STRAIGHT into first person through the eyes of the wizard whose turn it was: their position, the viewer's knowledge, nothing private leaked. It plays that turn and stops. Save-video and the board toggle come along for free. Two camera bugs die with it: the replay tween effect tracked its own writes, restarting the ease every frame until walks decayed into the slow wall-piercing drift Eric saw — untracked reads run one tween per step now. And the reel camera follows whichever eyes the reel wears, not always your own. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
68be32c43e
commit
f52d0d88a9
@@ -1375,6 +1375,11 @@
|
||||
onchange={(e) => setPref("flourishes", e.currentTarget.checked)} />
|
||||
<span>Spell flourishes (the animated effects)</span>
|
||||
</label>
|
||||
<label class="pref-row">
|
||||
<input type="checkbox" checked={prefs.instantReplay}
|
||||
onchange={(e) => setPref("instantReplay", e.currentTarget.checked)} />
|
||||
<span>Instant replay: notable chronicle lines offer a 👁 that relives the turn</span>
|
||||
</label>
|
||||
<label class="pref-row">
|
||||
<input type="checkbox" checked={prefs.cautions}
|
||||
onchange={(e) => setPref("cautions", e.currentTarget.checked)} />
|
||||
@@ -1606,7 +1611,9 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if net.catchUp && net.catchUp.length > 0}
|
||||
{#if net.moment && net.moment.length > 0}
|
||||
<Replay steps={net.moment} moment onclose={() => net.closeMoment()} />
|
||||
{:else if net.catchUp && net.catchUp.length > 0}
|
||||
<Replay steps={net.catchUp} onclose={() => net.closeCatchUp()} />
|
||||
{:else if local.replaySteps && local.replaySteps.length > 0}
|
||||
<Replay steps={local.replaySteps} onclose={() => (local.replaySteps = null)} />
|
||||
@@ -2038,9 +2045,21 @@
|
||||
</div>
|
||||
|
||||
<div class="chronicle" aria-label="game log" bind:this={chronicleEl}>
|
||||
{#each (local.active ? local.log : net.log).slice(-60) as line, i (i)}
|
||||
<div class:table-talk={line.startsWith("\u{1F4AC}")}>{line}</div>
|
||||
{/each}
|
||||
{#if local.active}
|
||||
{#each local.log.slice(-60) as line, i (i)}
|
||||
<div class:table-talk={line.startsWith("\u{1F4AC}")}>{line}</div>
|
||||
{/each}
|
||||
{:else}
|
||||
{#each net.log.slice(-60) as line, i (i)}
|
||||
<div class:table-talk={line.text.startsWith("\u{1F4AC}")}>
|
||||
{line.text}
|
||||
{#if line.notable && line.turn !== null && prefs.instantReplay && !net.spectating}
|
||||
<button class="moment-eye" title="relive this turn"
|
||||
onclick={() => net.requestMoment(line.turn!)}>👁</button>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
{#if local.active && local.viewerId}
|
||||
<div class="say-box">
|
||||
@@ -2892,6 +2911,15 @@
|
||||
box-shadow: 0 2px 7px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
.chronicle div + div { margin-top: 0.05rem; }
|
||||
.moment-eye {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 0.7rem;
|
||||
padding: 0 0.15rem;
|
||||
opacity: 0.55;
|
||||
}
|
||||
.moment-eye:hover { opacity: 1; }
|
||||
|
||||
.table-edge {
|
||||
margin-top: 0.9rem;
|
||||
|
||||
Reference in New Issue
Block a user