| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- 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');
- }
- }
|