/** * 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 = `
${dungeon.name}
${dungeon.difficulty.toUpperCase()}
${statusText ? `
${statusText}
` : ''}
${dungeon.description}
Rewards: ${dungeon.rewardMultiplier}x
Energy Cost: ${dungeon.energyCost || this.getEnergyCost(key)}
`; 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 = `

${this.currentDungeon.name}

Room ${this.currentDungeon.currentRoomIndex + 1} / ${this.currentDungeon.rooms.length}
${this.getHealthDisplay()}

${room.name}

${this.getRoomDescription(room)}
${this.getRoomContent(room)}
${this.getRoomActions(room)}
`; 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 `
Ship Health
${shipHealth} / ${shipMaxHealth}
`; } else { const playerHealth = player.attributes.health || 0; const playerMaxHealth = player.attributes.maxHealth || 100; const healthPercent = Math.round((playerHealth / playerMaxHealth) * 100); return `
Player Health
${playerHealth} / ${playerMaxHealth}
`; } } 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 `

${descriptions[room.type] || 'You continue exploring...'}

`; } getRoomContent(room) { if (room.completed) { return '

This room has been cleared.

'; } if (room.enemies.length > 0) { const enemiesHtml = room.enemies.map(enemy => `
${enemy.name}
${enemy.health} / ${enemy.maxHealth}
ATK: ${enemy.attack} | DEF: ${enemy.defense}
`).join(''); return `
${enemiesHtml}
`; } if (room.rewards && !room.completed) { return '

Treasure awaits!

'; } return '

The room is empty and quiet.

'; } getRoomActions(room) { if (room.completed) { if (this.currentDungeon.currentRoomIndex < this.currentDungeon.rooms.length - 1) { return ''; } else { return ''; } } if (room.enemies.length > 0) { const buttonHtml = ''; return buttonHtml; } if (room.rewards) { return ''; } // Check if this is the final room if (this.currentDungeon.currentRoomIndex >= this.currentDungeon.rooms.length - 1) { return ''; } return ''; } 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; } }