From 3a5f473d25ee90df5f92c376f1ca4396144cb561 Mon Sep 17 00:00:00 2001 From: Dorian Date: Mon, 9 Mar 2026 14:11:02 +0000 Subject: [PATCH] fix: show full text in battle log and speech bubbles Remove .slice(0, 120) truncation from battle log entries and .slice(0, 60) from speech bubble calls. Increase bubble limits to 200 chars, 24 chars/line, 8 lines so responses display fully. Co-Authored-By: Claude Opus 4.6 --- frontend/src/components/FightViewer.vue | 16 ++++++++-------- frontend/src/game/fight/config.ts | 6 +++--- frontend/src/pages/FightPage.vue | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/frontend/src/components/FightViewer.vue b/frontend/src/components/FightViewer.vue index 5853014..f399e24 100644 --- a/frontend/src/components/FightViewer.vue +++ b/frontend/src/components/FightViewer.vue @@ -298,8 +298,8 @@ function addRoundToLog(round: FightRound, stagger: boolean): Promise { logItems.value.push( { type: 'header', round: round.roundNumber, text: `ROUND ${round.roundNumber}: ${challengeLabel(round.challengeType)}`, color: 'neon-purple' }, { type: 'prompt', round: round.roundNumber, text: challenge.displayPrompt || challenge.prompt, color: 'text-muted' }, - { type: 'responseA', round: round.roundNumber, text: `${props.fight.botA?.name}: ${round.botAResponse?.slice(0, 120) || '[NO RESPONSE]'} (${round.botATimeMs}ms)`, color: 'neon-cyan' }, - { type: 'responseB', round: round.roundNumber, text: `${props.fight.botB?.name}: ${round.botBResponse?.slice(0, 120) || '[NO RESPONSE]'} (${round.botBTimeMs}ms)`, color: 'neon-pink' }, + { type: 'responseA', round: round.roundNumber, text: `${props.fight.botA?.name}: ${round.botAResponse || '[NO RESPONSE]'} (${round.botATimeMs}ms)`, color: 'neon-cyan' }, + { type: 'responseB', round: round.roundNumber, text: `${props.fight.botB?.name}: ${round.botBResponse || '[NO RESPONSE]'} (${round.botBTimeMs}ms)`, color: 'neon-pink' }, ) if (round.narration) logItems.value.push({ type: 'narration', round: round.roundNumber, text: `>> ${round.narration}`, color: 'neon-yellow' }) const winner = round.winnerId === props.fight.botA?.id ? props.fight.botA?.name : round.winnerId === props.fight.botB?.id ? props.fight.botB?.name : 'DRAW' @@ -313,11 +313,11 @@ function addRoundToLog(round: FightRound, stagger: boolean): Promise { scrollLog(); await sleep(150) logItems.value.push({ type: 'prompt', round: round.roundNumber, text: challenge.displayPrompt || challenge.prompt, color: 'text-muted' }) scrollLog(); await sleep(200) - logItems.value.push({ type: 'responseA', round: round.roundNumber, text: `${props.fight.botA?.name}: ${round.botAResponse?.slice(0, 120) || '[NO RESPONSE]'}`, color: 'neon-cyan' }) + logItems.value.push({ type: 'responseA', round: round.roundNumber, text: `${props.fight.botA?.name}: ${round.botAResponse || '[NO RESPONSE]'}`, color: 'neon-cyan' }) scrollLog(); await sleep(150) logItems.value.push({ type: 'time', round: round.roundNumber, text: ` ${round.botATimeMs}ms | Score: ${round.botAScore}`, color: 'text-muted' }) scrollLog(); await sleep(150) - logItems.value.push({ type: 'responseB', round: round.roundNumber, text: `${props.fight.botB?.name}: ${round.botBResponse?.slice(0, 120) || '[NO RESPONSE]'}`, color: 'neon-pink' }) + logItems.value.push({ type: 'responseB', round: round.roundNumber, text: `${props.fight.botB?.name}: ${round.botBResponse || '[NO RESPONSE]'}`, color: 'neon-pink' }) scrollLog(); await sleep(150) logItems.value.push({ type: 'time', round: round.roundNumber, text: ` ${round.botBTimeMs}ms | Score: ${round.botBScore}`, color: 'text-muted' }) scrollLog() @@ -434,11 +434,11 @@ async function _doReplay() { if (round.botAResponse) { if (doTTS) await awaitAnswerReady(props.fight.botA!.name, round.botAResponse) scene?.stopShowboating('a') - logItems.value.push({ type: 'responseA', round: round.roundNumber, text: `${props.fight.botA?.name}: ${round.botAResponse.slice(0, 120) || '[NO RESPONSE]'}`, color: 'neon-cyan' }) + logItems.value.push({ type: 'responseA', round: round.roundNumber, text: `${props.fight.botA?.name}: ${round.botAResponse || '[NO RESPONSE]'}`, color: 'neon-cyan' }) logItems.value.push({ type: 'time', round: round.roundNumber, text: ` ${round.botATimeMs}ms | Score: ${round.botAScore}`, color: 'text-muted' }) scrollLog() if (scene && !insanityMode.value) { - scene.showSpeechBubble('a', round.botAResponse.slice(0, 60), 8) + scene.showSpeechBubble('a', round.botAResponse, 8) scene.startTalking('a') } // Ensure bubble stays visible for at least 400ms even if TTS resolves instantly @@ -454,13 +454,13 @@ async function _doReplay() { if (round.botBResponse) { if (doTTS) await awaitAnswerReady(props.fight.botB!.name, round.botBResponse) scene?.stopShowboating('b') - logItems.value.push({ type: 'responseB', round: round.roundNumber, text: `${props.fight.botB?.name}: ${round.botBResponse.slice(0, 120) || '[NO RESPONSE]'}`, color: 'neon-pink' }) + logItems.value.push({ type: 'responseB', round: round.roundNumber, text: `${props.fight.botB?.name}: ${round.botBResponse || '[NO RESPONSE]'}`, color: 'neon-pink' }) logItems.value.push({ type: 'time', round: round.roundNumber, text: ` ${round.botBTimeMs}ms | Score: ${round.botBScore}`, color: 'text-muted' }) scrollLog() // Prefetch narration while bot B talks if (doTTS && round.narration) prefetchNarration(round.narration) if (scene && !insanityMode.value) { - scene.showSpeechBubble('b', round.botBResponse.slice(0, 60), 8) + scene.showSpeechBubble('b', round.botBResponse, 8) scene.startTalking('b') } const minBubbleB = sleep(400).catch(() => {}) diff --git a/frontend/src/game/fight/config.ts b/frontend/src/game/fight/config.ts index 3cbb8bb..3b9b5b5 100644 --- a/frontend/src/game/fight/config.ts +++ b/frontend/src/game/fight/config.ts @@ -107,9 +107,9 @@ export const SKY_GRADIENT_BANDS = 6 // Number of sky gradient ba export const GROUND_DEPTH_LINES = 12 // Ground gradient fade lines export const PERSPECTIVE_GRID_LINES = 24 // Floor grid convergence lines export const PILLAR_WIDTH = 8 // Side pillar frame width -export const SPEECH_BUBBLE_MAX_CHARS = 80 // Max chars in speech bubble -export const SPEECH_BUBBLE_WRAP = 18 // Chars per line in speech bubble -export const SPEECH_BUBBLE_MAX_LINES = 5 // Max lines in speech bubble +export const SPEECH_BUBBLE_MAX_CHARS = 200 // Max chars in speech bubble +export const SPEECH_BUBBLE_WRAP = 24 // Chars per line in speech bubble +export const SPEECH_BUBBLE_MAX_LINES = 8 // Max lines in speech bubble export const SPEECH_BUBBLE_FONT_SIZE = 12 // Speech bubble font size export const SPEECH_BUBBLE_DEFAULT_DURATION = 3 // Default speech bubble duration (seconds) diff --git a/frontend/src/pages/FightPage.vue b/frontend/src/pages/FightPage.vue index 2002d9f..4348c78 100644 --- a/frontend/src/pages/FightPage.vue +++ b/frontend/src/pages/FightPage.vue @@ -246,10 +246,10 @@ async function handleRoundEnd(data: any) { { type: 'header', round, text: `ROUND ${round}: ${cLabel}`, color: 'neon-purple' }, ) if (result.botAResponse) { - liveLogItems.value.push({ type: 'responseA', round, text: `${fd.botA.name}: ${result.botAResponse.slice(0, 120)}`, color: 'neon-cyan' }) + liveLogItems.value.push({ type: 'responseA', round, text: `${fd.botA.name}: ${result.botAResponse}`, color: 'neon-cyan' }) } if (result.botBResponse) { - liveLogItems.value.push({ type: 'responseB', round, text: `${fd.botB.name}: ${result.botBResponse.slice(0, 120)}`, color: 'neon-pink' }) + liveLogItems.value.push({ type: 'responseB', round, text: `${fd.botB.name}: ${result.botBResponse}`, color: 'neon-pink' }) } if (result.narration) { liveLogItems.value.push({ type: 'narration', round, text: `>> ${result.narration}`, color: 'neon-yellow' }) @@ -263,10 +263,10 @@ async function handleRoundEnd(data: any) { if (liveScene) { fanfareRound(round) - if (result.botAResponse) liveScene.showSpeechBubble('a', result.botAResponse.slice(0, 60), 3) + if (result.botAResponse) liveScene.showSpeechBubble('a', result.botAResponse, 3) if (result.botBResponse) { setTimeout(() => { - if (liveScene && result.botBResponse) liveScene.showSpeechBubble('b', result.botBResponse.slice(0, 60), 2.5) + if (liveScene && result.botBResponse) liveScene.showSpeechBubble('b', result.botBResponse, 2.5) }, 300) }