505 lines
14 KiB
JavaScript
505 lines
14 KiB
JavaScript
/**
|
|
* BOSS BATTLES SYSTEM
|
|
* Multi-phase boss fights with unique mechanics and legendary loot
|
|
*/
|
|
class BossBattlesSystem {
|
|
constructor(scene) {
|
|
this.scene = scene;
|
|
this.enabled = true;
|
|
|
|
// Active boss fight
|
|
this.currentBoss = null;
|
|
this.bossPhase = 1;
|
|
|
|
// Boss definitions
|
|
this.bossTypes = new Map();
|
|
|
|
// Boss arenas
|
|
this.arenas = new Map();
|
|
|
|
// Defeated bosses
|
|
this.defeatedBosses = new Set();
|
|
|
|
// Respawn timers
|
|
this.respawnTimers = new Map();
|
|
|
|
this.loadProgress();
|
|
this.init();
|
|
|
|
console.log('✅ Boss Battles System initialized');
|
|
}
|
|
|
|
init() {
|
|
this.defineBosses();
|
|
this.defineArenas();
|
|
console.log('👹 Boss battles ready');
|
|
}
|
|
|
|
// ========== BOSS DEFINITIONS ==========
|
|
|
|
defineBosses() {
|
|
// Mutant King - Early game boss
|
|
this.defineBoss('mutant_king', {
|
|
name: 'Mutant King',
|
|
level: 10,
|
|
phases: [
|
|
{
|
|
hp: 1000,
|
|
attacks: ['slash', 'charge'],
|
|
attackSpeed: 2.0,
|
|
moveSpeed: 1.0
|
|
},
|
|
{
|
|
hp: 500,
|
|
attacks: ['slash', 'charge', 'summon_minions'],
|
|
attackSpeed: 2.5,
|
|
moveSpeed: 1.2
|
|
},
|
|
{
|
|
hp: 250,
|
|
attacks: ['berserk', 'aoe_slam'],
|
|
attackSpeed: 3.0,
|
|
moveSpeed: 1.5
|
|
}
|
|
],
|
|
loot: [
|
|
{ item: 'mutant_crown', chance: 1.0 },
|
|
{ item: 'legendary_sword', chance: 0.2 },
|
|
{ item: 'gold', amount: 500, chance: 1.0 }
|
|
],
|
|
respawnTime: 604800000, // 7 days
|
|
arena: 'mutant_throne'
|
|
});
|
|
|
|
// Zombie Horde Leader
|
|
this.defineBoss('zombie_leader', {
|
|
name: 'Zombie Horde Leader',
|
|
level: 20,
|
|
phases: [
|
|
{
|
|
hp: 2000,
|
|
attacks: ['bite', 'claw_swipe'],
|
|
attackSpeed: 1.5,
|
|
moveSpeed: 0.8,
|
|
summons: 'zombie_minions'
|
|
},
|
|
{
|
|
hp: 1000,
|
|
attacks: ['bite', 'claw_swipe', 'plague_cloud'],
|
|
attackSpeed: 2.0,
|
|
moveSpeed: 1.0,
|
|
summons: 'zombie_minions'
|
|
},
|
|
{
|
|
hp: 500,
|
|
attacks: ['enrage', 'death_grip', 'plague_explosion'],
|
|
attackSpeed: 2.5,
|
|
moveSpeed: 1.2
|
|
}
|
|
],
|
|
loot: [
|
|
{ item: 'zombie_heart', chance: 1.0 },
|
|
{ item: 'necromancer_staff', chance: 0.15 },
|
|
{ item: 'gold', amount: 1000, chance: 1.0 }
|
|
],
|
|
respawnTime: 604800000,
|
|
arena: 'graveyard'
|
|
});
|
|
|
|
// Ancient Tree
|
|
this.defineBoss('ancient_tree', {
|
|
name: 'Ancient Tree',
|
|
level: 30,
|
|
phases: [
|
|
{
|
|
hp: 3000,
|
|
attacks: ['root_strike', 'thorn_volley'],
|
|
attackSpeed: 1.0,
|
|
moveSpeed: 0.5,
|
|
healing: true
|
|
},
|
|
{
|
|
hp: 1500,
|
|
attacks: ['root_strike', 'thorn_volley', 'vine_whip'],
|
|
attackSpeed: 1.5,
|
|
moveSpeed: 0.7,
|
|
summons: 'tree_spirits'
|
|
},
|
|
{
|
|
hp: 750,
|
|
attacks: ['nature_fury', 'poison_spores', 'earthquake'],
|
|
attackSpeed: 2.0,
|
|
moveSpeed: 0.8
|
|
}
|
|
],
|
|
loot: [
|
|
{ item: 'ancient_wood', chance: 1.0 },
|
|
{ item: 'nature_staff', chance: 0.1 },
|
|
{ item: 'life_essence', chance: 0.5 }
|
|
],
|
|
respawnTime: 604800000,
|
|
arena: 'sacred_grove'
|
|
});
|
|
|
|
// Ice Titan
|
|
this.defineBoss('ice_titan', {
|
|
name: 'Ice Titan',
|
|
level: 40,
|
|
phases: [
|
|
{
|
|
hp: 4000,
|
|
attacks: ['ice_punch', 'frost_breath'],
|
|
attackSpeed: 1.2,
|
|
moveSpeed: 0.6
|
|
},
|
|
{
|
|
hp: 2000,
|
|
attacks: ['ice_punch', 'frost_breath', 'blizzard'],
|
|
attackSpeed: 1.5,
|
|
moveSpeed: 0.8,
|
|
aura: 'freezing_aura'
|
|
},
|
|
{
|
|
hp: 1000,
|
|
attacks: ['avalanche', 'ice_prison', 'absolute_zero'],
|
|
attackSpeed: 2.0,
|
|
moveSpeed: 1.0
|
|
}
|
|
],
|
|
loot: [
|
|
{ item: 'ice_core', chance: 1.0 },
|
|
{ item: 'frost_hammer', chance: 0.08 },
|
|
{ item: 'eternal_ice', chance: 0.3 }
|
|
],
|
|
respawnTime: 604800000,
|
|
arena: 'frozen_peak'
|
|
});
|
|
|
|
// Fire Dragon - Final boss
|
|
this.defineBoss('fire_dragon', {
|
|
name: 'Fire Dragon',
|
|
level: 50,
|
|
phases: [
|
|
{
|
|
hp: 5000,
|
|
attacks: ['claw_slash', 'tail_swipe', 'fire_breath'],
|
|
attackSpeed: 1.5,
|
|
moveSpeed: 1.0,
|
|
flying: true
|
|
},
|
|
{
|
|
hp: 2500,
|
|
attacks: ['claw_slash', 'fire_breath', 'meteor_strike'],
|
|
attackSpeed: 2.0,
|
|
moveSpeed: 1.2,
|
|
flying: true,
|
|
aura: 'burning_aura'
|
|
},
|
|
{
|
|
hp: 1250,
|
|
attacks: ['inferno', 'dragon_rage', 'apocalypse'],
|
|
attackSpeed: 2.5,
|
|
moveSpeed: 1.5,
|
|
invulnerable_periods: true
|
|
}
|
|
],
|
|
loot: [
|
|
{ item: 'dragon_heart', chance: 1.0 },
|
|
{ item: 'dragon_scale_armor', chance: 0.05 },
|
|
{ item: 'legendary_gem', chance: 0.2 },
|
|
{ item: 'gold', amount: 5000, chance: 1.0 }
|
|
],
|
|
respawnTime: 1209600000, // 14 days
|
|
arena: 'volcano_peak'
|
|
});
|
|
}
|
|
|
|
defineBoss(id, data) {
|
|
this.bossTypes.set(id, {
|
|
id,
|
|
totalHp: data.phases.reduce((sum, p) => sum + p.hp, 0),
|
|
...data
|
|
});
|
|
}
|
|
|
|
// ========== ARENAS ==========
|
|
|
|
defineArenas() {
|
|
this.arenas.set('mutant_throne', {
|
|
name: 'Mutant Throne Room',
|
|
x: 50, y: 50,
|
|
width: 30, height: 30,
|
|
hazards: ['spike_traps']
|
|
});
|
|
|
|
this.arenas.set('graveyard', {
|
|
name: 'Cursed Graveyard',
|
|
x: 80, y: 80,
|
|
width: 40, height: 40,
|
|
hazards: ['poison_pools', 'zombie_spawners']
|
|
});
|
|
|
|
this.arenas.set('sacred_grove', {
|
|
name: 'Sacred Grove',
|
|
x: 120, y: 120,
|
|
width: 50, height: 50,
|
|
hazards: ['thorns', 'healing_pools']
|
|
});
|
|
|
|
this.arenas.set('frozen_peak', {
|
|
name: 'Frozen Peak',
|
|
x: 150, y: 150,
|
|
width: 50, height: 50,
|
|
hazards: ['ice_patches', 'avalanche_zones']
|
|
});
|
|
|
|
this.arenas.set('volcano_peak', {
|
|
name: 'Volcano Peak',
|
|
x: 200, y: 200,
|
|
width: 60, height: 60,
|
|
hazards: ['lava_pools', 'falling_rocks']
|
|
});
|
|
}
|
|
|
|
// ========== BOSS FIGHT ==========
|
|
|
|
startBossFight(bossId) {
|
|
const bossData = this.bossTypes.get(bossId);
|
|
if (!bossData) {
|
|
console.log('❌ Boss not found');
|
|
return false;
|
|
}
|
|
|
|
// Check if boss is on cooldown
|
|
if (this.isOnCooldown(bossId)) {
|
|
const timeLeft = this.getRespawnTimeLeft(bossId);
|
|
console.log(`❌ Boss respawns in ${Math.floor(timeLeft / 3600000)} hours`);
|
|
return false;
|
|
}
|
|
|
|
// Create boss instance
|
|
this.currentBoss = {
|
|
id: bossId,
|
|
name: bossData.name,
|
|
level: bossData.level,
|
|
currentPhase: 1,
|
|
hp: bossData.phases[0].hp,
|
|
maxHp: bossData.totalHp,
|
|
phases: bossData.phases,
|
|
loot: bossData.loot,
|
|
defeated: false,
|
|
startTime: Date.now()
|
|
};
|
|
|
|
this.bossPhase = 1;
|
|
|
|
// Visual effect
|
|
if (this.scene.visualEnhancements) {
|
|
this.scene.visualEnhancements.screenFlash(0xff0000, 1000);
|
|
}
|
|
|
|
console.log(`👹 Boss fight started: ${bossData.name}!`);
|
|
return true;
|
|
}
|
|
|
|
// ========== PHASE TRANSITIONS ==========
|
|
|
|
updateBossFight(delta) {
|
|
if (!this.currentBoss || this.currentBoss.defeated) return;
|
|
|
|
// Check for phase transition
|
|
const currentPhaseData = this.currentBoss.phases[this.bossPhase - 1];
|
|
|
|
if (this.currentBoss.hp <= 0 && this.bossPhase < this.currentBoss.phases.length) {
|
|
this.transitionPhase();
|
|
} else if (this.currentBoss.hp <= 0) {
|
|
this.defeatBoss();
|
|
}
|
|
}
|
|
|
|
transitionPhase() {
|
|
this.bossPhase++;
|
|
const newPhase = this.currentBoss.phases[this.bossPhase - 1];
|
|
|
|
this.currentBoss.hp = newPhase.hp;
|
|
this.currentBoss.currentPhase = this.bossPhase;
|
|
|
|
// Visual effect
|
|
if (this.scene.visualEnhancements) {
|
|
this.scene.visualEnhancements.screenFlash(0xff00ff, 500);
|
|
const player = this.scene.player;
|
|
if (player) {
|
|
const pos = player.getPosition();
|
|
this.scene.visualEnhancements.createExplosionEffect(pos.x, pos.y);
|
|
}
|
|
}
|
|
|
|
console.log(`⚡ Boss entered Phase ${this.bossPhase}!`);
|
|
}
|
|
|
|
// ========== BOSS DEFEAT ==========
|
|
|
|
defeatBoss() {
|
|
this.currentBoss.defeated = true;
|
|
|
|
// Grant loot
|
|
this.grantBossLoot();
|
|
|
|
// Mark as defeated
|
|
this.defeatedBosses.add(this.currentBoss.id);
|
|
|
|
// Start respawn timer
|
|
const bossData = this.bossTypes.get(this.currentBoss.id);
|
|
this.respawnTimers.set(this.currentBoss.id, {
|
|
defeatedTime: Date.now(),
|
|
respawnTime: bossData.respawnTime
|
|
});
|
|
|
|
// Visual effect
|
|
if (this.scene.visualEnhancements) {
|
|
this.scene.visualEnhancements.screenFlash(0xffd700, 1000);
|
|
}
|
|
|
|
// Achievement
|
|
if (this.scene.uiGraphics) {
|
|
if (this.currentBoss.id === 'fire_dragon') {
|
|
this.scene.uiGraphics.unlockAchievement('dragon_slayer');
|
|
}
|
|
if (this.defeatedBosses.size >= 5) {
|
|
this.scene.uiGraphics.unlockAchievement('boss_master');
|
|
}
|
|
}
|
|
|
|
console.log(`🏆 Defeated ${this.currentBoss.name}!`);
|
|
this.saveProgress();
|
|
}
|
|
|
|
grantBossLoot() {
|
|
const loot = this.currentBoss.loot;
|
|
|
|
for (const lootItem of loot) {
|
|
const roll = Math.random();
|
|
if (roll <= lootItem.chance) {
|
|
const amount = lootItem.amount || 1;
|
|
|
|
if (this.scene.inventorySystem) {
|
|
this.scene.inventorySystem.addItem(lootItem.item, amount);
|
|
}
|
|
|
|
console.log(`💎 Received: ${lootItem.item} x${amount}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ========== RESPAWN SYSTEM ==========
|
|
|
|
isOnCooldown(bossId) {
|
|
const timer = this.respawnTimers.get(bossId);
|
|
if (!timer) return false;
|
|
|
|
const elapsed = Date.now() - timer.defeatedTime;
|
|
return elapsed < timer.respawnTime;
|
|
}
|
|
|
|
getRespawnTimeLeft(bossId) {
|
|
const timer = this.respawnTimers.get(bossId);
|
|
if (!timer) return 0;
|
|
|
|
const elapsed = Date.now() - timer.defeatedTime;
|
|
return Math.max(0, timer.respawnTime - elapsed);
|
|
}
|
|
|
|
// ========== BOSS ATTACKS ==========
|
|
|
|
executeBossAttack(attackName) {
|
|
console.log(`💥 Boss used ${attackName}!`);
|
|
|
|
switch (attackName) {
|
|
case 'summon_minions':
|
|
this.summonMinions();
|
|
break;
|
|
case 'aoe_slam':
|
|
this.aoeSlam();
|
|
break;
|
|
case 'plague_cloud':
|
|
this.plagueCloud();
|
|
break;
|
|
case 'meteor_strike':
|
|
this.meteorStrike();
|
|
break;
|
|
case 'apocalypse':
|
|
this.apocalypse();
|
|
break;
|
|
}
|
|
}
|
|
|
|
summonMinions() {
|
|
console.log('👥 Boss summoned minions!');
|
|
}
|
|
|
|
aoeSlam() {
|
|
console.log('💥 Boss used AOE slam!');
|
|
}
|
|
|
|
plagueCloud() {
|
|
console.log('☠️ Boss released plague cloud!');
|
|
}
|
|
|
|
meteorStrike() {
|
|
console.log('☄️ Meteors falling!');
|
|
}
|
|
|
|
apocalypse() {
|
|
console.log('🔥 APOCALYPSE!');
|
|
}
|
|
|
|
// ========== UPDATE ==========
|
|
|
|
update(delta) {
|
|
this.updateBossFight(delta);
|
|
}
|
|
|
|
// ========== PERSISTENCE ==========
|
|
|
|
saveProgress() {
|
|
const data = {
|
|
defeatedBosses: Array.from(this.defeatedBosses),
|
|
respawnTimers: Array.from(this.respawnTimers.entries()).map(([id, timer]) => ({
|
|
id,
|
|
defeatedTime: timer.defeatedTime,
|
|
respawnTime: timer.respawnTime
|
|
}))
|
|
};
|
|
|
|
localStorage.setItem('novafarma_bosses', JSON.stringify(data));
|
|
}
|
|
|
|
loadProgress() {
|
|
const saved = localStorage.getItem('novafarma_bosses');
|
|
if (saved) {
|
|
try {
|
|
const data = JSON.parse(saved);
|
|
this.defeatedBosses = new Set(data.defeatedBosses || []);
|
|
|
|
if (data.respawnTimers) {
|
|
data.respawnTimers.forEach(timer => {
|
|
this.respawnTimers.set(timer.id, {
|
|
defeatedTime: timer.defeatedTime,
|
|
respawnTime: timer.respawnTime
|
|
});
|
|
});
|
|
}
|
|
|
|
console.log('✅ Boss progress loaded');
|
|
} catch (error) {
|
|
console.error('Failed to load boss progress:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
destroy() {
|
|
this.saveProgress();
|
|
console.log('👹 Boss Battles System destroyed');
|
|
}
|
|
}
|