feat: 50 new choreographies (430+ total)

15 food (sushiRoll, tacoSlam, iceCreamFreeze, wokToss, cakeSmash, etc.),
15 energy/beam (novaBlast, plasmaWhip, sonicBoom, gravityCrush, etc.),
10 silly (plushiePummel, selfieStun, vibeCheck, touchGrassSmack, etc.),
10 weapon (nunchakuSpin, tridentThrust, boomerangToss, scytheSlash, etc.).
Added to food_fight, magic_duel, space_war, meme_war, medieval_combat pools.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-08 21:32:23 +00:00
co-authored by Claude Opus 4.6
parent 561343164f
commit c876998601
+223 -5
View File
@@ -114,19 +114,19 @@ const CHALLENGE_THEMED: Record<string, { themed: string[]; generic: string[] }>
creative_writing: { themed: ['penStab', 'scrollBlast', 'bookStorm', 'enchantedArrow', 'newspaperRoll'], generic: ['jetpackDive', 'aerialSlam', 'projectile', 'rapidFlurry', 'katanaCombo', 'arcaneBarrage', 'memeBeam'] }, creative_writing: { themed: ['penStab', 'scrollBlast', 'bookStorm', 'enchantedArrow', 'newspaperRoll'], generic: ['jetpackDive', 'aerialSlam', 'projectile', 'rapidFlurry', 'katanaCombo', 'arcaneBarrage', 'memeBeam'] },
math_blitz: { themed: ['mathAttack', 'dataStream', 'pixelBeam', 'hackerAttack', 'chainLightning', 'merkleRoot', 'difficultyRetarget', 'halvingStrike'], generic: ['multiHit', 'dashPunch', 'fullScreenDash', 'rapidFlurry', 'laserBeam', 'hammerSmash', 'pinballCombo'] }, math_blitz: { themed: ['mathAttack', 'dataStream', 'pixelBeam', 'hackerAttack', 'chainLightning', 'merkleRoot', 'difficultyRetarget', 'halvingStrike'], generic: ['multiHit', 'dashPunch', 'fullScreenDash', 'rapidFlurry', 'laserBeam', 'hammerSmash', 'pinballCombo'] },
trap_card: { themed: ['trapCardAttack', 'captchaTrap', 'spiderWeb', 'flashBang', 'smokeBomb'], generic: ['gunBurst', 'teleportStrike', 'groundPound', 'zoomRush', 'sniperShot', 'rocketLauncher', 'minigunSpray'] }, trap_card: { themed: ['trapCardAttack', 'captchaTrap', 'spiderWeb', 'flashBang', 'smokeBomb'], generic: ['gunBurst', 'teleportStrike', 'groundPound', 'zoomRush', 'sniperShot', 'rocketLauncher', 'minigunSpray'] },
food_fight: { themed: ['pizzaSlam', 'bananaFling', 'pieSmash', 'hotdogWhip', 'watermelonBomb', 'sushiBarrage', 'burgerToss', 'tacoStorm', 'eggBombard', 'tomatoBarrage'], generic: ['popcornBlast', 'iceCreamFling', 'donutBarrage', 'cookieFling', 'nachoVolley', 'meatballStorm', 'candyBarrage'] }, food_fight: { themed: ['pizzaSlam', 'bananaFling', 'pieSmash', 'hotdogWhip', 'watermelonBomb', 'sushiBarrage', 'burgerToss', 'tacoStorm', 'eggBombard', 'tomatoBarrage', 'sushiRoll', 'tacoSlam', 'iceCreamFreeze', 'wokToss', 'cakeSmash', 'curryBlast', 'lobsterClaw', 'steakSlap', 'watermelonBowl'], generic: ['popcornBlast', 'iceCreamFling', 'donutBarrage', 'cookieFling', 'nachoVolley', 'meatballStorm', 'candyBarrage'] },
wrestling_match: { themed: ['piledriver', 'powerbomb', 'chokeslam', 'tombstone', 'rko', 'clothesline', 'suplex', 'germanSuplex'], generic: ['bodySlam', 'grappleFlurry', 'hurricanrana', 'moonsault', 'elbowDrop', 'spear', 'stunner'] }, wrestling_match: { themed: ['piledriver', 'powerbomb', 'chokeslam', 'tombstone', 'rko', 'clothesline', 'suplex', 'germanSuplex'], generic: ['bodySlam', 'grappleFlurry', 'hurricanrana', 'moonsault', 'elbowDrop', 'spear', 'stunner'] },
music_battle: { themed: ['bassDrop', 'guitarSolo', 'drumSolo', 'dubstepCannon', 'beatboxBlast', 'vinylScratch'], generic: ['airHornBlast', 'vuvuzelaBlast', 'sonicWave', 'bassDropBeam', 'karaokeAttack', 'airGuitar'] }, music_battle: { themed: ['bassDrop', 'guitarSolo', 'drumSolo', 'dubstepCannon', 'beatboxBlast', 'vinylScratch'], generic: ['airHornBlast', 'vuvuzelaBlast', 'sonicWave', 'bassDropBeam', 'karaokeAttack', 'airGuitar'] },
magic_duel: { themed: ['kamehameha', 'spiritBomb', 'arcaneBarrage', 'darkVoid', 'holySmite', 'shadowClone', 'hexCurse'], generic: ['fireball', 'iceLance', 'thunderStrike', 'portalPunch', 'crystalShards', 'scrollBlast', 'potionThrow'] }, magic_duel: { themed: ['kamehameha', 'spiritBomb', 'arcaneBarrage', 'darkVoid', 'holySmite', 'shadowClone', 'hexCurse', 'vortexPull', 'gravityCrush', 'darkPulse', 'prismBeam'], generic: ['fireball', 'iceLance', 'thunderStrike', 'portalPunch', 'crystalShards', 'scrollBlast', 'potionThrow'] },
sports_showdown: { themed: ['homeRunSwing', 'slapShot', 'servingAce', 'fieldGoalKick', 'bodyCheck', 'soccerKick', 'basketballDunk'], generic: ['baseballBat', 'tennisRacket', 'hockeyStick', 'bowlingBallRoll', 'tennisBallVolley', 'dropKick'] }, sports_showdown: { themed: ['homeRunSwing', 'slapShot', 'servingAce', 'fieldGoalKick', 'bodyCheck', 'soccerKick', 'basketballDunk'], generic: ['baseballBat', 'tennisRacket', 'hockeyStick', 'bowlingBallRoll', 'tennisBallVolley', 'dropKick'] },
nature_clash: { themed: ['treeSmash', 'icebergDrop', 'lavaSplash', 'tornadoFling', 'tsunamiWave', 'avalanche', 'earthquakeStrike'], generic: ['vineWhip', 'sandstorm', 'thornBarrage', 'pollenCloud', 'windSlash', 'meteorStrike'] }, nature_clash: { themed: ['treeSmash', 'icebergDrop', 'lavaSplash', 'tornadoFling', 'tsunamiWave', 'avalanche', 'earthquakeStrike'], generic: ['vineWhip', 'sandstorm', 'thornBarrage', 'pollenCloud', 'windSlash', 'meteorStrike'] },
space_war: { themed: ['blackHole', 'photonTorpedo', 'tractor_beam', 'warpDrive', 'alienAbduction', 'ionCannon', 'cosmicRay', 'bulletTimeAttack'], generic: ['laserSword', 'plasmaSword', 'asteroidBelt', 'satelliteLaser', 'plasmaBeam', 'solarFlare'] }, space_war: { themed: ['blackHole', 'photonTorpedo', 'tractor_beam', 'warpDrive', 'alienAbduction', 'ionCannon', 'cosmicRay', 'bulletTimeAttack', 'novaBlast', 'photonCannon', 'sonicBoom', 'glacialRay'], generic: ['laserSword', 'plasmaSword', 'asteroidBelt', 'satelliteLaser', 'plasmaBeam', 'solarFlare'] },
hack_battle: { themed: ['hackerAttack', 'bugSwarm', 'stackOverflow', 'segfault', 'blueScreen', 'malwareInject', 'bulletTimeAttack', 'hashSmash', 'miningRig', 'nodeSync', 'nonceGrind', 'proofOfWork'], generic: ['fourOhFour', 'ctrlAltDelete', 'aiUprising', 'captchaTrap', 'popupSpam', 'dataStream', 'glitchBeam'] }, hack_battle: { themed: ['hackerAttack', 'bugSwarm', 'stackOverflow', 'segfault', 'blueScreen', 'malwareInject', 'bulletTimeAttack', 'hashSmash', 'miningRig', 'nodeSync', 'nonceGrind', 'proofOfWork'], generic: ['fourOhFour', 'ctrlAltDelete', 'aiUprising', 'captchaTrap', 'popupSpam', 'dataStream', 'glitchBeam'] },
meme_war: { themed: ['selfieStrike', 'dabAttack', 'flossAttack', 'yeetThrow', 'tPoseAssert', 'emojiBarrage', 'memeBeam'], generic: ['rubberChicken', 'fingerGuns', 'micDrop', 'ratioAttack', 'capThrow', 'touchGrass', 'noScope'] }, meme_war: { themed: ['selfieStrike', 'dabAttack', 'flossAttack', 'yeetThrow', 'tPoseAssert', 'emojiBarrage', 'memeBeam', 'selfieStun', 'vibeCheck', 'rubberDucky', 'confettiPop', 'touchGrassSmack'], generic: ['rubberChicken', 'fingerGuns', 'micDrop', 'ratioAttack', 'capThrow', 'touchGrass', 'noScope'] },
animal_kingdom: { themed: ['sharkBite', 'bearSwipe', 'eagleDive', 'bullCharge', 'gorillaSlam', 'wolfPack', 'batSwarm'], generic: ['snakeLunge', 'scorpionSting', 'crabPinch', 'spiderWeb', 'beeSwarm', 'catScratch', 'dogPile', 'dolphinFlip'] }, animal_kingdom: { themed: ['sharkBite', 'bearSwipe', 'eagleDive', 'bullCharge', 'gorillaSlam', 'wolfPack', 'batSwarm'], generic: ['snakeLunge', 'scorpionSting', 'crabPinch', 'spiderWeb', 'beeSwarm', 'catScratch', 'dogPile', 'dolphinFlip'] },
demolition: { themed: ['dynamiteBlast', 'c4Detonation', 'nukeStrike', 'grenadeBlast', 'rocketLauncher', 'volcanoErupt'], generic: ['fireworksBurst', 'partyPopper', 'pinataSmash', 'cherryBomb', 'confettiCannon', 'anvilDrop', 'pianoDrop'] }, demolition: { themed: ['dynamiteBlast', 'c4Detonation', 'nukeStrike', 'grenadeBlast', 'rocketLauncher', 'volcanoErupt'], generic: ['fireworksBurst', 'partyPopper', 'pinataSmash', 'cherryBomb', 'confettiCannon', 'anvilDrop', 'pianoDrop'] },
vehicle_mayhem: { themed: ['motorbikeCharge', 'carSmash', 'tankRoll', 'helicopterStrike', 'zamboniCrush', 'tractorPlow'], generic: ['shoppingCart', 'forkliftCharge', 'airplaneSwoop', 'rocketRide', 'unicycleRun', 'golfCartDrive', 'boatCannon'] }, vehicle_mayhem: { themed: ['motorbikeCharge', 'carSmash', 'tankRoll', 'helicopterStrike', 'zamboniCrush', 'tractorPlow'], generic: ['shoppingCart', 'forkliftCharge', 'airplaneSwoop', 'rocketRide', 'unicycleRun', 'golfCartDrive', 'boatCannon'] },
medieval_combat: { themed: ['swordSlash', 'katanaCombo', 'battleAxe', 'maceSwing', 'crossbowBolt', 'shieldBash'], generic: ['flailSwing', 'holyWater', 'dragonBreath', 'enchantedArrow', 'laserSword', 'scrollBlast'] }, medieval_combat: { themed: ['swordSlash', 'katanaCombo', 'battleAxe', 'maceSwing', 'crossbowBolt', 'shieldBash', 'nunchakuSpin', 'tridentThrust', 'morningstar', 'scytheSlash', 'warhammerCrush'], generic: ['flailSwing', 'holyWater', 'dragonBreath', 'enchantedArrow', 'laserSword', 'scrollBlast'] },
retro_mode: { themed: ['dashPunch', 'uppercut', 'rapidFlurry', 'flyingKick', 'multiHit', 'fullScreenDash', 'backflipKick', 'cycloneKick'], generic: ['bodySlam', 'grappleFlurry', 'suplex', 'katanaCombo', 'breakdanceSweep', 'corkscrewDive', 'pinballCombo'] }, retro_mode: { themed: ['dashPunch', 'uppercut', 'rapidFlurry', 'flyingKick', 'multiHit', 'fullScreenDash', 'backflipKick', 'cycloneKick'], generic: ['bodySlam', 'grappleFlurry', 'suplex', 'katanaCombo', 'breakdanceSweep', 'corkscrewDive', 'pinballCombo'] },
} }
@@ -7176,6 +7176,209 @@ export async function createFightScene(config: FightSceneConfig) {
const stackSatsBlast = makeThrow('#ffd700', 5, 8, 50, true) const stackSatsBlast = makeThrow('#ffd700', 5, 8, 50, true)
// --- 50 NEW GENERAL CHOREOGRAPHIES ---
// -- Food (15) --
const sushiRoll = makeThrow('#ff8888', 10, 3, 55, true, '#ffffff')
const tacoSlam = makeDrop(18, 12, '#ffaa33', '#ffcc00', false)
const iceCreamFreeze = makeThrow('#aaddff', 8, 4, 45, true, '#88ccff')
const wokToss = makeThrow('#ff6600', 12, 2, 65, false, '#ffaa00')
const cakeSmash = makeDrop(22, 16, '#ffbbcc', '#ffffff', false)
const souffle = makeThrow('#ffeedd', 14, 1, 80, true, '#ffccaa')
const curryBlast = makeThrow('#ff8800', 6, 6, 40, true, '#ffaa00')
const gumballBarrage = makeThrow('#ff44ff', 5, 10, 35, true)
const frenchFryJavelin = makeThrow('#ffdd44', 3, 5, 30, false, '#ffbb00')
const coconutCannon = makeThrow('#884422', 12, 2, 70, true, '#66aa44')
const lobsterClaw = makeSwing(20, 8, '#ff3322', '#ff6644', 10, 10)
const chiliPepper = makeThrow('#ff2200', 6, 4, 45, false, '#ff4400')
const jellyBounce = makeThrow('#ff88ff', 10, 3, 90, true, '#ff44ff')
const steakSlap = makeSwing(18, 6, '#993322', '#ff4444', 8, 4)
const watermelonBowl = makeDrop(24, 18, '#44aa22', '#ff4444', true)
// -- Energy/Beam (15) --
const novaBlast = makeBeam('#ffdd00', 10, 3)
const plasmaWhip = makeSwing(40, 3, '#ff44ff', '#ff88ff', 4, 4)
async function sonicBoom(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
atk.play('special'); sfxSpecial(); await k.wait(0.1)
const wave = k.add([k.circle(10), k.pos(atk.pos.x + dir * 20, atk.pos.y - 30), k.color(safeColor(k, '#88ccff')), k.opacity(0.6), k.z(17)])
await Promise.all([
k.tween(wave.pos.x, def.pos.x, 0.15, (v: number) => { wave.pos.x = v }),
k.tween(10, isCritical ? 40 : 25, 0.15, (v: number) => { wave.radius = v }),
])
wave.destroy(); sfxExplosion(); k.shake(isCritical ? 14 : 7)
spawnSparks(def.pos.x, def.pos.y - 25, isCritical ? 12 : 6, '#88ccff')
spawnShockwave(def.pos.x, def.pos.y - 20, '#88ccff')
def.play(isCritical ? 'knockback' : 'hit')
if (isCritical) { screenFlash('#88ccff'); sfxCritical() }
const push = dir * (isCritical ? 90 : 40)
k.tween(def.pos.x, origDX + push, 0.2, (v: number) => { def.pos.x = v }, k.easings.easeOutQuad)
await k.wait(0.3); atk.play('idle')
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
}
const prismBeam = makeBeam('#ff88ff', 7, 2)
const photonCannon = makeBeam('#ffff44', 12, 1)
const vortexPull = makeBeam('#8844ff', 8, 3)
const thunderClap = makeDrop(40, 3, '#ffdd00', '#ffffff', false)
async function gravityCrush(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
atk.play('special'); sfxSpecial()
// Defender gets crushed down
const origY = def.pos.y
await k.tween(def.pos.y, GROUND_Y + 5, 0.15, (v: number) => { def.pos.y = v }, k.easings.easeInQuad)
sfxBonk(); k.shake(isCritical ? 16 : 8)
spawnSparks(def.pos.x, GROUND_Y, isCritical ? 14 : 7, '#8844ff')
def.play(isCritical ? 'knockback' : 'hit')
if (isCritical) { screenFlash('#8844ff'); sfxCritical() }
await k.wait(0.15)
await k.tween(def.pos.y, origY, 0.2, (v: number) => { def.pos.y = v }, k.easings.easeOutQuad)
const push = dir * (isCritical ? 80 : 35)
k.tween(def.pos.x, origDX + push, 0.2, (v: number) => { def.pos.x = v }, k.easings.easeOutQuad)
await k.wait(0.3); atk.play('idle')
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
}
async function shockPulse(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
atk.play('special'); sfxSpecial(); await k.wait(0.1)
const pulse = k.add([k.circle(5), k.pos(atk.pos.x, atk.pos.y - 30), k.color(safeColor(k, '#ffff00')), k.opacity(0.7), k.z(17)])
await k.tween(5, isCritical ? 60 : 40, 0.2, (v: number) => { pulse.radius = v; pulse.opacity = 0.7 - v / 100 })
pulse.destroy(); sfxExplosion(); k.shake(isCritical ? 14 : 7)
spawnSparks(def.pos.x, def.pos.y - 25, isCritical ? 12 : 6, '#ffff00')
def.play(isCritical ? 'knockback' : 'hit')
if (isCritical) { screenFlash('#ffff00'); sfxCritical() }
const push = dir * (isCritical ? 85 : 38)
k.tween(def.pos.x, origDX + push, 0.2, (v: number) => { def.pos.x = v }, k.easings.easeOutQuad)
await k.wait(0.3); atk.play('idle')
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
}
const auraBlast = makeBeam('#44ff88', 9, 2)
const darkPulse = makeBeam('#660066', 8, 2)
const radiantBeam = makeBeam('#ffaa44', 10, 1)
const glacialRay = makeBeam('#88ddff', 6, 3)
// -- Silly (10) --
async function plushiePummel(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
const contactX = origDX - dir * 45
sfxZoomWhoosh()
await k.tween(atk.pos.x, contactX, 0.12, (v: number) => { atk.pos.x = v }, k.easings.easeOutQuad)
const hits = isCritical ? 5 : 3
for (let i = 0; i < hits; i++) {
atk.play(i % 2 === 0 ? 'attack' : 'kick'); sfxBoing()
def.play('hit'); k.shake(2)
spawnSparks(def.pos.x, def.pos.y - 25, 3, '#ffbbcc')
await k.wait(0.08)
}
def.play(isCritical ? 'knockback' : 'hit'); k.shake(isCritical ? 8 : 4)
if (isCritical) { screenFlash('#ffbbcc'); sfxCritical() }
const push = dir * (isCritical ? 60 : 25)
k.tween(def.pos.x, origDX + push, 0.2, (v: number) => { def.pos.x = v }, k.easings.easeOutQuad)
await k.wait(0.3)
await Promise.all([
k.tween(atk.pos.x, origAX, 0.2, (v: number) => { atk.pos.x = v }, k.easings.easeInQuad),
k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad),
])
}
async function selfieStun(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
atk.play('special'); sfxBoing(); await k.wait(0.15)
// Camera flash
screenFlash('#ffffff', 0.08); sfxSpecial()
await k.wait(0.1)
def.play(isCritical ? 'knockback' : 'hit'); k.shake(isCritical ? 12 : 5)
spawnSparks(def.pos.x, def.pos.y - 25, isCritical ? 10 : 5, '#ffff00')
if (isCritical) sfxCritical()
const push = dir * (isCritical ? 75 : 30)
k.tween(def.pos.x, origDX + push, 0.2, (v: number) => { def.pos.x = v }, k.easings.easeOutQuad)
await k.wait(0.3); atk.play('idle')
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
}
async function vibeCheck(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
const contactX = origDX - dir * 40
sfxZoomWhoosh()
await k.tween(atk.pos.x, contactX, 0.1, (v: number) => { atk.pos.x = v }, k.easings.easeOutQuad)
atk.play('attack'); sfxPunch()
// Vibe waves
for (let i = 0; i < 3; i++) {
const wave = k.add([k.circle(5 + i * 10), k.pos(def.pos.x, def.pos.y - 25), k.color(safeColor(k, i % 2 === 0 ? '#ff44ff' : '#44ffff')), k.opacity(0.4), k.z(16)])
k.tween(wave.opacity, 0, 0.2, (v: number) => { wave.opacity = v }).then(() => wave.destroy())
}
def.play(isCritical ? 'knockback' : 'hit'); k.shake(isCritical ? 12 : 5)
spawnSparks(def.pos.x, def.pos.y - 25, isCritical ? 10 : 5, '#ff44ff')
if (isCritical) { screenFlash('#ff44ff'); sfxCritical() }
const push = dir * (isCritical ? 80 : 35)
k.tween(def.pos.x, origDX + push, 0.2, (v: number) => { def.pos.x = v }, k.easings.easeOutQuad)
await k.wait(0.3)
await Promise.all([
k.tween(atk.pos.x, origAX, 0.2, (v: number) => { atk.pos.x = v }, k.easings.easeInQuad),
k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad),
])
}
const bananaPeelSlip = makeDrop(14, 6, '#ffdd00', '#ffff00', false)
const rubberDucky = makeThrow('#ffdd00', 10, 2, 70, true, '#ffaa00')
const kazooBlast = makeBeam('#ff8844', 6, 2)
const confettiPop = makeThrow('#ff44ff', 4, 12, 40, true)
const airHornStun = makeBeam('#ff4444', 8, 1)
async function touchGrassSmack(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
atk.play('special'); sfxSpecial(); await k.wait(0.1)
// Grass shoots up from ground
const blades: any[] = []
for (let i = 0; i < (isCritical ? 8 : 4); i++) {
const gx = def.pos.x + (i - (isCritical ? 3.5 : 1.5)) * 10
const blade = k.add([k.rect(2, 0), k.pos(gx, GROUND_Y), k.color(safeColor(k, '#44cc22')), k.opacity(0.8), k.z(15)])
blades.push(blade)
k.tween(0, 40 + Math.random() * 20, 0.12, (v: number) => { blade.height = v; blade.pos.y = GROUND_Y - v })
await k.wait(0.02)
}
sfxBonk(); k.shake(isCritical ? 12 : 5)
def.play(isCritical ? 'knockback' : 'hit')
spawnSparks(def.pos.x, def.pos.y - 20, isCritical ? 10 : 5, '#44cc22')
if (isCritical) { screenFlash('#44cc22'); sfxCritical() }
await k.wait(0.2); blades.forEach(b => b.destroy())
const push = dir * (isCritical ? 75 : 30)
k.tween(def.pos.x, origDX + push, 0.2, (v: number) => { def.pos.x = v }, k.easings.easeOutQuad)
await k.wait(0.3); atk.play('idle')
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
}
// -- Weapons (10) --
const nunchakuSpin = makeSwing(25, 4, '#884422', '#ffaa44', 6, 6)
const tridentThrust = makeSwing(6, 40, '#44aaff', '#88ddff', 8, 4)
async function boomerangToss(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
atk.play('attack'); sfxPunch(); await k.wait(0.08)
const boom = k.add([k.rect(14, 4), k.pos(atk.pos.x + dir * 20, atk.pos.y - 30), k.color(safeColor(k, '#aa6633')), k.opacity(0.9), k.z(18), k.rotate(0)])
// Fly to defender
k.tween(boom.angle, 1080, 0.25, (v: number) => { boom.angle = v })
await k.tween(boom.pos.x, def.pos.x + dir * 30, 0.12, (v: number) => { boom.pos.x = v })
sfxBulletHit(); k.shake(5)
spawnSparks(def.pos.x, def.pos.y - 25, 4, '#aa6633')
def.play('hit')
// Return trip
await k.tween(boom.pos.x, atk.pos.x + dir * 15, 0.12, (v: number) => { boom.pos.x = v })
boom.destroy()
if (isCritical) {
// Double hit on return
def.play('knockback'); k.shake(14); screenFlash('#aa6633'); sfxCritical()
spawnSparks(def.pos.x, def.pos.y - 25, 10, '#aa6633')
}
const push = dir * (isCritical ? 85 : 35)
k.tween(def.pos.x, origDX + push, 0.2, (v: number) => { def.pos.x = v }, k.easings.easeOutQuad)
await k.wait(0.3); atk.play('idle')
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
}
const morningstar = makeSwing(8, 30, '#666666', '#aaaaaa', 12, 12)
const scytheSlash = makeSwing(35, 4, '#888888', '#aaddff', 6, 6)
const javelinthrow = makeThrow('#886644', 4, 1, 30, false, '#aa8866')
const shuriken = makeThrow('#999999', 6, 4, 25, false, '#cccccc')
const warhammerCrush = makeDrop(16, 30, '#666666', '#ffaa00', false)
const chakramSlice = makeThrow('#ddaa44', 8, 2, 20, true, '#ffcc44')
const blowgunDart = makeThrow('#44aa22', 3, 3, 15, false, '#66cc44')
const choreographyMap: Record<string, typeof dashPunch> = { const choreographyMap: Record<string, typeof dashPunch> = {
dashPunch, aerialSlam, flyingKick, dashThrough, uppercut, dashPunch, aerialSlam, flyingKick, dashThrough, uppercut,
multiHit, projectile, jetpackDive, gunBurst, groundPound, multiHit, projectile, jetpackDive, gunBurst, groundPound,
@@ -7279,6 +7482,21 @@ export async function createFightScene(config: FightSceneConfig) {
// Tier 5+ // Tier 5+
ultimateArmageddon, ultimateOmegaBeam, ultimateBeyondTheScreen, ultimateMatrixDodge, ultimateWorldEnder, ultimateArmageddon, ultimateOmegaBeam, ultimateBeyondTheScreen, ultimateMatrixDodge, ultimateWorldEnder,
ultimateAbsoluteZero, ultimateSolarCannon, ultimatePhantomStrike, ultimateGodPunch, ultimateVoidCollapse, ultimateAbsoluteZero, ultimateSolarCannon, ultimatePhantomStrike, ultimateGodPunch, ultimateVoidCollapse,
// --- 50 NEW GENERAL ---
// Food
sushiRoll, tacoSlam, iceCreamFreeze, wokToss, cakeSmash,
souffle, curryBlast, gumballBarrage, frenchFryJavelin, coconutCannon,
lobsterClaw, chiliPepper, jellyBounce, steakSlap, watermelonBowl,
// Energy/Beam
novaBlast, plasmaWhip, sonicBoom, prismBeam,
photonCannon, vortexPull, thunderClap, gravityCrush, shockPulse,
auraBlast, darkPulse, radiantBeam, glacialRay,
// Silly
plushiePummel, selfieStun, vibeCheck, bananaPeelSlip, rubberDucky,
kazooBlast, confettiPop, airHornStun, touchGrassSmack,
// Weapons
nunchakuSpin, tridentThrust, boomerangToss, morningstar, scytheSlash,
javelinthrow, shuriken, warhammerCrush, chakramSlice, blowgunDart,
// --- BITCOIN-THEMED (30 new) --- // --- BITCOIN-THEMED (30 new) ---
lightningBolt, hashSmash, blockDrop, mempoolFlood, difficultyBomb, lightningBolt, hashSmash, blockDrop, mempoolFlood, difficultyBomb,
feeSpike, utxoScatter, nodeSync, relayBounce, channelForceClose, feeSpike, utxoScatter, nodeSync, relayBounce, channelForceClose,