class Boss extends NPC { constructor(scene, gridX, gridY) { super(scene, gridX, gridY, scene.terrainOffsetX, scene.terrainOffsetY, 'boss'); this.maxHp = 500; this.hp = this.maxHp; this.moveSpeed = 70; // Slower than normal zombies // Cooldowns this.summonCooldown = 12000; this.smashCooldown = 6000; this.currentSkillTimer = 0; } createSprite() { super.createSprite(); // Customize appearance this.sprite.setScale(2.0); // Big Boss this.sprite.setTint(0x6600cc); // Dark Purple // Add a crown or something? (Text) this.crown = this.scene.add.text(this.sprite.x, this.sprite.y - 80, '👑', { fontSize: '30px' }); this.crown.setOrigin(0.5); this.crown.setDepth(this.sprite.depth + 100); } update(delta) { super.update(delta); // Update Crown position if (this.crown && this.sprite) { this.crown.setPosition(this.sprite.x, this.sprite.y - 80); this.crown.setDepth(this.sprite.depth + 100); } if (this.state === 'CHASE' || this.state === 'WANDER') { this.handleBossSkills(delta); } } handleBossSkills(delta) { if (!this.scene.player) return; this.currentSkillTimer += delta; const dist = Phaser.Math.Distance.Between(this.gridX, this.gridY, this.scene.player.gridX, this.scene.player.gridY); // Smash Attack (AoE close range) if (this.currentSkillTimer > this.smashCooldown && dist < 4) { this.smashAttack(); this.currentSkillTimer = 0; // Reset timer partially? No, full reset for simpler logic } // Summon Minions (Long range or cooldown) else if (this.currentSkillTimer > this.summonCooldown) { this.summonMinions(); this.currentSkillTimer = 5000; // Give back some time so he doesn't wait full CD for smash } } smashAttack() { console.log('💥 BOSS SMASH!'); this.scene.cameras.main.shake(300, 0.01); // Visual Warning const warning = this.scene.add.circle(this.sprite.x, this.sprite.y, 150, 0xff0000, 0.4); warning.setScale(0); this.scene.tweens.add({ targets: warning, scale: 1, alpha: 0, duration: 500, onComplete: () => { warning.destroy(); // Damage Logic const playerPos = this.scene.player.getPosition(); const d = Phaser.Math.Distance.Between(this.sprite.x, this.sprite.y, playerPos.x, playerPos.y); // Pixel distance if (d < 150) { this.scene.player.takeDamage(30); // Knockback // todo } // Sound if (this.scene.soundManager) this.scene.soundManager.playDeath(); // Placeholder for big boom } }); } summonMinions() { console.log('🧟🧟🧟 BOSS SUMMONS MINIONS!'); for (let i = 0; i < 3; i++) { const angle = (Math.PI * 2 / 3) * i; const dist = 3; const sx = Math.floor(this.gridX + Math.cos(angle) * dist); const sy = Math.floor(this.gridY + Math.sin(angle) * dist); if (this.scene.terrainSystem.getTile(sx, sy)) { // Spawn normal zombie // We access GameScene's spawn method or create NPC directly const zombie = new NPC(this.scene, sx, sy, this.scene.terrainOffsetX, this.scene.terrainOffsetY, 'zombie'); zombie.state = 'CHASE'; this.scene.npcs.push(zombie); // Spawn Effect if (this.scene.particleEffects) { const iso = new IsometricUtils(48, 24); const pos = iso.toScreen(sx, sy); this.scene.particleEffects.bloodSplash(pos.x + 300, pos.y + 100); // hardcoded offset fix maybe needed } } } } destroy() { if (this.crown) this.crown.destroy(); super.destroy(); // Boss Drops if (this.scene.lootSystem) { this.scene.lootSystem.spawnLoot(this.gridX, this.gridY, 'item_gold', 50); this.scene.lootSystem.spawnLoot(this.gridX, this.gridY, 'item_sword', 1); // Rare drop } // Boss Death Event? this.scene.events.emit('boss_killed'); } }