import { Anim, Character, type CharacterContext } from './Character'; import { aimDir } from './Mamie'; /** * Léon le Caméléon. * - Attack: shoots his long sticky tongue toward the aim. It licks a groove through the cake, * and whatever it catches at the tip is pulled back to him: players (who drop the cherry), * items, falling chunks. * - Special: blends in and turns invisible for the other players for a while (press again to * show up early). * - Flaw: attacking or being hit shows him at once, and a cherry he holds floats in plain sight. */ export class Leon extends Character { private tongueTimer = 0; private hidden = 0; onAttack(ctx: CharacterContext): void { const p = this.stats.params; this.reveal(ctx); const [dx, dy] = aimDir(ctx); // The groove licked through the cake on the way. for (let d = this.size; d <= this.size + p.tongueReach; d += p.tongueStep) { ctx.emitOp({ kind: 'carve', x: Math.round(ctx.x + dx * d), y: Math.round(ctx.y + dy * d), r: Math.round(p.tongueCarve), power: Math.round(p.tonguePower) }); } // Caught at the tip: stuck, then pulled back to him. const tx = ctx.x + dx * (this.size + p.tongueReach); const ty = ctx.y + dy * (this.size + p.tongueReach); ctx.hit(tx, ty, p.tongueRadius, 0, p.tongueStun); ctx.shove(tx, ty, p.tongueRadius, -dx * p.tonguePull, -dy * p.tonguePull - p.tongueLift, 1); ctx.cue('tongue'); this.tongueTimer = p.tongueAnim; } onSpecial(ctx: CharacterContext): void { if (this.hidden > 0) { this.reveal(ctx); return; } this.hidden = this.stats.params.invisibleTime; ctx.cue('vanish'); } override onHit(ctx: CharacterContext): void { this.reveal(ctx); } override onTick(ctx: CharacterContext, dt: number): void { this.tongueTimer = Math.max(0, this.tongueTimer - dt); if (this.hidden <= 0) return; this.hidden -= dt; if (this.hidden <= 0) this.reveal(ctx); } override anim(): number { return (this.tongueTimer > 0 ? Anim.Attack : 0) | (this.hidden > 0 ? Anim.Invisible : 0); } private reveal(ctx: CharacterContext): void { if (this.hidden === 0) return; this.hidden = 0; ctx.cue('appear'); } }