Game-Server/Client/js/systems/DungeonSystem.js
2026-01-24 16:47:19 -04:00

1978 lines
69 KiB
JavaScript

/**
* Galaxy Strike Online - Dungeon System
* Manages procedural dungeon generation and exploration
*/
class DungeonSystem {
constructor(gameEngine) {
this.game = gameEngine;
// Dungeon configuration
this.dungeonTypes = {
tutorial: {
name: 'Tutorial Dungeon',
description: 'Learn the basics of dungeon exploration in this guided tutorial',
difficulty: 'tutorial',
enemyTypes: ['training_drone', 'practice_target'],
rewardMultiplier: 0.5,
oneTimeOnly: true,
healthType: 'player', // Ground mission
energyCost: 0
},
alien_ruins: {
name: 'Alien Ruins',
description: 'Ancient alien structures filled with mysterious technology',
difficulty: 'medium',
enemyTypes: ['alien_guardian', 'ancient_drone', 'crystal_golem'],
rewardMultiplier: 1.2,
healthType: 'player', // Ground mission
energyCost: 20
},
pirate_lair: {
name: 'Pirate Lair',
description: 'Dangerous pirate hideouts with valuable loot',
difficulty: 'easy',
enemyTypes: ['space_pirate', 'pirate_captain', 'defense_turret'],
rewardMultiplier: 1.0,
healthType: 'ship', // Space mission
energyCost: 15
},
corrupted_vault: {
name: 'Corrupted AI Vault',
description: ' malfunctioning AI facilities with corrupted security',
difficulty: 'hard',
enemyTypes: ['security_drone', 'corrupted_ai', 'virus_program'],
rewardMultiplier: 1.5,
healthType: 'ship', // Space mission
energyCost: 25
},
asteroid_mine: {
name: 'Asteroid Mine',
description: 'Abandoned mining facilities in asteroid fields',
difficulty: 'easy',
enemyTypes: ['mining_drone', 'rock_creature', 'explosive_asteroid'],
rewardMultiplier: 0.8,
healthType: 'ship', // Space mission
energyCost: 10
},
nebula_anomaly: {
name: 'Nebula Anomaly',
description: 'Strange energy anomalies in deep space',
difficulty: 'extreme',
enemyTypes: ['energy_being', 'phase_shifter', 'quantum_entity'],
rewardMultiplier: 2.0,
healthType: 'ship', // Space mission
energyCost: 30
},
// NEW DUNGEONS - Space Theme
space_station: {
name: 'Abandoned Space Station',
description: 'A derelict space station floating in the void',
difficulty: 'medium',
enemyTypes: ['maintenance_drone', 'security_android', 'station_ai'],
rewardMultiplier: 1.3,
healthType: 'player',
energyCost: 22
},
comet_core: {
name: 'Comet Core',
description: 'The frozen heart of a passing comet',
difficulty: 'hard',
enemyTypes: ['ice_elemental', 'frost_wyrm', 'crystal_guardian'],
rewardMultiplier: 1.6,
healthType: 'ship',
energyCost: 28
},
black_hole_perimeter: {
name: 'Black Hole Perimeter',
description: 'Dangerous space near a black hole event horizon',
difficulty: 'extreme',
enemyTypes: ['gravity_wraith', 'void_stalker', 'singularity_spawn'],
rewardMultiplier: 2.5,
healthType: 'ship',
energyCost: 35
},
star_forge: {
name: 'Star Forge',
description: 'Ancient facility that harnesses stellar energy',
difficulty: 'hard',
enemyTypes: ['plasma_elemental', 'solar_guardian', 'fusion_core'],
rewardMultiplier: 1.8,
healthType: 'ship',
energyCost: 30
},
debris_field: {
name: 'Ship Debris Field',
description: 'Graveyard of destroyed spacecraft',
difficulty: 'easy',
enemyTypes: ['scrap_golem', 'hull_breacher', 'salage_drone'],
rewardMultiplier: 0.9,
healthType: 'ship',
energyCost: 12
},
// NEW DUNGEONS - Planet Theme
jungle_temple: {
name: 'Jungle Temple',
description: 'Overgrown temple hidden in dense alien jungle',
difficulty: 'medium',
enemyTypes: ['plant_beast', 'tribal_warrior', 'jungle_spirit'],
rewardMultiplier: 1.4,
healthType: 'player',
energyCost: 25
},
desert_pyramid: {
name: 'Desert Pyramid',
description: 'Ancient pyramid buried under endless sand dunes',
difficulty: 'hard',
enemyTypes: ['sand_worm', 'mummy_guardian', 'heat_elemental'],
rewardMultiplier: 1.7,
healthType: 'player',
energyCost: 28
},
volcanic_caverns: {
name: 'Volcanic Caverns',
description: 'Molten caverns deep within an active volcano',
difficulty: 'hard',
enemyTypes: ['lava_elemental', 'fire_demon', 'magma_beast'],
rewardMultiplier: 1.6,
healthType: 'player',
energyCost: 26
},
arctic_research: {
name: 'Arctic Research Base',
description: 'Frozen research facility with failed experiments',
difficulty: 'medium',
enemyTypes: ['cryo_mutant', 'frost_android', 'ice_wraith'],
rewardMultiplier: 1.5,
healthType: 'player',
energyCost: 24
},
swamp_lair: {
name: 'Swamp Lair',
description: 'Murky swamp inhabited by strange creatures',
difficulty: 'easy',
enemyTypes: ['swamp_beast', 'toxic_spitter', 'mud_golem'],
rewardMultiplier: 1.1,
healthType: 'player',
energyCost: 18
},
// NEW DUNGEONS - Technology Theme
cyber_realm: {
name: 'Cyber Realm',
description: 'Virtual reality space corrupted by malware',
difficulty: 'hard',
enemyTypes: ['glitch_wraith', 'firewall_guardian', 'data_vampire'],
rewardMultiplier: 1.9,
healthType: 'player',
energyCost: 32
},
robot_factory: {
name: 'Robot Factory',
description: 'Automated factory producing hostile machines',
difficulty: 'medium',
enemyTypes: ['assembly_drone', 'welder_bot', 'factory_overseer'],
rewardMultiplier: 1.4,
healthType: 'player',
energyCost: 23
},
quantum_lab: {
name: 'Quantum Laboratory',
description: 'Research facility experimenting with quantum physics',
difficulty: 'extreme',
enemyTypes: ['quantum_phantom', 'particle_accelerator', 'reality_bender'],
rewardMultiplier: 2.3,
healthType: 'player',
energyCost: 38
},
server_farm: {
name: 'Server Farm',
description: 'Massive data center with rogue security programs',
difficulty: 'medium',
enemyTypes: ['sentinel_program', 'data_corruptor', 'system_guardian'],
rewardMultiplier: 1.3,
healthType: 'player',
energyCost: 21
},
// NEW DUNGEONS - Biome/Elemental Theme
crystal_caves: {
name: 'Crystal Caves',
description: 'Caves filled with energy-infused crystals',
difficulty: 'medium',
enemyTypes: ['crystal_golem', 'shard_elemental', 'resonance_beast'],
rewardMultiplier: 1.4,
healthType: 'player',
energyCost: 22
},
toxic_wastes: {
name: 'Toxic Wastes',
description: 'Polluted wasteland filled with mutated creatures',
difficulty: 'hard',
enemyTypes: ['mutant_horror', 'toxic_slime', 'radiation_beast'],
rewardMultiplier: 1.7,
healthType: 'player',
energyCost: 27
},
shadow_realm: {
name: 'Shadow Realm',
description: 'Dark dimension inhabited by shadow creatures',
difficulty: 'extreme',
enemyTypes: ['shadow_demon', 'nightmare_stalker', 'void_walker'],
rewardMultiplier: 2.2,
healthType: 'player',
energyCost: 36
},
time_anomaly: {
name: 'Time Anomaly',
description: 'Area where time flows unpredictably',
difficulty: 'extreme',
enemyTypes: ['temporal_paradox', 'future_soldier', 'past_guardian'],
rewardMultiplier: 2.4,
healthType: 'player',
energyCost: 40
},
// NEW DUNGEONS - Military/War Theme
war_zone: {
name: 'Active War Zone',
description: 'Battlefield with ongoing combat operations',
difficulty: 'hard',
enemyTypes: ['enemy_soldier', 'combat_drone', 'field_commander'],
rewardMultiplier: 1.8,
healthType: 'player',
energyCost: 29
},
military_base: {
name: 'Abandoned Military Base',
description: 'Former military installation with automated defenses',
difficulty: 'medium',
enemyTypes: ['turret_system', 'combat_android', 'base_commander'],
rewardMultiplier: 1.5,
healthType: 'player',
energyCost: 24
},
weapons_testing: {
name: 'Weapons Testing Facility',
description: 'Secret facility testing advanced weaponry',
difficulty: 'hard',
enemyTypes: ['weapon_drone', 'test_subject', 'chief_scientist'],
rewardMultiplier: 1.9,
healthType: 'player',
energyCost: 31
},
// NEW DUNGEONS - Special/Unique Theme
dream_scape: {
name: 'Dream Scape',
description: 'Surreal landscape shaped by collective dreams',
difficulty: 'medium',
enemyTypes: ['nightmare_creature', 'dream_guardian', 'subconscious_demon'],
rewardMultiplier: 1.6,
healthType: 'player',
energyCost: 26
},
memory_palace: {
name: 'Memory Palace',
description: 'Mental realm storing forgotten memories',
difficulty: 'hard',
enemyTypes: ['memory_fragment', 'forgetfulness_demon', 'nostalgia_spirit'],
rewardMultiplier: 1.7,
healthType: 'player',
energyCost: 28
},
dimension_rift: {
name: 'Dimension Rift',
description: 'Tear between dimensions with interdimensional invaders',
difficulty: 'extreme',
enemyTypes: ['rift_demon', 'dimensional_hunter', 'reality_tear'],
rewardMultiplier: 2.6,
healthType: 'player',
energyCost: 42
}
};
// Current dungeon state
this.currentDungeon = null;
this.currentRoom = null;
this.dungeonProgress = 0;
this.isExploring = false;
// Dungeon templates
this.roomTypes = {
entrance: { name: 'Entrance', enemies: 0, rewards: false },
corridor: { name: 'Corridor', enemies: 1, rewards: false },
chamber: { name: 'Chamber', enemies: 2, rewards: true },
treasure: { name: 'Treasure Room', enemies: 0, rewards: true },
boss: { name: 'Boss Room', enemies: 1, rewards: true, isBoss: true },
exit: { name: 'Exit', enemies: 0, rewards: false }
};
// Enemy templates
this.enemyTemplates = {
// Original enemies
training_drone: {
name: 'Training Drone',
health: 10,
attack: 5,
defense: 2,
experience: 5,
credits: 3
},
practice_target: {
name: 'Practice Target',
health: 5,
attack: 0,
defense: 0,
experience: 2,
credits: 1
},
alien_guardian: {
name: 'Alien Guardian',
health: 50,
attack: 8,
defense: 5,
experience: 25,
credits: 15
},
ancient_drone: {
name: 'Ancient Drone',
health: 30,
attack: 12,
defense: 2,
experience: 20,
credits: 10
},
crystal_golem: {
name: 'Crystal Golem',
health: 80,
attack: 6,
defense: 10,
experience: 35,
credits: 25
},
space_pirate: {
name: 'Space Pirate',
health: 25,
attack: 10,
defense: 3,
experience: 15,
credits: 12
},
pirate_captain: {
name: 'Pirate Captain',
health: 40,
attack: 15,
defense: 6,
experience: 30,
credits: 20
},
defense_turret: {
name: 'Defense Turret',
health: 20,
attack: 18,
defense: 8,
experience: 18,
credits: 8
},
security_drone: {
name: 'Security Drone',
health: 35,
attack: 14,
defense: 4,
experience: 22,
credits: 15
},
corrupted_ai: {
name: 'Corrupted AI',
health: 60,
attack: 20,
defense: 2,
experience: 40,
credits: 30
},
virus_program: {
name: 'Virus Program',
health: 15,
attack: 25,
defense: 1,
experience: 20,
credits: 12
},
mining_drone: {
name: 'Mining Drone',
health: 20,
attack: 8,
defense: 3,
experience: 12,
credits: 8
},
rock_creature: {
name: 'Rock Creature',
health: 45,
attack: 6,
defense: 12,
experience: 25,
credits: 15
},
explosive_asteroid: {
name: 'Explosive Asteroid',
health: 10,
attack: 30,
defense: 0,
experience: 15,
credits: 5
},
energy_being: {
name: 'Energy Being',
health: 55,
attack: 22,
defense: 3,
experience: 45,
credits: 35
},
phase_shifter: {
name: 'Phase Shifter',
health: 30,
attack: 28,
defense: 1,
experience: 35,
credits: 25
},
quantum_entity: {
name: 'Quantum Entity',
health: 70,
attack: 35,
defense: 5,
experience: 60,
credits: 50
},
// NEW ENEMIES - Space Theme
maintenance_drone: {
name: 'Maintenance Drone',
health: 28,
attack: 11,
defense: 4,
experience: 18,
credits: 12
},
security_android: {
name: 'Security Android',
health: 42,
attack: 16,
defense: 7,
experience: 28,
credits: 20
},
station_ai: {
name: 'Station AI',
health: 65,
attack: 24,
defense: 3,
experience: 45,
credits: 32
},
ice_elemental: {
name: 'Ice Elemental',
health: 38,
attack: 18,
defense: 8,
experience: 32,
credits: 24
},
frost_wyrm: {
name: 'Frost Wyrm',
health: 72,
attack: 26,
defense: 6,
experience: 52,
credits: 38
},
gravity_wraith: {
name: 'Gravity Wraith',
health: 85,
attack: 32,
defense: 4,
experience: 68,
credits: 48
},
void_stalker: {
name: 'Void Stalker',
health: 78,
attack: 38,
defense: 5,
experience: 72,
credits: 52
},
singularity_spawn: {
name: 'Singularity Spawn',
health: 95,
attack: 42,
defense: 8,
experience: 85,
credits: 65
},
plasma_elemental: {
name: 'Plasma Elemental',
health: 58,
attack: 28,
defense: 4,
experience: 48,
credits: 35
},
solar_guardian: {
name: 'Solar Guardian',
health: 82,
attack: 34,
defense: 7,
experience: 65,
credits: 48
},
fusion_core: {
name: 'Fusion Core',
health: 68,
attack: 30,
defense: 12,
experience: 58,
credits: 42
},
scrap_golem: {
name: 'Scrap Golem',
health: 35,
attack: 14,
defense: 9,
experience: 22,
credits: 16
},
hull_breacher: {
name: 'Hull Breacher',
health: 32,
attack: 20,
defense: 3,
experience: 26,
credits: 18
},
salage_drone: {
name: 'Salvage Drone',
health: 22,
attack: 12,
defense: 5,
experience: 16,
credits: 11
},
// NEW ENEMIES - Planet Theme
plant_beast: {
name: 'Plant Beast',
health: 48,
attack: 15,
defense: 8,
experience: 35,
credits: 26
},
tribal_warrior: {
name: 'Tribal Warrior',
health: 38,
attack: 18,
defense: 6,
experience: 28,
credits: 20
},
jungle_spirit: {
name: 'Jungle Spirit',
health: 55,
attack: 22,
defense: 4,
experience: 42,
credits: 30
},
sand_worm: {
name: 'Sand Worm',
health: 75,
attack: 28,
defense: 9,
experience: 58,
credits: 42
},
mummy_guardian: {
name: 'Mummy Guardian',
health: 62,
attack: 24,
defense: 7,
experience: 48,
credits: 35
},
heat_elemental: {
name: 'Heat Elemental',
health: 52,
attack: 26,
defense: 3,
experience: 45,
credits: 32
},
lava_elemental: {
name: 'Lava Elemental',
health: 68,
attack: 30,
defense: 5,
experience: 55,
credits: 40
},
fire_demon: {
name: 'Fire Demon',
health: 72,
attack: 32,
defense: 6,
experience: 62,
credits: 45
},
magma_beast: {
name: 'Magma Beast',
health: 85,
attack: 28,
defense: 12,
experience: 68,
credits: 50
},
cryo_mutant: {
name: 'Cryo Mutant',
health: 45,
attack: 20,
defense: 7,
experience: 38,
credits: 28
},
frost_android: {
name: 'Frost Android',
health: 52,
attack: 22,
defense: 8,
experience: 42,
credits: 30
},
ice_wraith: {
name: 'Ice Wraith',
health: 58,
attack: 25,
defense: 4,
experience: 48,
credits: 35
},
swamp_beast: {
name: 'Swamp Beast',
health: 35,
attack: 16,
defense: 9,
experience: 24,
credits: 18
},
toxic_spitter: {
name: 'Toxic Spitter',
health: 28,
attack: 19,
defense: 3,
experience: 22,
credits: 16
},
mud_golem: {
name: 'Mud Golem',
health: 42,
attack: 12,
defense: 11,
experience: 26,
credits: 19
},
// NEW ENEMIES - Technology Theme
glitch_wraith: {
name: 'Glitch Wraith',
health: 48,
attack: 26,
defense: 2,
experience: 45,
credits: 32
},
firewall_guardian: {
name: 'Firewall Guardian',
health: 65,
attack: 22,
defense: 8,
experience: 52,
credits: 38
},
data_vampire: {
name: 'Data Vampire',
health: 38,
attack: 30,
defense: 3,
experience: 35,
credits: 26
},
assembly_drone: {
name: 'Assembly Drone',
health: 32,
attack: 15,
defense: 6,
experience: 24,
credits: 17
},
welder_bot: {
name: 'Welder Bot',
health: 28,
attack: 20,
defense: 4,
experience: 22,
credits: 15
},
factory_overseer: {
name: 'Factory Overseer',
health: 58,
attack: 24,
defense: 7,
experience: 46,
credits: 33
},
quantum_phantom: {
name: 'Quantum Phantom',
health: 78,
attack: 35,
defense: 4,
experience: 68,
credits: 50
},
particle_accelerator: {
name: 'Particle Accelerator',
health: 92,
attack: 40,
defense: 6,
experience: 85,
credits: 62
},
reality_bender: {
name: 'Reality Bender',
health: 88,
attack: 45,
defense: 3,
experience: 92,
credits: 68
},
sentinel_program: {
name: 'Sentinel Program',
health: 42,
attack: 21,
defense: 8,
experience: 32,
credits: 24
},
data_corruptor: {
name: 'Data Corruptor',
health: 35,
attack: 25,
defense: 3,
experience: 28,
credits: 20
},
system_guardian: {
name: 'System Guardian',
health: 55,
attack: 23,
defense: 9,
experience: 42,
credits: 30
},
// NEW ENEMIES - Biome/Elemental Theme
shard_elemental: {
name: 'Shard Elemental',
health: 45,
attack: 19,
defense: 10,
experience: 38,
credits: 28
},
resonance_beast: {
name: 'Resonance Beast',
health: 52,
attack: 22,
defense: 6,
experience: 42,
credits: 30
},
mutant_horror: {
name: 'Mutant Horror',
health: 68,
attack: 28,
defense: 5,
experience: 58,
credits: 42
},
toxic_slime: {
name: 'Toxic Slime',
health: 42,
attack: 18,
defense: 8,
experience: 32,
credits: 24
},
radiation_beast: {
name: 'Radiation Beast',
health: 75,
attack: 30,
defense: 4,
experience: 65,
credits: 48
},
shadow_demon: {
name: 'Shadow Demon',
health: 72,
attack: 34,
defense: 3,
experience: 68,
credits: 50
},
nightmare_stalker: {
name: 'Nightmare Stalker',
health: 85,
attack: 38,
defense: 5,
experience: 78,
credits: 58
},
void_walker: {
name: 'Void Walker',
health: 92,
attack: 42,
defense: 7,
experience: 88,
credits: 65
},
temporal_paradox: {
name: 'Temporal Paradox',
health: 78,
attack: 40,
defense: 4,
experience: 75,
credits: 55
},
future_soldier: {
name: 'Future Soldier',
health: 65,
attack: 32,
defense: 9,
experience: 58,
credits: 42
},
past_guardian: {
name: 'Past Guardian',
health: 70,
attack: 28,
defense: 12,
experience: 62,
credits: 45
},
// NEW ENEMIES - Military/War Theme
enemy_soldier: {
name: 'Enemy Soldier',
health: 45,
attack: 20,
defense: 7,
experience: 35,
credits: 26
},
combat_drone: {
name: 'Combat Drone',
health: 38,
attack: 22,
defense: 5,
experience: 30,
credits: 22
},
field_commander: {
name: 'Field Commander',
health: 62,
attack: 28,
defense: 9,
experience: 52,
credits: 38
},
turret_system: {
name: 'Turret System',
health: 48,
attack: 26,
defense: 10,
experience: 38,
credits: 28
},
combat_android: {
name: 'Combat Android',
health: 55,
attack: 24,
defense: 8,
experience: 45,
credits: 33
},
base_commander: {
name: 'Base Commander',
health: 72,
attack: 30,
defense: 11,
experience: 62,
credits: 45
},
weapon_drone: {
name: 'Weapon Drone',
health: 42,
attack: 28,
defense: 4,
experience: 38,
credits: 28
},
test_subject: {
name: 'Test Subject',
health: 58,
attack: 25,
defense: 6,
experience: 48,
credits: 35
},
chief_scientist: {
name: 'Chief Scientist',
health: 35,
attack: 32,
defense: 3,
experience: 42,
credits: 30
},
// NEW ENEMIES - Special/Unique Theme
nightmare_creature: {
name: 'Nightmare Creature',
health: 62,
attack: 28,
defense: 5,
experience: 55,
credits: 40
},
dream_guardian: {
name: 'Dream Guardian',
health: 68,
attack: 30,
defense: 8,
experience: 58,
credits: 42
},
subconscious_demon: {
name: 'Subconscious Demon',
health: 75,
attack: 34,
defense: 4,
experience: 68,
credits: 50
},
memory_fragment: {
name: 'Memory Fragment',
health: 48,
attack: 26,
defense: 6,
experience: 45,
credits: 33
},
forgetfulness_demon: {
name: 'Forgetfulness Demon',
health: 55,
attack: 30,
defense: 3,
experience: 48,
credits: 35
},
nostalgia_spirit: {
name: 'Nostalgia Spirit',
health: 52,
attack: 24,
defense: 9,
experience: 42,
credits: 30
},
rift_demon: {
name: 'Rift Demon',
health: 88,
attack: 44,
defense: 5,
experience: 92,
credits: 68
},
dimensional_hunter: {
name: 'Dimensional Hunter',
health: 95,
attack: 48,
defense: 8,
experience: 105,
credits: 78
},
reality_tear: {
name: 'Reality Tear',
health: 102,
attack: 52,
defense: 3,
experience: 115,
credits: 85
}
};
// Statistics
this.stats = {
dungeonsAttempted: 0,
dungeonsCompleted: 0,
totalEnemiesDefeated: 0,
bestTime: Infinity,
totalLootEarned: 0
};
}
async initialize() {
this.generateDungeonList();
}
generateDungeonList() {
const dungeonListElement = document.getElementById('dungeonList');
if (!dungeonListElement) {
console.error('Dungeon list element not found!');
return;
}
// Clear existing list
dungeonListElement.innerHTML = '';
const questSystem = this.game.systems.questSystem;
const firstStepsQuest = questSystem ? questSystem.findQuest('tutorial_complete') : null;
const showTutorialDungeon = firstStepsQuest && firstStepsQuest.status === 'active';
Object.entries(this.dungeonTypes).forEach(([key, dungeon]) => {
// Skip tutorial dungeon unless First Steps quest is active
if (key === 'tutorial' && !showTutorialDungeon) {
return;
}
const dungeonElement = document.createElement('div');
dungeonElement.className = 'dungeon-item';
dungeonElement.dataset.dungeonType = key;
// Check if tutorial dungeon is completed
const isCompleted = key === 'tutorial' && this.game.systems.player.stats.tutorialDungeonCompleted;
const statusClass = isCompleted ? 'completed' : '';
const statusText = isCompleted ? 'COMPLETED' : '';
dungeonElement.innerHTML = `
<div class="dungeon-name">${dungeon.name}</div>
<div class="dungeon-difficulty ${dungeon.difficulty}">${dungeon.difficulty.toUpperCase()}</div>
${statusText ? `<div class="dungeon-status ${statusClass}">${statusText}</div>` : ''}
<div class="dungeon-description">${dungeon.description}</div>
<div class="dungeon-rewards">Rewards: ${dungeon.rewardMultiplier}x</div>
<div class="dungeon-cost">Energy Cost: ${dungeon.energyCost || this.getEnergyCost(key)}</div>
`;
dungeonElement.addEventListener('click', () => {
if (isCompleted) {
this.game.showNotification('Tutorial dungeon has already been completed!', 'warning', 3000);
} else {
this.selectDungeon(key);
}
});
dungeonListElement.appendChild(dungeonElement);
});
}
selectDungeon(type) {
// Check energy cost
const energyCost = this.getEnergyCost(type);
const player = this.game.systems.player;
if (!player.useEnergy(energyCost)) {
this.game.showNotification(`Not enough energy! Need ${energyCost} energy`, 'error', 3000);
return;
}
// Ensure we're on the Dungeons tab so the user can see the dungeon
if (this.game.ui && this.game.ui.currentTab !== 'dungeons') {
this.game.ui.switchTab('dungeons');
}
// Remove previous selection
document.querySelectorAll('.dungeon-item').forEach(item => {
item.classList.remove('selected');
});
// Add selection to clicked dungeon
const selectedElement = document.querySelector(`[data-dungeon-type="${type}"]`);
if (selectedElement) {
selectedElement.classList.add('selected');
}
// Generate dungeon
this.generateDungeon(type);
this.displayDungeon();
this.game.showNotification(`Entered dungeon! -${energyCost} energy`, 'info', 3000);
}
getEnergyCost(type) {
const costs = {
tutorial: 0,
alien_ruins: 20,
pirate_lair: 15,
corrupted_vault: 25,
asteroid_mine: 10,
nebula_anomaly: 30
};
return costs[type] || 15;
}
calculateDungeonRewards(type, difficulty) {
const dungeonTemplate = this.dungeonTypes[type];
const baseRewards = {
credits: 50,
experience: 25,
items: []
};
// Apply difficulty multiplier
const difficultyMultipliers = {
tutorial: 0.5,
easy: 1.0,
medium: 1.5,
hard: 2.0
};
const multiplier = difficultyMultipliers[difficulty] || 1.0;
const rewardMultiplier = dungeonTemplate.rewardMultiplier || 1.0;
baseRewards.credits = Math.floor(baseRewards.credits * multiplier * rewardMultiplier);
baseRewards.experience = Math.floor(baseRewards.experience * multiplier * rewardMultiplier);
return baseRewards;
}
generateDungeon(type) {
const dungeonTemplate = this.dungeonTypes[type];
// Check if tutorial dungeon has already been completed
if (type === 'tutorial' && this.game.systems.player.stats.tutorialDungeonCompleted) {
this.game.showNotification('Tutorial dungeon has already been completed!', 'warning', 3000);
return;
}
this.currentDungeon = {
type: type,
name: dungeonTemplate.name,
description: dungeonTemplate.description,
difficulty: dungeonTemplate.difficulty,
healthType: dungeonTemplate.healthType,
enemyTypes: dungeonTemplate.enemyTypes,
rewardMultiplier: dungeonTemplate.rewardMultiplier,
rooms: [],
currentRoomIndex: 0,
startTime: Date.now(),
completed: false
};
// Generate rooms - ensure minimum of 3 rooms (entrance, at least 1 middle, boss)
const roomCount = Math.max(3, this.game.getRandomInt(5, 8));
this.currentDungeon.rooms = this.generateRoomLayout(roomCount, dungeonTemplate);
// Set current room
this.currentRoom = this.currentDungeon.rooms[0];
this.dungeonProgress = 0;
// Show dungeon view and hide list
this.showDungeonView();
}
generateRoomLayout(roomCount, dungeonTemplate) {
const rooms = [];
// Always start with entrance
rooms.push(this.createRoom('entrance', dungeonTemplate));
// Generate middle rooms (subtract 2 for entrance and boss room)
const middleRoomCount = roomCount - 2;
for (let i = 0; i < middleRoomCount; i++) {
const roomType = this.getRandomRoomType();
const room = this.createRoom(roomType, dungeonTemplate);
rooms.push(room);
}
// Always end with boss room (exit is handled by completing the boss room)
rooms.push(this.createRoom('boss', dungeonTemplate));
// Verify room accessibility
for (let i = 0; i < rooms.length; i++) {
}
return rooms;
}
getRandomRoomType() {
const weights = {
corridor: 40,
chamber: 30,
treasure: 0, // Temporarily disabled
entrance: 5,
boss: 5,
exit: 0
};
const totalWeight = Object.values(weights).reduce((sum, weight) => sum + weight, 0);
let random = Math.random() * totalWeight;
for (const [type, weight] of Object.entries(weights)) {
random -= weight;
if (random <= 0) {
return type;
}
}
return 'corridor';
}
createRoom(roomType, dungeonTemplate) {
const template = this.roomTypes[roomType];
const room = {
type: roomType,
name: template.name,
enemies: [],
rewards: null,
explored: false,
completed: false
};
// Generate enemies
if (template.enemies > 0) {
for (let i = 0; i < template.enemies; i++) {
const enemyType = dungeonTemplate.enemyTypes[
Math.floor(Math.random() * dungeonTemplate.enemyTypes.length)
];
room.enemies.push(this.createEnemy(enemyType, template.isBoss));
}
}
// Generate rewards
if (template.rewards) {
room.rewards = this.generateRoomRewards(dungeonTemplate.difficulty, template.isBoss);
}
return room;
}
createEnemy(enemyType, isBoss = false) {
const template = this.enemyTemplates[enemyType];
const bossMultiplier = isBoss ? 2.5 : 1.0;
return {
id: Date.now() + Math.random().toString(36).substr(2, 9),
type: enemyType,
name: isBoss ? `Boss ${template.name}` : template.name,
health: Math.floor(template.health * bossMultiplier),
maxHealth: Math.floor(template.health * bossMultiplier),
attack: Math.floor(template.attack * bossMultiplier),
defense: Math.floor(template.defense * bossMultiplier),
experience: Math.floor(template.experience * bossMultiplier),
credits: Math.floor(template.credits * bossMultiplier),
isBoss: isBoss
};
}
generateRoomRewards(difficulty, isBoss = false) {
const baseRewards = this.game.systems.economy.generateRewards(difficulty, 'dungeon');
const multiplier = isBoss ? 2.0 : 1.0;
const rewards = {
credits: Math.floor(baseRewards.credits * multiplier),
experience: Math.floor(baseRewards.experience * multiplier),
materials: []
};
// Add crafting materials based on chance and difficulty
const materialChance = isBoss ? 0.9 : 0.4;
if (Math.random() < materialChance) {
const materialCount = isBoss ? this.game.getRandomInt(3, 6) : this.game.getRandomInt(1, 3);
// Define material pools with weights for better balance
const materialPools = {
tutorial: [
{ id: 'iron_ore', weight: 40 },
{ id: 'copper_wire', weight: 30 },
{ id: 'herbs', weight: 20 },
{ id: 'bandages', weight: 10 }
],
easy: [
{ id: 'iron_ore', weight: 30 },
{ id: 'copper_wire', weight: 25 },
{ id: 'energy_crystal', weight: 15 },
{ id: 'leather', weight: 15 },
{ id: 'herbs', weight: 10 },
{ id: 'bandages', weight: 5 }
],
medium: [
{ id: 'iron_ore', weight: 25 },
{ id: 'steel_plate', weight: 20 },
{ id: 'energy_crystal', weight: 20 },
{ id: 'copper_wire', weight: 15 },
{ id: 'rare_metal', weight: 5 },
{ id: 'bandages', weight: 15 }
],
hard: [
{ id: 'steel_plate', weight: 30 },
{ id: 'energy_crystal', weight: 25 },
{ id: 'rare_metal', weight: 15 },
{ id: 'battery', weight: 20 },
{ id: 'bandages', weight: 10 }
],
extreme: [
{ id: 'rare_metal', weight: 30 },
{ id: 'energy_crystal', weight: 25 },
{ id: 'battery', weight: 25 },
{ id: 'advanced_components', weight: 20 }
]
};
const pool = materialPools[difficulty] || materialPools.easy;
// Helper function to get weighted random material
function getWeightedRandomMaterial(materialPool) {
const totalWeight = materialPool.reduce((sum, mat) => sum + mat.weight, 0);
let random = Math.random() * totalWeight;
for (const material of materialPool) {
random -= material.weight;
if (random <= 0) {
return material.id;
}
}
return materialPool[0].id; // Fallback
}
for (let i = 0; i < materialCount; i++) {
const material = getWeightedRandomMaterial(pool);
const quantity = this.game.getRandomInt(1, isBoss ? 3 : 2);
rewards.materials.push({
id: material,
quantity: quantity
});
}
}
return rewards;
}
displayDungeon() {
const dungeonViewElement = document.getElementById('dungeonView');
if (!dungeonViewElement) {
const allElements = document.querySelectorAll('[id*="dungeon"]');
return;
}
if (!this.currentDungeon) {
return;
}
const room = this.currentRoom;
if (room) {
// Room exists, continue processing
}
const progress = Math.floor((this.currentDungeon.currentRoomIndex / this.currentDungeon.rooms.length) * 100);
let content = `
<div class="dungeon-display">
<div class="dungeon-header">
<h2>${this.currentDungeon.name}</h2>
<div class="dungeon-progress">
<div class="progress-bar">
<div class="progress-fill" style="width: ${progress}%"></div>
</div>
<span>Room ${this.currentDungeon.currentRoomIndex + 1} / ${this.currentDungeon.rooms.length}</span>
</div>
</div>
<div class="health-status">
${this.getHealthDisplay()}
</div>
<div class="current-room">
<h3>${room.name}</h3>
${this.getRoomDescription(room)}
</div>
<div class="room-content">
${this.getRoomContent(room)}
</div>
<div class="room-actions">
${this.getRoomActions(room)}
</div>
</div>
`;
dungeonViewElement.innerHTML = content;
// Only add event listeners for buttons that don't use inline onclick handlers
const completeDungeonBtn = dungeonViewElement.querySelector('button[onclick*="completeDungeon"]');
if (completeDungeonBtn) {
completeDungeonBtn.addEventListener('click', (e) => {
e.preventDefault();
this.completeDungeon();
});
}
}
getHealthDisplay() {
const player = this.game.systems.player;
const healthType = this.currentDungeon.healthType;
if (healthType === 'ship') {
const shipHealth = player.ship.health || 0;
const shipMaxHealth = player.ship.maxHealth || 1000;
const healthPercent = Math.round((shipHealth / shipMaxHealth) * 100);
return `
<div class="health-bar ship-health">
<div class="health-label">Ship Health</div>
<div class="progress-bar">
<div class="progress-fill ship-health-fill" style="width: ${healthPercent}%"></div>
</div>
<span>${shipHealth} / ${shipMaxHealth}</span>
</div>
`;
} else {
const playerHealth = player.attributes.health || 0;
const playerMaxHealth = player.attributes.maxHealth || 100;
const healthPercent = Math.round((playerHealth / playerMaxHealth) * 100);
return `
<div class="health-bar player-health">
<div class="health-label">Player Health</div>
<div class="progress-bar">
<div class="progress-fill player-health-fill" style="width: ${healthPercent}%"></div>
</div>
<span>${playerHealth} / ${playerMaxHealth}</span>
</div>
`;
}
}
getRoomDescription(room) {
const descriptions = {
entrance: 'You enter the dungeon. The air is thick with anticipation.',
corridor: 'A narrow corridor stretches ahead. You can hear distant sounds.',
chamber: 'You enter a large chamber. The echoes of past battles linger here.',
treasure: 'Golden light glimmers from piles of treasure in this room.',
boss: 'A massive presence fills the room. This is the guardian of this dungeon.',
exit: 'You can see the exit. Freedom awaits!'
};
return `<p class="room-description">${descriptions[room.type] || 'You continue exploring...'}</p>`;
}
getRoomContent(room) {
if (room.completed) {
return '<p class="room-completed">This room has been cleared.</p>';
}
if (room.enemies.length > 0) {
const enemiesHtml = room.enemies.map(enemy => `
<div class="enemy ${enemy.isBoss ? 'boss' : ''}">
<div class="enemy-name">${enemy.name}</div>
<div class="enemy-health">
<div class="progress-bar">
<div class="progress-fill" style="width: ${(enemy.health / enemy.maxHealth) * 100}%"></div>
</div>
<span>${enemy.health} / ${enemy.maxHealth}</span>
</div>
<div class="enemy-stats">ATK: ${enemy.attack} | DEF: ${enemy.defense}</div>
</div>
`).join('');
return `<div class="enemies">${enemiesHtml}</div>`;
}
if (room.rewards && !room.completed) {
return '<div class="treasure"><i class="fas fa-treasure-chest"></i> <p>Treasure awaits!</p></div>';
}
return '<p>The room is empty and quiet.</p>';
}
getRoomActions(room) {
if (room.completed) {
if (this.currentDungeon.currentRoomIndex < this.currentDungeon.rooms.length - 1) {
return '<button class="btn btn-primary" onclick="try { if(window.game && window.game.systems) window.game.systems.dungeonSystem.nextRoom(); else { console.error(\'Game not available for nextRoom\'); } } catch(e) { console.error(\'Next room button error:\', e); }">Continue to Next Room</button>';
} else {
return '<button class="btn btn-success" onclick="try { if(window.game && window.game.systems) window.game.systems.dungeonSystem.completeDungeon(); else { console.error(\'Game not available for completeDungeon\'); } } catch(e) { console.error(\'Complete dungeon button error:\', e); }">Complete Dungeon</button>';
}
}
if (room.enemies.length > 0) {
const buttonHtml = '<button class="btn btn-danger" onclick="try { if(window.game && window.game.systems) window.game.systems.dungeonSystem.startCombat(); else { console.error(\'Game not available, retrying...\'); setTimeout(() => { if(window.game && window.game.systems) window.game.systems.dungeonSystem.startCombat(); }, 100); } } catch(e) { console.error(\'Combat button error:\', e); }">Start Combat</button>';
return buttonHtml;
}
if (room.rewards) {
return '<button class="btn btn-success" onclick="try { if(window.game && window.game.systems) window.game.systems.dungeonSystem.claimRewards();} else { console.error(\'Game not available for claimRewards\'); } } catch(e) { console.error(\'Claim rewards button error:\', e); }">Claim Rewards</button>';
}
// Check if this is the final room
if (this.currentDungeon.currentRoomIndex >= this.currentDungeon.rooms.length - 1) {
return '<button class="btn btn-success" onclick="try { if(window.game && window.game.systems) window.game.systems.dungeonSystem.completeDungeon(); else { console.error(\'Game not available for completeDungeon\'); } } catch(e) { console.error(\'Complete dungeon button error:\', e); }">Complete Dungeon</button>';
}
return '<button class="btn btn-primary" onclick="try { if(window.game && window.game.systems) window.game.systems.dungeonSystem.nextRoom(); else { console.error(\'Game not available for nextRoom\'); alert(\'Game not ready. Please try again.\'); } } catch(e) { console.error(\'Move forward button error:\', e); alert(\'Error moving forward. Please try again.\'); }">Move Forward</button>';
}
async startCombat() {
if (this.isExploring) {
return;
}
this.isExploring = true;
const room = this.currentRoom;
const enemies = room.enemies.filter(e => e.health > 0);
if (enemies.length === 0) {
this.completeRoom();
return;
}
// Simulate combat
await this.simulateCombat(enemies);
}
async simulateCombat(enemies) {
try {
const player = this.game.systems.player;
const healthType = this.currentDungeon.healthType;
let combatLog = [];
// Handle case where there are no enemies
if (enemies.length === 0) {
combatLog.push('Room was empty - no enemies found');
this.completeRoom();
return;
}
for (const [index, enemy] of enemies.entries()) {
// Player attacks
const playerDamage = player.calculateDamage(this.currentDungeon.difficulty);
const actualDamage = Math.max(1, playerDamage.damage - enemy.defense);
enemy.health = Math.max(0, enemy.health - actualDamage);
combatLog.push(`You dealt ${actualDamage} damage to ${enemy.name}${playerDamage.isCritical ? ' (CRITICAL!)' : ''}`);
// Update UI after player attack to show enemy health change
this.displayDungeon();
// Also update global player UI to ensure health bars are updated
if (player.updateUI) {
player.updateUI();
}
// Small delay to make the combat visible
await new Promise(resolve => setTimeout(resolve, 500));
// Enemy attacks if still alive
if (enemy.health > 0) {
let enemyDamage, damageTarget;
if (healthType === 'ship') {
// Space missions: higher damage, target ship health
enemyDamage = Math.max(1, Math.floor(enemy.attack * 1.5) - player.ship.defense);
damageTarget = 'ship';
this.applyShipDamage(enemyDamage);
combatLog.push(`${enemy.name} dealt ${enemyDamage} damage to your ship`);
} else {
// Ground missions: normal damage, target player health
enemyDamage = Math.max(1, enemy.attack - player.attributes.defense);
damageTarget = 'player';
player.takeDamage(enemyDamage);
combatLog.push(`${enemy.name} dealt ${enemyDamage} damage to you`);
}
// Update UI after enemy attack to show player health change
this.displayDungeon();
// Also update global player UI to ensure health bars are updated
if (player.updateUI) {
player.updateUI();
}
// Small delay to make the combat visible
await new Promise(resolve => setTimeout(resolve, 500));
// Check for destruction
if (healthType === 'ship' && player.ship.health <= 0) {
this.handleShipDestruction();
} else if (healthType === 'player' && player.attributes.health <= 0) {
this.handlePlayerDefeat();
}
} else {
// Enemy defeated
player.addExperience(enemy.experience);
this.game.systems.economy.addCredits(enemy.credits, 'dungeon');
player.incrementKills();
this.stats.totalEnemiesDefeated++;
// Update quest progress for combat objectives
if (this.game.systems.questSystem) {
this.game.systems.questSystem.onEnemyDefeated();
}
combatLog.push(`${enemy.name} defeated! +${enemy.experience} XP, +${enemy.credits} credits`);
// Update UI after enemy defeat
this.displayDungeon();
// Also update global player UI to ensure health bars are updated
if (player.updateUI) {
player.updateUI();
}
// Small delay to make the combat visible
await new Promise(resolve => setTimeout(resolve, 500));
}
}
// Show combat results
this.game.showNotification('Combat completed!', 'success', 3000);
combatLog.forEach(message => this.game.showNotification(message, 'info', 2000));
// Check if all enemies defeated
const remainingEnemies = this.currentRoom.enemies.filter(e => e.health > 0);
if (remainingEnemies.length === 0) {
this.completeRoom();
}
this.isExploring = false;
this.displayDungeon();
} catch (error) {
console.error('[DUNGEON] Error in simulateCombat:', error);
console.error('[DUNGEON] Error stack:', error.stack);
this.isExploring = false;
}
}
// Health system methods
applyShipDamage(amount) {
const player = this.game.systems.player;
player.ship.health = Math.max(0, player.ship.health - amount);
player.updateUI();
// Check for ship destruction
if (player.ship.health <= 0) {
this.handleShipDestruction();
}
}
handleShipDestruction() {
const player = this.game.systems.player;
// Show destruction message
this.game.showNotification('Your ship has been destroyed!', 'error', 5000);
this.game.showNotification('Dungeon failed - all progress lost.', 'warning', 4000);
// Remove the current ship from inventory
if (this.game.systems.inventory) {
this.game.systems.inventory.removeItem(player.ship);
}
// Reset to a basic ship if available in inventory
const availableShips = this.game.systems.inventory.getItemsByType('ship');
if (availableShips.length > 0) {
player.ship = availableShips[0];
this.game.showNotification(`Switched to ${player.ship.name}`, 'info', 3000);
} else {
// No ships available - create a basic one
player.ship = {
name: 'Basic Fighter',
health: 1000,
maxHealth: 1000,
defense: 5,
attack: 10,
type: 'ship'
};
this.game.showNotification('No ships available - using emergency fighter', 'warning', 3000);
}
// Apply dungeon failure penalty
this.applyDungeonFailurePenalty();
// Exit dungeon
this.exitDungeon();
}
applyDungeonFailurePenalty() {
const player = this.game.systems.player;
// Lose some credits as penalty
const creditPenalty = Math.floor(this.game.systems.economy.credits * 0.1); // 10% credit loss
this.game.systems.economy.removeCredits(creditPenalty);
// Lose some experience
const expPenalty = Math.floor(player.experience * 0.05); // 5% exp loss
player.experience = Math.max(0, player.experience - expPenalty);
// Update failure statistics
this.stats.dungeonsFailed++;
this.game.showNotification(`Dungeon penalty: -${creditPenalty} credits, -${expPenalty} XP`, 'warning', 4000);
}
handlePlayerDefeat() {
this.game.showNotification('You have been defeated!', 'error', 5000);
this.game.showNotification('You\'ve been forced to retreat from the dungeon.', 'warning', 4000);
// Heal player to prevent death loop
const player = this.game.systems.player;
player.attributes.health = Math.floor(player.attributes.maxHealth * 0.5);
// Exit dungeon
this.exitDungeon();
}
exitDungeon() {
this.currentDungeon = null;
this.currentRoom = null;
this.dungeonProgress = 0;
this.isExploring = false;
// Return to main view
this.generateDungeonList();
}
claimRewards() {
const room = this.currentRoom;
if (!room.rewards || room.completed) return;
// Give all rewards including materials
this.game.systems.economy.giveRewards(room.rewards, 'dungeon');
room.rewards = null; // Remove rewards after claiming
this.game.showNotification('Rewards claimed!', 'success', 3000);
// Use the proper completeRoom method to ensure consistent behavior
this.completeRoom();
}
completeRoom() {
const room = this.currentRoom;
room.completed = true;
room.explored = true;
// Reset exploring flag when completing a room
this.isExploring = false;
// Auto-claim rewards if available
if (room.rewards) {
// Give credits and experience
this.game.systems.economy.giveRewards(room.rewards, 'dungeon');
// Add crafting materials to inventory
if (room.rewards.materials && room.rewards.materials.length > 0) {
let materialText = '';
room.rewards.materials.forEach(material => {
this.game.systems.inventory.addItem(material.id, material.quantity);
materialText += `${material.quantity}x ${material.id}, `;
});
materialText = materialText.slice(0, -2);
this.game.showNotification(`Materials found: ${materialText}`, 'success', 4000);
}
room.rewards = null;
}
this.game.showNotification(`${room.name} completed!`, 'success', 3000);
// Check if this is a boss room - if so, automatically complete the dungeon
if (room.type === 'boss') {
setTimeout(() => {
this.completeDungeon();
}, 2000); // Small delay to show the completion message first
} else {
this.displayDungeon();
}
}
nextRoom() {
// Log all rooms for debugging
this.currentDungeon.rooms.forEach((room, index) => {
});
if (this.currentDungeon.currentRoomIndex >= this.currentDungeon.rooms.length - 1) {
return;
}
const oldIndex = this.currentDungeon.currentRoomIndex;
this.currentDungeon.currentRoomIndex++;
this.currentRoom = this.currentDungeon.rooms[this.currentDungeon.currentRoomIndex];
this.displayDungeon();
}
completeDungeon() {
if (!this.currentDungeon) {
return;
}
const completionTime = Date.now() - this.currentDungeon.startTime;
const player = this.game.systems.player;
const economy = this.game.systems.economy;
// Generate proper rewards including materials
const baseRewards = this.generateRoomRewards(this.currentDungeon.difficulty, false);
// Apply time bonus
const timeBonus = Math.floor(completionTime < 300000 ? 50 : 0); // Bonus for completing in under 5 minutes
baseRewards.credits += timeBonus;
baseRewards.experience += Math.floor(timeBonus / 2);
// Give rewards
economy.giveRewards(baseRewards, 'dungeon');
player.addExperience(baseRewards.experience);
// Update statistics
this.stats.dungeonsCompleted++;
this.stats.totalTimeInDungeons += completionTime;
// Update player dungeons cleared stat
player.stats.dungeonsCleared++;
// Update quest progress for dungeon objectives
if (this.game.systems.questSystem) {
// Check if this is a tutorial dungeon
if (this.currentDungeon.type === 'tutorial') {
// Mark tutorial dungeon as completed in player stats
player.stats.tutorialDungeonCompleted = true;
// Update tutorial dungeon quest progress
this.game.systems.questSystem.updateTutorialDungeonProgress();
} else {
// Update regular dungeon quest progress using the standard method
this.game.systems.questSystem.onDungeonCompleted();
}
}
// Show completion message
this.game.showNotification(`Dungeon completed! Time: ${this.game.formatTime(completionTime)}`, 'success', 5000);
if (timeBonus > 0) {
this.game.showNotification(`Time bonus: +${timeBonus} credits!`, 'info', 3000);
}
// Reset dungeon state
this.currentDungeon = null;
this.currentRoom = null;
this.isExploring = false;
// Return to dungeon list view
this.showDungeonList();
this.generateDungeonList();
// Force UI refresh
this.updateUI();
}
showDungeonList() {
const dungeonListElement = document.getElementById('dungeonList');
const dungeonViewElement = document.getElementById('dungeonView');
if (dungeonListElement) {
dungeonListElement.style.display = 'flex';
}
if (dungeonViewElement) {
dungeonViewElement.style.display = 'none';
// Clear the dungeon view content to prevent frozen display
dungeonViewElement.innerHTML = '';
}
}
showDungeonView() {
const dungeonListElement = document.getElementById('dungeonList');
const dungeonViewElement = document.getElementById('dungeonView');
if (dungeonListElement) {
dungeonListElement.style.display = 'none';
}
if (dungeonViewElement) {
dungeonViewElement.style.display = 'flex';
}
// Display the current dungeon
this.displayDungeon();
}
// UI updates
updateUI() {
// Update dungeon statistics if elements exist
const dungeonsClearedElement = document.getElementById('dungeonsCleared');
if (dungeonsClearedElement) {
dungeonsClearedElement.textContent = this.stats.dungeonsCompleted;
}
}
// Save/Load
save() {
return {
stats: this.stats,
currentDungeon: this.currentDungeon,
currentRoom: this.currentRoom,
dungeonProgress: this.dungeonProgress
};
}
load(data) {
if (data.stats) this.stats = { ...this.stats, ...data.stats };
if (data.currentDungeon) this.currentDungeon = data.currentDungeon;
if (data.currentRoom) this.currentRoom = data.currentRoom;
if (data.dungeonProgress !== undefined) this.dungeonProgress = data.dungeonProgress;
}
}