import { Witch } from './Witch.js'; import { WitchProjectile } from './WitchProjectile.js'; import { Vector2D } from '../engine/Vector2D.js'; export class MegaWitch extends Witch { constructor( x, y, target, { container, viewport, speed = 55, size = 52, color = [0.8, 0.15, 0.7, 1], health = 22, knockback = 130, scoreValue = 12, preferredDistance = 240, fireInterval = 2, projectileSpeed = 240, projectileCount = 3, projectileSpread = 0.35, projectileColor = [1, 0.3, 0.3, 1], novaInterval = 5, novaCount = 16, novaProjectileSpeed = 250, spawnProjectile = (p) => {}, spawnOnDeath = () => {}, spawnCount = 3, } = {}, ) { super(x, y, target, { container, viewport, speed, size, color, health, knockback, scoreValue, preferredDistance, fireInterval, projectileSpeed, projectileCount, projectileSpread, projectileColor, spawnProjectile, onDeath: (mega) => { for (let i = 0; i < spawnCount; i += 1) { const angle = (i / spawnCount) * Math.PI * 2; const offset = mega.size + 30; spawnOnDeath( mega.pos.x + Math.cos(angle) * offset, mega.pos.y + Math.sin(angle) * offset, target, container, ); } }, }); this.novaInterval = novaInterval; this.novaCount = novaCount; this.novaProjectileSpeed = novaProjectileSpeed; this._novaTimer = novaInterval * 0.5; this._novaRotation = Math.random() * Math.PI * 2; this._pendingNova = []; } update(dt) { super.update(dt); if (this.target.health <= 0) return; for (let i = this._pendingNova.length - 1; i >= 0; i -= 1) { const entry = this._pendingNova[i]; entry.remaining -= dt; if (entry.remaining <= 0) { this._pendingNova.splice(i, 1); entry.fire(); } } this._novaTimer -= dt; if (this._novaTimer <= 0) { this._novaTimer = this.novaInterval * (0.85 + Math.random() * 0.3); this.nova(); } } nova() { const lost = 1 - Math.max(0, this.health / this.maxHealth); const count = Math.max(6, Math.round(this.novaCount * (0.75 + 0.25 * lost))); const speed = this.novaProjectileSpeed * (1 + lost * 0.45); const size = this.size * 0.3; const color = [1, 0.5, 0.3, 1]; this._novaRotation += 0.36; const fireRing = (offset) => { for (let i = 0; i < count; i += 1) { const angle = (i / count) * Math.PI * 2 + this._novaRotation + offset; const direction = new Vector2D(Math.cos(angle), Math.sin(angle)); const projectile = new WitchProjectile(this.pos.x, this.pos.y, direction, { container: this.container, viewport: this.viewport, speed, size, color, }); this.spawnProjectile(projectile); } }; fireRing(0); this._pendingNova.push({ remaining: 0.22, fire: () => fireRing(Math.PI / count), }); if (lost > 0.34) { this._pendingNova.push({ remaining: 0.44, fire: () => fireRing(0), }); } this._cast = 0.32; } draw(renderer) { const charge = 1 - Math.max(0, this._novaTimer) / this.novaInterval; if (charge > 0.72) { const hp = Math.max(0, this.health / this.maxHealth); const punch = (charge - 0.72) / 0.28; const r = this.size * (0.6 + punch * 1.7) * (1.4 - hp * 0.6); renderer.setBlendMode('additive'); renderer.drawTexture( renderer.glowTexture, this.pos.x - r, this.pos.y - r, r * 2, r * 2, [1, 0.3, 0.15, punch * 0.7], ); renderer.drawTexture( renderer.ringTexture, this.pos.x - r * 1.5, this.pos.y - r * 1.5, r * 3, r * 3, [1, 0.45, 0.2, punch * 0.9], ); renderer.drawTexture( renderer.ringTexture, this.pos.x - r * 2.1, this.pos.y - r * 2.1, r * 4.2, r * 4.2, [1, 0.25, 0.1, punch * 0.35], ); renderer.setBlendMode('normal'); } super.draw(renderer); } }