refactor: type Fighter interface for all choreographies
Define Fighter type alias using Kaplay's GameObj with SpriteComp, PosComp, ScaleComp, AnchorComp, OpacityComp, ColorComp, RotateComp, and ZComp. Replace 81 choreography function signatures from (atk: any, def: any, ...) to (atk: Fighter, def: Fighter, ...). Type loadSpriteWithTimeout opts as LoadSpriteOpt. Type lines/bands arrays as GameObj[]. Type spawnAfterimages and cameraZoom fighter params. Add as Fighter casts at k.get() call sites. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
156c727f82
commit
1ca8a6feb0
+137
-134
@@ -1,4 +1,7 @@
|
||||
import kaplay from 'kaplay'
|
||||
import type { GameObj, SpriteComp, PosComp, ScaleComp, AnchorComp, OpacityComp, ColorComp, RotateComp, ZComp, LoadSpriteOpt } from 'kaplay'
|
||||
|
||||
type Fighter = GameObj<SpriteComp | PosComp | ScaleComp | AnchorComp | OpacityComp | ColorComp | RotateComp | ZComp>
|
||||
import { generateSpriteSheet, generateJudgeSpriteSheet, generateHumanSpriteSheet, generateHumanFighterSpriteSheet, getBotColors, FRAME_SIZE, MAX_FRAMES, TOTAL_ROWS, ANIMATIONS, JUDGE_ANIMATIONS, JUDGE_MAX_FRAMES, JUDGE_ROWS, HUMAN_ANIMATIONS, HUMAN_MAX_FRAMES, HUMAN_ROWS, type SpriteCustomization } from './sprites'
|
||||
import {
|
||||
sfxPunch, sfxKick, sfxSpecial, sfxCritical, sfxGunshot, sfxBulletHit,
|
||||
@@ -293,7 +296,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
const isHumanB = botB.archetype === 'human'
|
||||
|
||||
// Helper: load sprite with a 5s timeout so mobile never hangs forever
|
||||
async function loadSpriteWithTimeout(name: string, src: string, opts: any): Promise<void> {
|
||||
async function loadSpriteWithTimeout(name: string, src: string, opts: LoadSpriteOpt): Promise<void> {
|
||||
try {
|
||||
await Promise.race([
|
||||
k.loadSprite(name, src, opts),
|
||||
@@ -519,7 +522,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// Scanline glitch — horizontal bands flicker
|
||||
function scanlineGlitch(duration: number = 0.3) {
|
||||
const lines: any[] = []
|
||||
const lines: GameObj[] = []
|
||||
const count = 6 + Math.floor(Math.random() * 8)
|
||||
for (let i = 0; i < count; i++) {
|
||||
const ly = Math.random() * H
|
||||
@@ -540,7 +543,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// VHS tracking distortion — horizontal offset bands
|
||||
function vhsTracking(duration: number = 0.4) {
|
||||
const bands: any[] = []
|
||||
const bands: GameObj[] = []
|
||||
const bandCount = 3
|
||||
for (let i = 0; i < bandCount; i++) {
|
||||
const by = Math.random() * H
|
||||
@@ -576,8 +579,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// Schizo cut — rapid zoom/position jitter simulating jump cuts
|
||||
async function schizoCut() {
|
||||
const fA = k.get('fighterA')[0]
|
||||
const fB = k.get('fighterB')[0]
|
||||
const fA = k.get('fighterA')[0] as Fighter
|
||||
const fB = k.get('fighterB')[0] as Fighter
|
||||
if (!fA || !fB) return
|
||||
const origAX = fA.pos.x, origBX = fB.pos.x
|
||||
const origAY = fA.pos.y, origBY = fB.pos.y
|
||||
@@ -598,7 +601,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// Hyperspeed lines — converging toward a point
|
||||
function hyperSpeedLines(targetX: number, targetY: number, duration: number = 0.3) {
|
||||
const lines: any[] = []
|
||||
const lines: GameObj[] = []
|
||||
for (let i = 0; i < 16; i++) {
|
||||
const angle = (i / 16) * Math.PI * 2
|
||||
const dist = 300 + Math.random() * 200
|
||||
@@ -650,7 +653,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// Spawn afterimages: trailing ghost sprites behind a moving fighter
|
||||
function spawnAfterimages(fighter: any, count: number = 3) {
|
||||
function spawnAfterimages(fighter: Fighter, count: number = 3) {
|
||||
if (!fighter?.exists()) return
|
||||
for (let i = 0; i < count; i++) {
|
||||
const ghost = k.add([
|
||||
@@ -667,7 +670,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// Camera zoom: scale fighters toward/away from a focal point for impact emphasis
|
||||
async function cameraZoom(
|
||||
fighters: any[],
|
||||
fighters: Fighter[],
|
||||
savedScales: { x: number; y: number }[],
|
||||
zoomFactor: number,
|
||||
duration: number,
|
||||
@@ -685,7 +688,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// Grotesque close-up overlays removed — noops retained for call-site compatibility
|
||||
function spawnGrotesqueDetails(_fighter: any, _scaleFactor: number) {}
|
||||
function spawnGrotesqueDetails(_fighter: Fighter, _scaleFactor: number) {}
|
||||
function destroyGrotesqueDetails() {}
|
||||
// Arena-specific background decoration
|
||||
function drawArenaDecor() {
|
||||
@@ -2038,7 +2041,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
// === CHOREOGRAPHY FUNCTIONS ===
|
||||
// Each returns a Promise and handles all movement + animation
|
||||
|
||||
async function dashPunch(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function dashPunch(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const contactX = origDX - dir * 50
|
||||
// Fast sprint to contact
|
||||
await k.tween(atk.pos.x, contactX, 0.12, (v) => { atk.pos.x = v }, k.easings.easeOutQuad)
|
||||
@@ -2061,7 +2064,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
])
|
||||
}
|
||||
|
||||
async function aerialSlam(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function aerialSlam(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const origAY = atk.pos.y
|
||||
const contactX = origDX - dir * 20
|
||||
// Jump way up
|
||||
@@ -2090,7 +2093,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
])
|
||||
}
|
||||
|
||||
async function flyingKick(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function flyingKick(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const origAY = atk.pos.y
|
||||
const contactX = origDX - dir * 30
|
||||
// Small jump + fly horizontally
|
||||
@@ -2117,7 +2120,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
])
|
||||
}
|
||||
|
||||
async function dashThrough(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function dashThrough(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const behindX = origDX + dir * 80
|
||||
atk.play('attack')
|
||||
sfxSpecial()
|
||||
@@ -2137,7 +2140,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.wait(0.1)
|
||||
}
|
||||
|
||||
async function uppercut(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function uppercut(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const contactX = origDX - dir * 40
|
||||
const origDY = def.pos.y
|
||||
// Run to contact
|
||||
@@ -2163,7 +2166,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(atk.pos.x, origAX, 0.2, (v) => { atk.pos.x = v }, k.easings.easeInQuad)
|
||||
}
|
||||
|
||||
async function multiHit(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function multiHit(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const contactX = origDX - dir * 45
|
||||
// Sprint to contact
|
||||
await k.tween(atk.pos.x, contactX, 0.1, (v) => { atk.pos.x = v }, k.easings.easeOutQuad)
|
||||
@@ -2192,7 +2195,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
])
|
||||
}
|
||||
|
||||
async function projectile(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function projectile(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
await k.wait(0.25)
|
||||
@@ -2213,7 +2216,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function jetpackDive(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function jetpackDive(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const origAY = atk.pos.y
|
||||
sfxJetpack()
|
||||
// Jetpack blast off - fly way up off screen
|
||||
@@ -2250,7 +2253,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
])
|
||||
}
|
||||
|
||||
async function gunBurst(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function gunBurst(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
// Spawn visible pixel gun prop
|
||||
const gunX = atk.pos.x + dir * 15
|
||||
@@ -2292,7 +2295,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function groundPound(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function groundPound(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const origAY = atk.pos.y
|
||||
// Jump super high off screen
|
||||
sfxJetpack()
|
||||
@@ -2332,7 +2335,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
])
|
||||
}
|
||||
|
||||
async function teleportStrike(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function teleportStrike(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Fade out
|
||||
sfxSpecial()
|
||||
spawnSparks(atk.pos.x, atk.pos.y - 30, 8, '#b83dff')
|
||||
@@ -2365,7 +2368,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function fullScreenDash(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function fullScreenDash(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Back up to wall
|
||||
const wallX = dir === 1 ? 20 : W - 20
|
||||
await k.tween(atk.pos.x, wallX, 0.15, (v) => { atk.pos.x = v }, k.easings.easeOutQuad)
|
||||
@@ -2448,7 +2451,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// CODE GOLF: swing a giant golf club, golf balls fly at opponent
|
||||
async function golfClubSmash(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function golfClubSmash(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const contactX = origDX - dir * 60
|
||||
await k.tween(atk.pos.x, contactX, 0.15, (v) => { atk.pos.x = v }, k.easings.easeOutQuad)
|
||||
// Spawn golf club (long thin rect)
|
||||
@@ -2509,7 +2512,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// ROAST BATTLE: fire breath — stream of fire from attacker's face
|
||||
async function fireBreath(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function fireBreath(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const contactX = origDX - dir * 80
|
||||
await k.tween(atk.pos.x, contactX, 0.12, (v) => { atk.pos.x = v }, k.easings.easeOutQuad)
|
||||
atk.play('special')
|
||||
@@ -2567,7 +2570,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// RIDDLE: question mark barrage rains from the sky
|
||||
async function riddleBarrage(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function riddleBarrage(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
sfxZap()
|
||||
@@ -2612,7 +2615,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// HALLUCINATION CHECK: clone confusion — multiple fake attackers appear
|
||||
async function cloneStrike(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function cloneStrike(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
sfxZap()
|
||||
// Spawn 3-5 "ghost" clones that zip around
|
||||
const cloneCount = isCritical ? 5 : 3
|
||||
@@ -2662,7 +2665,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// TOKEN ECONOMY: coin shower — coins rain down on opponent
|
||||
async function coinShower(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function coinShower(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
sfxBoing()
|
||||
@@ -2698,7 +2701,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// CREATIVE WRITING: giant pen stab + ink splatter
|
||||
async function penStab(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function penStab(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Spawn a giant pen/quill
|
||||
const penX = atk.pos.x + dir * 15
|
||||
const penY = atk.pos.y - 70
|
||||
@@ -2757,7 +2760,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// MATH BLITZ: number projectiles fly at opponent
|
||||
async function mathAttack(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function mathAttack(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
await k.wait(0.15)
|
||||
@@ -2798,7 +2801,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// TRAP CARD: card shuriken + trap springs
|
||||
async function trapCardAttack(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function trapCardAttack(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
await k.wait(0.1)
|
||||
@@ -2863,7 +2866,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// SPEED BLITZ: afterimage dash — leaves ghost copies behind
|
||||
async function afterimageDash(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function afterimageDash(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
sfxSpecial()
|
||||
const contactX = origDX - dir * 40
|
||||
// Leave afterimages as we dash
|
||||
@@ -2911,7 +2914,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// BULLET TIME: slow-mo dodge, afterimages trail behind, golden traces, devastating counter
|
||||
async function bulletTimeAttack(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function bulletTimeAttack(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Phase 1: Darken screen — entering bullet time
|
||||
const dim = k.add([k.rect(W, H), k.pos(0, 0), k.color(safeColor(k, '#000011')), k.opacity(0), k.z(25)])
|
||||
await k.tween(0, 0.45, 0.15, (v) => { dim.opacity = v })
|
||||
@@ -3017,7 +3020,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// INVISIBLE SPEED: so fast you can barely see — just blur lines and impact
|
||||
async function lightningRush(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function lightningRush(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
sfxSpecial()
|
||||
// Attacker vanishes
|
||||
atk.opacity = 0
|
||||
@@ -3069,7 +3072,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// ZOOM RUSH: fly toward camera (scale huge) then slam back into opponent
|
||||
async function zoomRush(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function zoomRush(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const origAY = atk.pos.y
|
||||
const origScaleX = atk.scale.x
|
||||
const origScaleY = atk.scale.y
|
||||
@@ -3150,7 +3153,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// RAPID FLURRY: DBZ-style machine gun punches — so fast it's a blur
|
||||
async function rapidFlurry(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function rapidFlurry(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const contactX = origDX - dir * 40
|
||||
// Sprint to contact
|
||||
sfxSpecial()
|
||||
@@ -3210,7 +3213,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// SWORD SLASH: giant energy sword swing with arc trail
|
||||
async function swordSlash(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function swordSlash(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const contactX = origDX - dir * 50
|
||||
await k.tween(atk.pos.x, contactX, 0.1, (v) => { atk.pos.x = v }, k.easings.easeOutQuad)
|
||||
atk.play('special')
|
||||
@@ -3245,7 +3248,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// HAMMER SMASH: pull out giant hammer, overhead slam with ground crack
|
||||
async function hammerSmash(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function hammerSmash(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const contactX = origDX - dir * 40
|
||||
await k.tween(atk.pos.x, contactX, 0.12, (v) => { atk.pos.x = v }, k.easings.easeOutQuad)
|
||||
// Giant hammer
|
||||
@@ -3277,7 +3280,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// LASER BEAM: charge up then fire continuous beam across screen
|
||||
async function laserBeam(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function laserBeam(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
// Charge up (growing ball of energy)
|
||||
@@ -3308,7 +3311,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// ROCKET LAUNCHER: fire a big slow rocket that explodes on impact
|
||||
async function rocketLauncher(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function rocketLauncher(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
await k.wait(0.15)
|
||||
@@ -3352,7 +3355,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// BOMB THROW: lob an arcing bomb that bounces once then detonates
|
||||
async function bombThrow(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function bombThrow(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('attack')
|
||||
sfxSpecial()
|
||||
const bombX = atk.pos.x + dir * 20
|
||||
@@ -3387,7 +3390,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// MINIGUN SPRAY: sustained automatic fire with shell casings
|
||||
async function minigunSpray(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function minigunSpray(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
// Spawn visible pixel minigun
|
||||
const gpx = atk.pos.x + dir * 15
|
||||
@@ -3433,7 +3436,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// SNIPER SHOT: long pause, laser sight, then one devastating hit
|
||||
async function sniperShot(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function sniperShot(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Back up to wall
|
||||
const wallX = dir === 1 ? 30 : W - 30
|
||||
await k.tween(atk.pos.x, wallX, 0.2, (v) => { atk.pos.x = v }, k.easings.easeOutQuad)
|
||||
@@ -3471,7 +3474,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// WHIP CRACK: ranged whip attack with crack sound
|
||||
async function whipCrack(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function whipCrack(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('attack')
|
||||
sfxSpecial()
|
||||
await k.wait(0.1)
|
||||
@@ -3514,7 +3517,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// KATANA COMBO: triple slash with cross patterns
|
||||
async function katanaCombo(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function katanaCombo(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const contactX = origDX - dir * 45
|
||||
sfxSpecial()
|
||||
await k.tween(atk.pos.x, contactX, 0.08, (v) => { atk.pos.x = v }, k.easings.easeOutQuad)
|
||||
@@ -3552,7 +3555,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// CHAINSAW: charge with buzzing chainsaw, multi-hit grind
|
||||
async function chainsawRev(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function chainsawRev(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const contactX = origDX - dir * 35
|
||||
atk.play('special')
|
||||
// Chainsaw buzzing (visual: vibrating rect)
|
||||
@@ -3595,7 +3598,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// MOTORBIKE CHARGE: ride a motorbike across the screen and slam into defender
|
||||
async function motorbikeCharge(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function motorbikeCharge(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Back up to edge
|
||||
const startX = dir === 1 ? -30 : W + 30
|
||||
atk.opacity = 0
|
||||
@@ -3643,7 +3646,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// CAR SMASH: drive a car from off-screen, defender gets sent flying
|
||||
async function carSmash(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function carSmash(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.opacity = 0
|
||||
const carY = GROUND_Y - 20
|
||||
const startX = dir === 1 ? -60 : W + 60
|
||||
@@ -3688,7 +3691,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// BOAT CANNON: a boat slides across the ground and fires cannons
|
||||
async function boatCannon(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function boatCannon(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
// Build boat
|
||||
@@ -3731,7 +3734,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// ANVIL DROP: classic cartoon — anvil falls from sky onto opponent
|
||||
async function anvilDrop(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function anvilDrop(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
await k.wait(0.15)
|
||||
@@ -3766,7 +3769,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// POCKET CANNON: reach into pocket, pull out comically oversized gun, fire
|
||||
async function pocketCannon(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function pocketCannon(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// "Reach into pocket" — arm down motion
|
||||
atk.play('special')
|
||||
await k.wait(0.12)
|
||||
@@ -3866,7 +3869,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// GRAPPLE FLURRY: both bots close in and trade sustained blows without splitting apart
|
||||
async function grappleFlurry(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function grappleFlurry(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Both rush to center — meet in the middle
|
||||
const meetX = (origAX + origDX) / 2
|
||||
const atkMeetX = meetX - dir * 25
|
||||
@@ -3928,7 +3931,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// BODY SLAM: wrestling-style grab, lift, and slam
|
||||
async function bodySlam(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function bodySlam(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Rush in close
|
||||
sfxSpecial()
|
||||
const contactX = def.pos.x - dir * 30
|
||||
@@ -3978,7 +3981,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// PINBALL COMBO: bounce the opponent between walls/edges like a pinball
|
||||
async function pinballCombo(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function pinballCombo(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Initial launch punch
|
||||
atk.play('attack')
|
||||
sfxPunch()
|
||||
@@ -4026,7 +4029,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// SUPLEX: grab from behind, lift, and drive headfirst into ground
|
||||
async function suplex(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function suplex(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Dash behind defender
|
||||
sfxSpecial()
|
||||
const behindX = def.pos.x + dir * 30
|
||||
@@ -4379,7 +4382,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
// === DEFENSE / SHIELD SYSTEM ===
|
||||
|
||||
async function playBlock(side: 'a' | 'b') {
|
||||
const defender = k.get(side === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const defender = k.get(side === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
if (!defender) return
|
||||
const dir = side === 'a' ? 1 : -1
|
||||
// Spawn shield in front
|
||||
@@ -5246,7 +5249,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
// ============================================================
|
||||
|
||||
// --- TIER 2+ ULTIMATES (Silver) — flashy multi-hits ---
|
||||
async function ultimateRapidBarrage(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateRapidBarrage(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Rush in and land 8 alternating punches + kicks with screen shake
|
||||
const contactX = origDX - dir * 45
|
||||
sfxZoomWhoosh()
|
||||
@@ -5275,7 +5278,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateOrbitalStrike(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateOrbitalStrike(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Call down 5 orbital beams on the defender's position
|
||||
atk.play('special'); sfxSpecial()
|
||||
for (let i = 0; i < 5; i++) {
|
||||
@@ -5291,7 +5294,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.wait(0.3); atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateCloneSurround(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateCloneSurround(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Spawn 4 clones around the defender, all attack simultaneously
|
||||
const clones: any[] = []
|
||||
const positions = [
|
||||
@@ -5316,7 +5319,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.wait(0.3)
|
||||
}
|
||||
|
||||
async function ultimateGatlingFury(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateGatlingFury(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Pull out massive gatling gun, fire 12 shots with screen shake
|
||||
atk.play('special')
|
||||
const gunLen = 60
|
||||
@@ -5343,7 +5346,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.wait(0.3); atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateEarthquake(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateEarthquake(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Jump high, slam ground, cracks + shockwaves across screen
|
||||
sfxZoomWhoosh()
|
||||
await k.tween(atk.pos.y, GROUND_Y - 150, 0.2, (v) => { atk.pos.y = v }, k.easings.easeOutQuad)
|
||||
@@ -5373,7 +5376,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
const ultimateMeteorShower = makeSwarm('#ff6600', 8, 10, 500, true)
|
||||
|
||||
// --- TIER 3+ ULTIMATES (Gold) — multi-phase, full screen ---
|
||||
async function ultimateScreenNuke(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateScreenNuke(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Charge up glowing orb, launch it, entire screen whites out
|
||||
atk.play('special'); sfxSpecial()
|
||||
const orb = k.add([k.circle(5), k.pos(atk.pos.x + dir * 20, atk.pos.y - 30), k.color(safeColor(k,'#ffffff')), k.opacity(0.8), k.z(18)])
|
||||
@@ -5398,7 +5401,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.wait(0.4); atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateBlackHoleVortex(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateBlackHoleVortex(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Summon black hole that pulls defender in, crushes, and ejects
|
||||
atk.play('special'); sfxZap()
|
||||
const bh = k.add([k.circle(8), k.pos(W / 2, GROUND_Y - 50), k.anchor('center'), k.color(safeColor(k,'#220044')), k.opacity(0.9), k.z(20)])
|
||||
@@ -5429,7 +5432,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.wait(0.2); atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateDimensionalRift(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateDimensionalRift(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Open rift, attacker disappears, attacks from multiple portals
|
||||
sfxZap(); atk.opacity = 0
|
||||
const colors = ['#ff2d7b', '#00f0ff', '#39ff14', '#b83dff']
|
||||
@@ -5460,7 +5463,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateTimeSlow(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateTimeSlow(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Everything goes slow-mo, attacker lands 6 devastating hits in "frozen" time
|
||||
scanlineGlitch(0.1)
|
||||
// Dim screen
|
||||
@@ -5486,7 +5489,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateSummonArmy(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateSummonArmy(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Summon an army of 8 mini clones that charge across the screen
|
||||
atk.play('special'); sfxSpecial()
|
||||
const army: any[] = []
|
||||
@@ -5516,7 +5519,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
const ultimateAvalancheDrop = makeExplosion(30, 30, '#aaeeff', 0.2, '#ffffff', true)
|
||||
|
||||
// ULTIMATE BULLET TIME BARRAGE — full slow-mo cinematic: dodge rain of projectiles, afterimage rush, multi-hit counter
|
||||
async function ultimateBulletTimeBarrage(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateBulletTimeBarrage(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Phase 1: World goes dark, heavy slow-mo overlay
|
||||
const dim = k.add([k.rect(W, H), k.pos(0, 0), k.color(safeColor(k, '#000022')), k.opacity(0), k.z(25)])
|
||||
await k.tween(0, 0.55, 0.2, (v) => { dim.opacity = v })
|
||||
@@ -5620,7 +5623,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
// --- TIER 4+ ULTIMATES (Platinum) — full screen, multi-phase spectacles ---
|
||||
async function ultimateFinaleRush(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateFinaleRush(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Full-screen dash through, reverse, dash again, then combo finish
|
||||
sfxZoomWhoosh()
|
||||
// First pass
|
||||
@@ -5649,7 +5652,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateMeteorCrash(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateMeteorCrash(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Attacker launches into sky, becomes a meteor, crashes into arena
|
||||
sfxZoomWhoosh(); atk.play('special')
|
||||
await k.tween(atk.pos.y, -100, 0.2, (v) => { atk.pos.y = v }, k.easings.easeInQuad)
|
||||
@@ -5682,7 +5685,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateScreenShatter(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateScreenShatter(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Hit so hard the "screen" shatters with fragment overlay
|
||||
const contactX = origDX - dir * 45
|
||||
await k.tween(atk.pos.x, contactX, 0.1, (v) => { atk.pos.x = v }, k.easings.easeOutQuad)
|
||||
@@ -5709,7 +5712,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateGravityReverse(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateGravityReverse(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Flip gravity — defender floats up, gets juggled, slammed back down
|
||||
atk.play('special'); sfxZap()
|
||||
// Defender floats up
|
||||
@@ -5733,7 +5736,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.wait(0.3); atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateInfiniteCombo(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateInfiniteCombo(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// 15-hit combo with escalating screen effects
|
||||
const contactX = origDX - dir * 40
|
||||
sfxZoomWhoosh()
|
||||
@@ -5769,7 +5772,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
const ultimateRocketBarrage = makeSwarm('#ff6600', 10, 14, 550, false)
|
||||
|
||||
// --- TIER 5+ ULTIMATES (Diamond/Legend) — absolutely insane full-screen ---
|
||||
async function ultimateArmageddon(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateArmageddon(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Full screen goes dark, rain of fire, massive explosion, screen flash
|
||||
const darkness = k.add([k.rect(W, H), k.pos(0, 0), k.color(safeColor(k,'#000000')), k.opacity(0), k.z(25)])
|
||||
await k.tween(0, 0.7, 0.3, (v) => { darkness.opacity = v })
|
||||
@@ -5797,7 +5800,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.wait(0.5); atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateOmegaBeam(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateOmegaBeam(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Charge up, fire a massive full-width beam that covers half the screen
|
||||
atk.play('special'); sfxSpecial()
|
||||
// Charge particles converging on attacker
|
||||
@@ -5829,7 +5832,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.wait(0.2); atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateBeyondTheScreen(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateBeyondTheScreen(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Attacker punches defender so hard they "break" off-screen, then gravity brings them back
|
||||
const contactX = origDX - dir * 45
|
||||
sfxZoomWhoosh()
|
||||
@@ -5860,7 +5863,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateMatrixDodge(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateMatrixDodge(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Matrix-style slow-mo: attacker fires 3 projectiles, "dodges" in slo-mo, then counters
|
||||
atk.play('special')
|
||||
// Fire 3 slow projectiles
|
||||
@@ -5891,7 +5894,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
atk.play('idle')
|
||||
}
|
||||
|
||||
async function ultimateWorldEnder(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateWorldEnder(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// The ultimate ultimate: 3-phase attack — air combo, ground slam, finishing beam
|
||||
// Phase 1: Launch defender into air
|
||||
const contactX = origDX - dir * 45
|
||||
@@ -5945,7 +5948,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
// THE CREATOR — Exclusive choreographies (bitcoin-themed)
|
||||
// ═══════════════════════════════════════════════════════
|
||||
|
||||
async function bitcoinRain(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function bitcoinRain(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
await k.wait(0.2)
|
||||
@@ -5987,7 +5990,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function lightningInvoice(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function lightningInvoice(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxZap()
|
||||
await k.wait(0.15)
|
||||
@@ -6031,7 +6034,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function satoshiStrike(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function satoshiStrike(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
await k.wait(0.1)
|
||||
@@ -6069,7 +6072,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function hashRateOverload(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function hashRateOverload(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
// Screen fills with scrolling hash text (simulated with falling green/gold rects)
|
||||
@@ -6105,7 +6108,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function blockchainSlam(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function blockchainSlam(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
const contactX = origDX - dir * 60
|
||||
sfxZoomWhoosh()
|
||||
await k.tween(atk.pos.x, contactX, 0.12, (v: number) => { atk.pos.x = v }, k.easings.easeOutQuad)
|
||||
@@ -6144,7 +6147,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
atk.play('idle')
|
||||
}
|
||||
|
||||
async function creatorMode(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function creatorMode(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
// Typing effect — rapid small flashes from attacker
|
||||
@@ -6181,7 +6184,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function morphStrike(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function morphStrike(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Flash golden — the morph is handled by the morph system
|
||||
// This move itself is a quick dash-hit with gold sparks
|
||||
screenFlash('#ffd700', 0.08)
|
||||
@@ -6205,7 +6208,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
atk.play('idle')
|
||||
}
|
||||
|
||||
async function divineIntervention(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function divineIntervention(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Ascend off screen
|
||||
sfxZoomWhoosh()
|
||||
atk.play('win')
|
||||
@@ -6250,7 +6253,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// ── Creator ₿ Swarm Variations ──
|
||||
|
||||
async function bitcoinSwarm(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function bitcoinSwarm(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Swarm of ₿ letters fly from creator toward defender with zigzag paths
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
@@ -6300,7 +6303,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function satoshiTornado(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function satoshiTornado(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// ₿ letters spiral around the defender in a tightening vortex then explode
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
@@ -6360,7 +6363,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function hodlWave(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function hodlWave(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Wall of ₿ letters advancing across the screen like a tidal wave
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
@@ -6414,7 +6417,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function bitcoinBarrage(atk: any, def: any, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
async function bitcoinBarrage(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, isCritical: boolean) {
|
||||
// Rapid-fire ₿ letters shot from the creator's laptop like bullets
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
@@ -6462,7 +6465,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// ── Creator Ultimates ──
|
||||
|
||||
async function ultimateGenesisBlock(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateGenesisBlock(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Screen goes dark, massive genesis block materializes and detonates
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
@@ -6495,7 +6498,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function ultimateTheHalving(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateTheHalving(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Screen splits horizontally with a golden line
|
||||
atk.play('special')
|
||||
sfxZap()
|
||||
@@ -6528,7 +6531,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function ultimateFullNodeCrush(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateFullNodeCrush(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Giant server rack drops from above
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
@@ -6567,7 +6570,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
await k.tween(def.pos.x, origDX, 0.3, (v: number) => { def.pos.x = v }, k.easings.easeInOutQuad)
|
||||
}
|
||||
|
||||
async function ultimateSatoshiVision(atk: any, def: any, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
async function ultimateSatoshiVision(atk: Fighter, def: Fighter, dir: number, origAX: number, origDX: number, _isCrit: boolean) {
|
||||
// Everything turns gold — defender trapped in bitcoin block
|
||||
atk.play('special')
|
||||
sfxSpecial()
|
||||
@@ -7179,7 +7182,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
|
||||
function showSpeechBubble(side: 'a' | 'b', text: string, duration: number = 3) {
|
||||
const fighter = k.get(side === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const fighter = k.get(side === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
if (!fighter || !text) return
|
||||
|
||||
// Kill previous bubble on this side
|
||||
@@ -7332,7 +7335,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
function startTalking(side: 'a' | 'b') {
|
||||
stopTalking(side) // cleanup any existing
|
||||
const fighter = k.get(side === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const fighter = k.get(side === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
if (!fighter?.exists()) return
|
||||
|
||||
const mouthColor = side === 'a' ? '#00f0ff' : '#ff2d7b'
|
||||
@@ -7510,7 +7513,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
async function humanJumpsIn(side: 'a' | 'b') {
|
||||
const fighterTag = side === 'a' ? 'fighterA' : 'fighterB'
|
||||
const spriteId = side === 'a' ? 'humanA' : 'humanB'
|
||||
const fighter = k.get(fighterTag)[0]
|
||||
const fighter = k.get(fighterTag)[0] as Fighter
|
||||
if (!fighter) return
|
||||
|
||||
// Spawn human at fighter position
|
||||
@@ -8628,8 +8631,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
},
|
||||
|
||||
async playEntrance() {
|
||||
const fA = k.get('fighterA')[0]
|
||||
const fB = k.get('fighterB')[0]
|
||||
const fA = k.get('fighterA')[0] as Fighter
|
||||
const fB = k.get('fighterB')[0] as Fighter
|
||||
if (!fA || !fB) return
|
||||
|
||||
const entrances = [
|
||||
@@ -9170,8 +9173,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// Helper: reset both fighters to home positions
|
||||
async _resetPositions() {
|
||||
const fA = k.get('fighterA')[0]
|
||||
const fB = k.get('fighterB')[0]
|
||||
const fA = k.get('fighterA')[0] as Fighter
|
||||
const fB = k.get('fighterB')[0] as Fighter
|
||||
if (!fA || !fB) return
|
||||
await Promise.all([
|
||||
k.tween(fA.pos.x, HOME_A, 0.2, (v) => { fA.pos.x = v }, k.easings.easeOutQuad),
|
||||
@@ -9185,8 +9188,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// 0: RAPID BRAWL — close distance, trade rapid blows
|
||||
async _brawlRapid(winningSide: 'a' | 'b' | null, intensity: number) {
|
||||
const fA = k.get('fighterA')[0]
|
||||
const fB = k.get('fighterB')[0]
|
||||
const fA = k.get('fighterA')[0] as Fighter
|
||||
const fB = k.get('fighterB')[0] as Fighter
|
||||
if (!fA || !fB) return
|
||||
const midX = W / 2
|
||||
sfxZoomWhoosh()
|
||||
@@ -9211,8 +9214,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// 1: KNOCKDOWN BRAWL — combo ends with loser knocked flat, has to get back up
|
||||
async _brawlKnockdown(winningSide: 'a' | 'b' | null, intensity: number) {
|
||||
const fA = k.get('fighterA')[0]
|
||||
const fB = k.get('fighterB')[0]
|
||||
const fA = k.get('fighterA')[0] as Fighter
|
||||
const fB = k.get('fighterB')[0] as Fighter
|
||||
if (!fA || !fB) return
|
||||
const winner = winningSide === 'a' ? fA : winningSide === 'b' ? fB : (Math.random() > 0.5 ? fA : fB)
|
||||
const loser = winner === fA ? fB : fA
|
||||
@@ -9261,8 +9264,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// 2: WALL BOUNCE — punch sends fighter flying into screen edge, bounces off
|
||||
async _brawlWallBounce(winningSide: 'a' | 'b' | null, intensity: number) {
|
||||
const fA = k.get('fighterA')[0]
|
||||
const fB = k.get('fighterB')[0]
|
||||
const fA = k.get('fighterA')[0] as Fighter
|
||||
const fB = k.get('fighterB')[0] as Fighter
|
||||
if (!fA || !fB) return
|
||||
const winner = winningSide === 'a' ? fA : winningSide === 'b' ? fB : (Math.random() > 0.5 ? fA : fB)
|
||||
const loser = winner === fA ? fB : fA
|
||||
@@ -9320,8 +9323,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// 3: DIZZY STAGGER — sustained combo leaves loser wobbling around the screen
|
||||
async _brawlDizzyStagger(winningSide: 'a' | 'b' | null, intensity: number) {
|
||||
const fA = k.get('fighterA')[0]
|
||||
const fB = k.get('fighterB')[0]
|
||||
const fA = k.get('fighterA')[0] as Fighter
|
||||
const fB = k.get('fighterB')[0] as Fighter
|
||||
if (!fA || !fB) return
|
||||
const winner = winningSide === 'a' ? fA : winningSide === 'b' ? fB : (Math.random() > 0.5 ? fA : fB)
|
||||
const loser = winner === fA ? fB : fA
|
||||
@@ -9372,8 +9375,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// 4: SUPLEX SLAM — grab, lift overhead, slam to ground with bounce
|
||||
async _brawlSuplex(attackerSide: 'a' | 'b', intensity: number) {
|
||||
const attacker = k.get(attackerSide === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const defender = k.get(attackerSide === 'a' ? 'fighterB' : 'fighterA')[0]
|
||||
const attacker = k.get(attackerSide === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
const defender = k.get(attackerSide === 'a' ? 'fighterB' : 'fighterA')[0] as Fighter
|
||||
if (!attacker || !defender) return
|
||||
const dir = attackerSide === 'a' ? 1 : -1
|
||||
|
||||
@@ -9423,8 +9426,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// 5: PING PONG VOLLEY — fighters knock each other back and forth across the screen
|
||||
async _brawlPingPong(winningSide: 'a' | 'b' | null, intensity: number) {
|
||||
const fA = k.get('fighterA')[0]
|
||||
const fB = k.get('fighterB')[0]
|
||||
const fA = k.get('fighterA')[0] as Fighter
|
||||
const fB = k.get('fighterB')[0] as Fighter
|
||||
if (!fA || !fB) return
|
||||
const volleys = 3 + Math.floor(intensity * 3) + Math.floor(Math.random() * 2) // 3-8
|
||||
|
||||
@@ -9471,8 +9474,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// 6: GROUND AND POUND — attacker pins defender, hits them on the ground
|
||||
async _brawlGroundPound(attackerSide: 'a' | 'b', intensity: number) {
|
||||
const attacker = k.get(attackerSide === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const defender = k.get(attackerSide === 'a' ? 'fighterB' : 'fighterA')[0]
|
||||
const attacker = k.get(attackerSide === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
const defender = k.get(attackerSide === 'a' ? 'fighterB' : 'fighterA')[0] as Fighter
|
||||
if (!attacker || !defender) return
|
||||
const dir = attackerSide === 'a' ? 1 : -1
|
||||
|
||||
@@ -9515,8 +9518,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// 7: HAYMAKER — slow dramatic wind-up, pause, devastating single hit with knockdown
|
||||
async _brawlHaymaker(attackerSide: 'a' | 'b', _intensity: number) {
|
||||
const attacker = k.get(attackerSide === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const defender = k.get(attackerSide === 'a' ? 'fighterB' : 'fighterA')[0]
|
||||
const attacker = k.get(attackerSide === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
const defender = k.get(attackerSide === 'a' ? 'fighterB' : 'fighterA')[0] as Fighter
|
||||
if (!attacker || !defender) return
|
||||
const dir = attackerSide === 'a' ? 1 : -1
|
||||
|
||||
@@ -9563,8 +9566,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// 8: BODY CHECK BOUNCER — both charge, collide, one bounces off the other
|
||||
async _brawlBodyCheck(winningSide: 'a' | 'b' | null, _intensity: number) {
|
||||
const fA = k.get('fighterA')[0]
|
||||
const fB = k.get('fighterB')[0]
|
||||
const fA = k.get('fighterA')[0] as Fighter
|
||||
const fB = k.get('fighterB')[0] as Fighter
|
||||
if (!fA || !fB) return
|
||||
const winner = winningSide === 'a' ? fA : winningSide === 'b' ? fB : (Math.random() > 0.5 ? fA : fB)
|
||||
const loser = winner === fA ? fB : fA
|
||||
@@ -9625,8 +9628,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// Clinch combo: grapple at close range, one fighter dominates with sustained contact
|
||||
async _clinchCombo(attackerSide: 'a' | 'b', intensity: number) {
|
||||
const attacker = k.get(attackerSide === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const defender = k.get(attackerSide === 'a' ? 'fighterB' : 'fighterA')[0]
|
||||
const attacker = k.get(attackerSide === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
const defender = k.get(attackerSide === 'a' ? 'fighterB' : 'fighterA')[0] as Fighter
|
||||
if (!attacker || !defender) return
|
||||
const dir = attackerSide === 'a' ? 1 : -1
|
||||
const origAX = attackerSide === 'a' ? HOME_A : HOME_B
|
||||
@@ -9664,8 +9667,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// Counter-attack: after a choreography hit, the defender retaliates briefly
|
||||
async _counterAttack(defenderSide: 'a' | 'b') {
|
||||
const defender = k.get(defenderSide === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const attacker = k.get(defenderSide === 'a' ? 'fighterB' : 'fighterA')[0]
|
||||
const defender = k.get(defenderSide === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
const attacker = k.get(defenderSide === 'a' ? 'fighterB' : 'fighterA')[0] as Fighter
|
||||
if (!defender || !attacker) return
|
||||
const dir = defenderSide === 'a' ? 1 : -1
|
||||
const origDX = defenderSide === 'a' ? HOME_A : HOME_B
|
||||
@@ -9683,8 +9686,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
},
|
||||
|
||||
async playAttack(side: 'a' | 'b', choreographyName: string, isCritical: boolean) {
|
||||
const attacker = k.get(side === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const defender = k.get(side === 'a' ? 'fighterB' : 'fighterA')[0]
|
||||
const attacker = k.get(side === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
const defender = k.get(side === 'a' ? 'fighterB' : 'fighterA')[0] as Fighter
|
||||
if (!attacker || !defender) return
|
||||
|
||||
const origAX = side === 'a' ? HOME_A : HOME_B
|
||||
@@ -9705,8 +9708,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
},
|
||||
|
||||
async playRound(event: RoundEvent) {
|
||||
const fA = k.get('fighterA')[0]
|
||||
const fB = k.get('fighterB')[0]
|
||||
const fA = k.get('fighterA')[0] as Fighter
|
||||
const fB = k.get('fighterB')[0] as Fighter
|
||||
if (!fA || !fB) { await k.wait(0.5); return } // Sprites missing (mobile load failure) — skip animation
|
||||
|
||||
const aWon = event.winnerId === event.botAId
|
||||
@@ -9932,7 +9935,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
: (isUltimate || (exchangeCritical && intensity > 0.7 && Math.random() < 0.4))
|
||||
let morphRevert: (() => Promise<void>) | null = null
|
||||
if (shouldMorph) {
|
||||
const attacker = k.get(attackerSide === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const attacker = k.get(attackerSide === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
if (attacker) {
|
||||
if (isCreatorFighter) {
|
||||
// Omni-morph: creator transforms into a random archetype (sprite swap)
|
||||
@@ -10010,7 +10013,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
}
|
||||
// RGB glitch + hyperspeed lines on critical final blow
|
||||
glitchRGB(0.3)
|
||||
const defPos = k.get(attackerSide === 'a' ? 'fighterB' : 'fighterA')[0]
|
||||
const defPos = k.get(attackerSide === 'a' ? 'fighterB' : 'fighterA')[0] as Fighter
|
||||
if (defPos) hyperSpeedLines(defPos.pos.x, defPos.pos.y - 30, 0.4)
|
||||
}
|
||||
|
||||
@@ -10246,8 +10249,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
|
||||
// Respect nod between fighters on close rounds (10% when margin <= 1)
|
||||
if (margin <= 1 && Math.random() < 0.1) {
|
||||
const fA2 = k.get('fighterA')[0]
|
||||
const fB2 = k.get('fighterB')[0]
|
||||
const fA2 = k.get('fighterA')[0] as Fighter
|
||||
const fB2 = k.get('fighterB')[0] as Fighter
|
||||
if (fA2 && fB2) {
|
||||
spawnEmoteText(fA2.pos.x, fA2.pos.y - 45, respectLines[Math.floor(Math.random() * respectLines.length)], '#88ccff')
|
||||
await k.wait(0.3)
|
||||
@@ -10265,7 +10268,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
},
|
||||
|
||||
async playTaunt(side: 'a' | 'b') {
|
||||
const taunter = k.get(side === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const taunter = k.get(side === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
if (!taunter) return
|
||||
// Creator taunts come with menacing voice lines
|
||||
const taunterArch = side === 'a' ? botA.archetype : botB.archetype
|
||||
@@ -10307,7 +10310,7 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
},
|
||||
|
||||
async playDodge(side: 'a' | 'b') {
|
||||
const dodger = k.get(side === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const dodger = k.get(side === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
if (!dodger) return
|
||||
const origX = side === 'a' ? HOME_A : HOME_B
|
||||
const origY = dodger.pos.y
|
||||
@@ -10324,8 +10327,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
},
|
||||
|
||||
async playKO(winningSide: 'a' | 'b', winnerName: string) {
|
||||
const loser = k.get(winningSide === 'a' ? 'fighterB' : 'fighterA')[0]
|
||||
const winner = k.get(winningSide === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const loser = k.get(winningSide === 'a' ? 'fighterB' : 'fighterA')[0] as Fighter
|
||||
const winner = k.get(winningSide === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
if (!loser || !winner) return
|
||||
|
||||
const dir = winningSide === 'a' ? 1 : -1
|
||||
@@ -11183,8 +11186,8 @@ export async function createFightScene(config: FightSceneConfig) {
|
||||
},
|
||||
|
||||
async playPerfect(winningSide: 'a' | 'b', winnerName: string) {
|
||||
const winner = k.get(winningSide === 'a' ? 'fighterA' : 'fighterB')[0]
|
||||
const loser = k.get(winningSide === 'a' ? 'fighterB' : 'fighterA')[0]
|
||||
const winner = k.get(winningSide === 'a' ? 'fighterA' : 'fighterB')[0] as Fighter
|
||||
const loser = k.get(winningSide === 'a' ? 'fighterB' : 'fighterA')[0] as Fighter
|
||||
if (!loser || !winner) return
|
||||
|
||||
// Judge goes wild for a perfect
|
||||
|
||||
Reference in New Issue
Block a user