From c8769986018304024ae8994fe1d57969aa2f57ed Mon Sep 17 00:00:00 2001 From: Dorian Date: Sun, 8 Mar 2026 21:32:23 +0000 Subject: [PATCH] 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 --- frontend/src/game/FightScene.ts | 228 +++++++++++++++++++++++++++++++- 1 file changed, 223 insertions(+), 5 deletions(-) diff --git a/frontend/src/game/FightScene.ts b/frontend/src/game/FightScene.ts index e47d6f4..570ec64 100644 --- a/frontend/src/game/FightScene.ts +++ b/frontend/src/game/FightScene.ts @@ -114,19 +114,19 @@ const CHALLENGE_THEMED: Record 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'] }, 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'] }, 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'] }, 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'] }, - 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'] }, 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'] }, - 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'] }, } @@ -7176,6 +7176,209 @@ export async function createFightScene(config: FightSceneConfig) { 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 = { dashPunch, aerialSlam, flyingKick, dashThrough, uppercut, multiHit, projectile, jetpackDive, gunBurst, groundPound, @@ -7279,6 +7482,21 @@ export async function createFightScene(config: FightSceneConfig) { // Tier 5+ ultimateArmageddon, ultimateOmegaBeam, ultimateBeyondTheScreen, ultimateMatrixDodge, ultimateWorldEnder, 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) --- lightningBolt, hashSmash, blockDrop, mempoolFlood, difficultyBomb, feeSpike, utxoScatter, nodeSync, relayBounce, channelForceClose,