Hold the battle result until the replay ends, then show it last.
This commit is contained in:
@@ -724,10 +724,14 @@ func (g *Game) resolveBattle() {
|
|||||||
|
|
||||||
g.Battle = res
|
g.Battle = res
|
||||||
g.Phase = PhaseBattle
|
g.Phase = PhaseBattle
|
||||||
|
// Tagged "result" so the client can hold it back until the replay finishes
|
||||||
|
// (the outcome is known now, but showing it early would spoil the battle).
|
||||||
if winner < 0 {
|
if winner < 0 {
|
||||||
g.logf(-1, "⚔️", "Round %d battle ends in a draw.", g.Round)
|
g.addLog(LogEntry{Seat: -1, Icon: "⚔️", Kind: "result",
|
||||||
|
Text: fmt.Sprintf("Round %d battle ends in a draw.", g.Round)})
|
||||||
} else {
|
} else {
|
||||||
g.logf(winner, "⚔️", "%s wins the round %d battle (+%d🏆).", pname(winner), g.Round, res.Trophies)
|
g.addLog(LogEntry{Seat: winner, Icon: "⚔️", Kind: "result",
|
||||||
|
Text: fmt.Sprintf("%s wins the round %d battle (+%d🏆).", pname(winner), g.Round, res.Trophies)})
|
||||||
}
|
}
|
||||||
for _, p := range g.Players {
|
for _, p := range g.Players {
|
||||||
p.Ready = false
|
p.Ready = false
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ type LogEntry struct {
|
|||||||
Phase Phase `json:"phase"`
|
Phase Phase `json:"phase"`
|
||||||
Seat int `json:"seat"` // acting seat, or -1 when none
|
Seat int `json:"seat"` // acting seat, or -1 when none
|
||||||
Icon string `json:"icon,omitempty"` // leading emoji
|
Icon string `json:"icon,omitempty"` // leading emoji
|
||||||
|
Kind string `json:"kind,omitempty"` // e.g. "result" (battle outcome)
|
||||||
Text string `json:"text"` // the sentence itself
|
Text string `json:"text"` // the sentence itself
|
||||||
Source string `json:"source,omitempty"` // card id that caused a spawn
|
Source string `json:"source,omitempty"` // card id that caused a spawn
|
||||||
Spawn string `json:"spawn,omitempty"` // "apple" | "bee" for spawn entries
|
Spawn string `json:"spawn,omitempty"` // "apple" | "bee" for spawn entries
|
||||||
|
|||||||
@@ -32,13 +32,38 @@ export function Table({ session, onLeave }: { session: Session; onLeave: () => v
|
|||||||
return { round: battleRound, step: next }
|
return { round: battleRound, step: next }
|
||||||
})
|
})
|
||||||
|
|
||||||
const battleLines = useMemo(
|
// The battle outcome is known before the replay plays out, so we hold its
|
||||||
() =>
|
// "result" log entry back: it's dropped from the persistent list during the
|
||||||
view?.phase === 'battle' && view.battle?.events
|
// battle and appended as the final battle line only once the replay reaches
|
||||||
? battleLogLines(view.battle.events, step)
|
// the end (and reappears in the persistent log in later phases).
|
||||||
: undefined,
|
const inBattle = view?.phase === 'battle'
|
||||||
[view, step],
|
const events = view?.battle?.events ?? null
|
||||||
)
|
const battleDone = !!(inBattle && events && step >= events.length)
|
||||||
|
|
||||||
|
const entries = useMemo(() => {
|
||||||
|
const log = view?.log ?? []
|
||||||
|
if (!inBattle) return log
|
||||||
|
return log.filter((e) => !(e.kind === 'result' && e.round === battleRound))
|
||||||
|
}, [view, inBattle, battleRound])
|
||||||
|
|
||||||
|
const battleLines = useMemo(() => {
|
||||||
|
if (!inBattle || !events) return undefined
|
||||||
|
const lines = battleLogLines(events, step)
|
||||||
|
if (battleDone) {
|
||||||
|
const result = (view?.log ?? []).find(
|
||||||
|
(e) => e.kind === 'result' && e.round === battleRound,
|
||||||
|
)
|
||||||
|
if (result) {
|
||||||
|
lines.push({
|
||||||
|
key: `result-${result.seq}`,
|
||||||
|
icon: result.icon,
|
||||||
|
text: result.text,
|
||||||
|
seat: result.seat,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lines
|
||||||
|
}, [view, inBattle, events, step, battleDone, battleRound])
|
||||||
|
|
||||||
if (!view) {
|
if (!view) {
|
||||||
return (
|
return (
|
||||||
@@ -98,11 +123,7 @@ export function Table({ session, onLeave }: { session: Session; onLeave: () => v
|
|||||||
{view.phase === 'gameover' && <GameOver view={view} onLeave={onLeave} />}
|
{view.phase === 'gameover' && <GameOver view={view} onLeave={onLeave} />}
|
||||||
</main>
|
</main>
|
||||||
{view.phase !== 'lobby' && (
|
{view.phase !== 'lobby' && (
|
||||||
<EventLog
|
<EventLog entries={entries} youSeat={view.youSeat} battleLines={battleLines} />
|
||||||
entries={view.log ?? []}
|
|
||||||
youSeat={view.youSeat}
|
|
||||||
battleLines={battleLines}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ export interface LogEntry {
|
|||||||
phase: Phase
|
phase: Phase
|
||||||
seat: number // acting seat, or -1
|
seat: number // acting seat, or -1
|
||||||
icon?: string
|
icon?: string
|
||||||
|
kind?: string // e.g. 'result' (battle outcome)
|
||||||
text: string
|
text: string
|
||||||
source?: string // card id that caused a spawn
|
source?: string // card id that caused a spawn
|
||||||
spawn?: string // 'apple' | 'bee'
|
spawn?: string // 'apple' | 'bee'
|
||||||
|
|||||||
Reference in New Issue
Block a user