feat: comedy overhaul start, profile page, bot setup docs, auth improvements

Rewrites announcer commentary (HYPE_LINES, DEEP_INTROS, ROUND_HYPE) with
modern edgy humor. Adds BOT_SETUP.md, bot SDK, customization engine,
profile page character display, persistent auth, rate limit tweaks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-07 08:52:24 +00:00
co-authored by Claude Opus 4.6
parent 4a35e1e0b5
commit 559782c8ce
15 changed files with 1086 additions and 58 deletions
+4 -4
View File
@@ -25,8 +25,8 @@ interface Round {
interface FightData {
id: string
botA: { id: string; name: string; avatarSeed: string; archetype?: string; profilePicUrl?: string | null; eloRating: number; wins: number; losses: number; tier: number } | null
botB: { id: string; name: string; avatarSeed: string; archetype?: string; profilePicUrl?: string | null; eloRating: number; wins: number; losses: number; tier: number } | null
botA: { id: string; name: string; avatarSeed: string; archetype?: string; customization?: Record<string, unknown> | null; profilePicUrl?: string | null; eloRating: number; wins: number; losses: number; tier: number } | null
botB: { id: string; name: string; avatarSeed: string; archetype?: string; customization?: Record<string, unknown> | null; profilePicUrl?: string | null; eloRating: number; wins: number; losses: number; tier: number } | null
arenaInfo: { id: string; name: string; description: string; modifier: string | null } | null
arena: string
winnerId: string | null
@@ -107,8 +107,8 @@ async function initScene() {
scene = await createFightScene({
canvas: canvasRef.value,
botA: { name: props.fight.botA.name, seed: props.fight.botA.avatarSeed || props.fight.botA.name, tier: props.fight.botA.tier, archetype: props.fight.botA.archetype },
botB: { name: props.fight.botB.name, seed: props.fight.botB.avatarSeed || props.fight.botB.name, tier: props.fight.botB.tier, archetype: props.fight.botB.archetype },
botA: { name: props.fight.botA.name, seed: props.fight.botA.avatarSeed || props.fight.botA.name, tier: props.fight.botA.tier, archetype: props.fight.botA.archetype, customization: props.fight.botA.customization as any },
botB: { name: props.fight.botB.name, seed: props.fight.botB.avatarSeed || props.fight.botB.name, tier: props.fight.botB.tier, archetype: props.fight.botB.archetype, customization: props.fight.botB.customization as any },
arena: props.fight.arena,
})
}
+4 -3
View File
@@ -1,12 +1,13 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch } from 'vue'
import { generateSpriteSheet, getBotColors, FRAME_SIZE, ANIMATIONS } from '../game/sprites'
import { generateSpriteSheet, getBotColors, FRAME_SIZE, ANIMATIONS, type SpriteCustomization } from '../game/sprites'
const props = defineProps<{
seed: string
archetype?: string
tier?: number
size?: number
customization?: SpriteCustomization
}>()
const canvasRef = ref<HTMLCanvasElement>()
@@ -37,7 +38,7 @@ function render() {
function loadSprite() {
const colors = getBotColors(props.seed)
const dataUrl = generateSpriteSheet(props.seed, props.tier || 0, colors.primary, colors.secondary, props.archetype)
const dataUrl = generateSpriteSheet(props.seed, props.tier || 0, colors.primary, colors.secondary, props.archetype, props.customization)
img = new Image()
img.onload = () => render()
img.src = dataUrl
@@ -45,7 +46,7 @@ function loadSprite() {
onMounted(() => loadSprite())
watch(() => [props.seed, props.archetype], () => {
watch(() => [props.seed, props.archetype, props.customization], () => {
if (animHandle) clearTimeout(animHandle)
frame = 0
loadSprite()