*/ private array $pendingNova = []; public function __construct( float $x, float $y, EntityList $container, Room $room, ?Player $initialTarget, array $config = [], ?callable $onDeath = null, ) { $spawnCount = $config['spawnCount'] ?? 3; $spawnOnDeath = $config['spawnOnDeath'] ?? null; parent::__construct($x, $y, $container, $room, $initialTarget, $config, $onDeath ?? function (Zombie $mega) use ($spawnCount, $spawnOnDeath): void { if ($spawnOnDeath === null) { return; } for ($i = 0; $i < $spawnCount; $i++) { $angle = ($i / $spawnCount) * M_PI * 2.0; $offset = $mega->size + 30.0; $spawnOnDeath( $mega->pos->x + cos($angle) * $offset, $mega->pos->y + sin($angle) * $offset, $mega->container, $mega->room, $mega->target, ); } }); if ($initialTarget !== null) { $this->target = $initialTarget; } $this->novaInterval = $config['novaInterval'] ?? 5.0; $this->novaCount = $config['novaCount'] ?? 16; $this->novaProjectileSpeed = $config['novaProjectileSpeed'] ?? 250.0; $this->novaTimer = $this->novaInterval * 0.5; $this->novaRotation = $config['novaRotation'] ?? $this->rand01() * M_PI * 2.0; } public function kind(): string { return 'megawitch'; } public function update(float $dt): void { parent::update($dt); $target = $this->target; if ($target !== null && $target->dead) { return; } foreach (array_keys($this->pendingNova) as $i) { $this->pendingNova[$i][0] -= $dt; if ($this->pendingNova[$i][0] <= 0.0) { $closure = $this->pendingNova[$i][1]; unset($this->pendingNova[$i]); $closure(); } } $this->novaTimer -= $dt; if ($this->novaTimer <= 0.0) { $this->novaTimer = $this->novaInterval * (0.85 + $this->rand01() * 0.3); $this->nova(); } } private function nova(): void { $lost = 1.0 - max(0.0, $this->health / max(1, $this->maxHealth)); $count = max(6, (int) round($this->novaCount * (0.75 + 0.25 * $lost))); $speed = $this->novaProjectileSpeed * (1.0 + $lost * 0.45); $size = max(8.0, $this->size * 0.3); $color = [1.0, 0.5, 0.3, 1.0]; $this->novaRotation += 0.36; $fireRing = function (float $offset) use ($count, $speed, $size, $color): void { for ($i = 0; $i < $count; $i++) { $angle = ($i / $count) * M_PI * 2.0 + $this->novaRotation + $offset; $direction = new Vector2(cos($angle), sin($angle)); $this->container->append(new WitchProjectile( $this->pos->x, $this->pos->y, $direction, $this->container, $this->room, $speed, $size, $color, )); } }; $fireRing(0.0); $this->pendingNova[] = [0.22, function () use ($fireRing, $count): void { $fireRing(M_PI / $count); }]; if ($lost > 0.34) { $this->pendingNova[] = [0.44, function () use ($fireRing): void { $fireRing(0.0); }]; } } public function toSnapshot(): array { $data = parent::toSnapshot(); $data['charge'] = 1.0 - max(0.0, $this->novaTimer) / $this->novaInterval; if ($data['hp'] < $data['mhp'] && $data['charge'] > 0.72) { $data['nova'] = true; } return $data; } }