From a5cccc03baa6cedba7e8c9c961d0cb1d94ebc061 Mon Sep 17 00:00:00 2001 From: Malte Langkabel Date: Wed, 1 Jul 2026 22:14:43 +0200 Subject: [PATCH] Freeze replay at the run's terminal state (win/defeat) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Playback only stopped when the recorded command stream ran out, so a run that ended on the artifact win (e.g. 3/3) kept ticking during replay because win and game-over are gated off in replay mode and the recording ran a few ticks past the win. Stop advancing when m_sim->isWon() || isGameOver() (in addition to the stream end), and show it in the replay overlay: "Replay ended — Victory" / "— Defeat" (desync still takes priority). This matches where the real game froze. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01DUsFgd2Ga6pmLz8giS8WUn --- src/ui/GameWorldView.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/ui/GameWorldView.cpp b/src/ui/GameWorldView.cpp index 86679cd..8020246 100644 --- a/src/ui/GameWorldView.cpp +++ b/src/ui/GameWorldView.cpp @@ -194,7 +194,11 @@ void GameWorldView::onFrame() static_cast(elapsed), m_gameSpeedMultiplier); for (int i = 0; i < ticks; ++i) { - if (m_replayPlayer->isFinished()) { break; } + // Stop at the recorded stream's end, or at the run's terminal state: + // the real game froze when it was won or lost, so the replay does too + // (the recording may run a few ticks past that point). + if (m_replayPlayer->isFinished() + || m_sim->isWon() || m_sim->isGameOver()) { break; } m_sim->tick(); m_replayPlayer->advanceTo(m_sim->currentTick()); } @@ -1314,7 +1318,11 @@ void GameWorldView::drawReplayOverlay(QPainter& painter) painter.setPen(QColor(255, 220, 80)); painter.drawText(QRect(0, 8, width(), 24), Qt::AlignHCenter | Qt::AlignTop, tr("REPLAY")); - if (m_replayPlayer->isFinished()) + // The replay is over once the recorded stream is exhausted or the run reached + // its terminal state (win / defeat) — matching where playback freezes above. + const bool ended = m_replayPlayer->isFinished() + || m_sim->isWon() || m_sim->isGameOver(); + if (ended) { // Dim the world so the end message reads clearly over it. painter.fillRect(rect(), QColor(0, 0, 0, 140)); @@ -1326,6 +1334,16 @@ void GameWorldView::drawReplayOverlay(QPainter& painter) message = tr("Desync at tick %1").arg(static_cast(*desync)); painter.setPen(QColor(255, 90, 90)); } + else if (m_sim->isWon()) + { + message = tr("Replay ended — Victory"); + painter.setPen(QColor(120, 255, 120)); + } + else if (m_sim->isGameOver()) + { + message = tr("Replay ended — Defeat"); + painter.setPen(QColor(255, 255, 255)); + } else { message = tr("Replay ended");