From 8448f1d8237acc7abf1578e5c78f1e9c12fdbf01 Mon Sep 17 00:00:00 2001 From: Dorian Date: Sat, 7 Mar 2026 15:20:14 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20human=20vs=20AI=20mode=20=E2=80=94=20li?= =?UTF-8?q?ve=20typing=20challenges,=20baby=20growth=20system,=20SSE=20rou?= =?UTF-8?q?nds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add choose-mode step: "I BUILD BOTS" vs "I FIGHT MYSELF" paths - Human registration with baby avatar picker, no webhook required - Live fight scene with SSE round streaming and real-time challenge UI - 5-second timer per round, submit answers via browser - Baby → toddler → kid → teen → adult → hero → super growth stages - Huge sparkly baby eyes, diapers, pacifiers, bibs, rattles, rosy cheeks - Speech bubble positioning fix (pushed to outside of sprite) - Canvas text rendering via offscreen canvas to bypass kaplay color issues - Voice timing improvements: await pauses between voice lines and hits - 30 devastating announcement lines, 15 critical/hit word variants - Orchestrator human player detection + waitForHumanResponse system - Server endpoints: GET /challenge/:botId, POST /respond/:botId - Human player auth: register-human route, isHuman flag on login Co-Authored-By: Claude Opus 4.6 --- frontend/src/components/FightViewer.vue | 8 +- frontend/src/composables/useNostr.ts | 39 ++ frontend/src/game/FightScene.ts | 129 +++-- frontend/src/game/sounds.ts | 5 +- frontend/src/game/sprites/human.ts | 188 ++++++- frontend/src/pages/BotProfilePage.vue | 18 +- frontend/src/pages/FightPage.vue | 627 +++++++++++++++++++++++- frontend/src/pages/HumanFightPage.vue | 361 ++++++++++++++ frontend/src/pages/JoinBoutPage.vue | 277 ++++++++++- frontend/src/router.ts | 5 + server/src/engine/customization.ts | 2 +- server/src/engine/human-responses.ts | 100 ++++ server/src/engine/orchestrator.ts | 21 +- server/src/routes/auth.ts | 70 +++ server/src/routes/fights.ts | 40 ++ 15 files changed, 1805 insertions(+), 85 deletions(-) create mode 100644 frontend/src/pages/HumanFightPage.vue create mode 100644 server/src/engine/human-responses.ts diff --git a/frontend/src/components/FightViewer.vue b/frontend/src/components/FightViewer.vue index 4741da3..be93050 100644 --- a/frontend/src/components/FightViewer.vue +++ b/frontend/src/components/FightViewer.vue @@ -279,8 +279,8 @@ async function replay() { // Hit text overlay — after playRound completes so it lands on the result const hitWords = isCritical - ? ['CRITICAL!', 'DEVASTATING!', 'OBLITERATED!', 'ANNIHILATED!', 'WRECKED!'] - : ['POW!', 'BAM!', 'WHAM!', 'CRACK!', 'SMASH!', 'BOOM!', 'THWACK!'] + ? ['CRITICAL!', 'OBLITERATED!', 'ANNIHILATED!', 'WRECKED!', 'BRUTAL!', 'CRUSHED!', 'DELETED!', 'ERASED!', 'VAPORIZED!', 'DESTROYED!', 'SHATTERED!', 'TERMINATED!', 'MASSACRED!', 'PULVERIZED!', 'DECIMATED!'] + : ['POW!', 'BAM!', 'WHAM!', 'CRACK!', 'SMASH!', 'BOOM!', 'THWACK!', 'BONK!', 'CRUNCH!', 'SLAM!', 'WHACK!', 'KAPOW!', 'ZAP!', 'CLONK!', 'THUD!'] if (aWon || bWon) { showHitText( hitWords[Math.floor(Math.random() * hitWords.length)], @@ -358,8 +358,10 @@ async function replay() { if (isPerfect) { await scene.playPerfect(winningSide, winnerName) announceFlawlessVictory() + await sleep(600) // let "flawless victory" voice land } else { await scene.playKO(winningSide, winnerName) + await sleep(300) // let fatality voice finish } glitching.value = true @@ -527,7 +529,7 @@ async function replay() { :disabled="isReplaying" @click="replay" > - {{ isReplaying ? 'FIGHTING...' : 'REPLAY FIGHT' }} + {{ isReplaying ? 'FIGHTING...' : 'VIDEO REPLAY' }}