fix: human vs AI fight bugs — CSP for TTS, invisible sprites, fight end sequence

- Allow huggingface.co in CSP connect-src (fixes Kokoro TTS model download)
- Add registerSW.js route (fixes PWA service worker 404)
- Add _resetPositions() safety after entrance (fixes invisible fighters)
- Fight end sequence works without canvas scene (KO/overlays/log always play)
- Pre-fight instructions in battle log for human players
- NIP-55 visibility sync and cleanup handlers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-09 17:00:20 +00:00
co-authored by Claude Opus 4.6
parent 63cc00fcb6
commit 150ce7447d
5 changed files with 142 additions and 54 deletions
+23 -6
View File
@@ -170,6 +170,13 @@ async function initLiveScene() {
{ type: 'system', round: 0, text: `${data.botA.name} vs ${data.botB.name}`, color: 'text-secondary' },
{ type: 'divider', round: 0, text: '', color: '' },
)
// Pre-fight instructions for human players
if (isHumanFight.value) {
liveLogItems.value.push(
{ type: 'narration', round: 0, text: 'HUMAN VS AI — Answer challenges faster and better than the bot! Tap a choice or type your answer before time runs out.', color: 'neon-yellow' },
{ type: 'divider', round: 0, text: '', color: '' },
)
}
scrollLiveLog()
}
@@ -320,7 +327,7 @@ async function handleFightEnd(data: any) {
else liveHpA.value = 0
}
if (liveScene && data.winnerId) {
if (data.winnerId) {
const winningSide = (data.winnerId === fd.botA.id ? 'a' : 'b') as 'a' | 'b'
sfxDrumRoll()
@@ -328,11 +335,21 @@ async function handleFightEnd(data: any) {
announceFinishHim()
await showLiveOverlay('FINISH IT!', '#ff2d2d', 900)
if (data.isPerfect) {
await liveScene.playPerfect(winningSide, data.winnerName)
announceFlawlessVictory()
if (liveScene) {
try {
if (data.isPerfect) {
await liveScene.playPerfect(winningSide, data.winnerName)
announceFlawlessVictory()
} else {
await liveScene.playKO(winningSide, data.winnerName)
}
} catch (err) {
console.warn('[FightPage] KO animation failed:', err)
}
} else {
await liveScene.playKO(winningSide, data.winnerName)
// Scene unavailable — still announce vocally
if (data.isPerfect) announceFlawlessVictory()
await sleep(800)
}
sfxApplause()
@@ -341,7 +358,7 @@ async function handleFightEnd(data: any) {
if (data.mode === 'ranked' && data.potSats) {
await showLiveOverlay(`WON ${data.potSats} SATS!`, '#00f0ff', 1500)
}
liveScene.stopMusic()
if (liveScene) liveScene.stopMusic()
}
if (isHumanFight.value) {