408 lines
11 KiB
JavaScript
408 lines
11 KiB
JavaScript
/**
|
|
* MINING & DUNGEONS SYSTEM
|
|
* Underground cave generation, mining, and dungeon exploration
|
|
*/
|
|
class MiningDungeonsSystem {
|
|
constructor(scene) {
|
|
this.scene = scene;
|
|
this.enabled = true;
|
|
|
|
// Caves & dungeons
|
|
this.caves = new Map();
|
|
this.currentCave = null;
|
|
|
|
// Mining
|
|
this.oreVeins = new Map();
|
|
this.minedOres = [];
|
|
|
|
// Elevators
|
|
this.elevators = new Map();
|
|
|
|
// Enemies
|
|
this.caveEnemies = [];
|
|
|
|
// Bosses
|
|
this.dungeonBosses = new Map();
|
|
|
|
// Settings
|
|
this.settings = {
|
|
maxDepth: 50,
|
|
roomSize: { min: 5, max: 15 },
|
|
tunnelWidth: 2,
|
|
oreChance: 0.1
|
|
};
|
|
|
|
this.loadProgress();
|
|
this.init();
|
|
|
|
console.log('✅ Mining & Dungeons System initialized');
|
|
}
|
|
|
|
init() {
|
|
this.defineOreTypes();
|
|
this.defineEnemyTypes();
|
|
console.log('⛏️ Mining & Dungeons ready');
|
|
}
|
|
|
|
// ========== ORE TYPES ==========
|
|
|
|
defineOreTypes() {
|
|
this.oreTypes = {
|
|
// Depth 0-10
|
|
copper: { depth: [0, 10], value: 5, rarity: 0.4 },
|
|
tin: { depth: [0, 10], value: 5, rarity: 0.4 },
|
|
|
|
// Depth 10-20
|
|
iron: { depth: [10, 20], value: 15, rarity: 0.3 },
|
|
coal: { depth: [10, 20], value: 10, rarity: 0.35 },
|
|
|
|
// Depth 20-30
|
|
gold: { depth: [20, 30], value: 50, rarity: 0.15 },
|
|
silver: { depth: [20, 30], value: 30, rarity: 0.2 },
|
|
|
|
// Depth 30+
|
|
diamond: { depth: [30, 50], value: 200, rarity: 0.05 },
|
|
mythril: { depth: [30, 50], value: 500, rarity: 0.02 }
|
|
};
|
|
}
|
|
|
|
// ========== ENEMY TYPES ==========
|
|
|
|
defineEnemyTypes() {
|
|
this.enemyTypes = {
|
|
bat: {
|
|
name: 'Cave Bat',
|
|
hp: 20,
|
|
damage: 5,
|
|
speed: 1.5,
|
|
xp: 10,
|
|
loot: ['bat_wing', 'guano']
|
|
},
|
|
spider: {
|
|
name: 'Giant Spider',
|
|
hp: 50,
|
|
damage: 15,
|
|
speed: 1.0,
|
|
xp: 25,
|
|
loot: ['spider_silk', 'venom']
|
|
},
|
|
mole: {
|
|
name: 'Mutant Mole',
|
|
hp: 80,
|
|
damage: 20,
|
|
speed: 0.8,
|
|
xp: 40,
|
|
loot: ['mole_claw', 'earth_essence']
|
|
},
|
|
golem: {
|
|
name: 'Stone Golem',
|
|
hp: 200,
|
|
damage: 40,
|
|
speed: 0.5,
|
|
xp: 100,
|
|
loot: ['stone_core', 'ancient_rune']
|
|
}
|
|
};
|
|
}
|
|
|
|
// ========== CAVE GENERATION ==========
|
|
|
|
generateCave(depth, seed) {
|
|
const cave = {
|
|
id: `cave_${depth}_${seed}`,
|
|
depth,
|
|
seed,
|
|
rooms: [],
|
|
tunnels: [],
|
|
oreVeins: [],
|
|
enemies: [],
|
|
boss: null,
|
|
explored: false
|
|
};
|
|
|
|
// Generate rooms
|
|
const numRooms = 5 + Math.floor(depth / 10);
|
|
for (let i = 0; i < numRooms; i++) {
|
|
cave.rooms.push(this.generateRoom(depth));
|
|
}
|
|
|
|
// Connect rooms with tunnels
|
|
cave.tunnels = this.connectRooms(cave.rooms);
|
|
|
|
// Place ore veins
|
|
cave.oreVeins = this.placeOres(depth, cave.rooms);
|
|
|
|
// Spawn enemies
|
|
cave.enemies = this.spawnEnemies(depth, cave.rooms);
|
|
|
|
// Boss every 10 levels
|
|
if (depth % 10 === 0) {
|
|
cave.boss = this.createBoss(depth);
|
|
}
|
|
|
|
this.caves.set(cave.id, cave);
|
|
return cave;
|
|
}
|
|
|
|
generateRoom(depth) {
|
|
const size = this.settings.roomSize;
|
|
const width = size.min + Math.floor(Math.random() * (size.max - size.min));
|
|
const height = size.min + Math.floor(Math.random() * (size.max - size.min));
|
|
|
|
return {
|
|
x: Math.floor(Math.random() * 100),
|
|
y: Math.floor(Math.random() * 100),
|
|
width,
|
|
height,
|
|
type: this.getRoomType(depth)
|
|
};
|
|
}
|
|
|
|
getRoomType(depth) {
|
|
const types = ['cave', 'crystal_cavern', 'lava_chamber', 'ice_cave', 'mushroom_grove'];
|
|
const index = Math.floor(depth / 10) % types.length;
|
|
return types[index];
|
|
}
|
|
|
|
connectRooms(rooms) {
|
|
const tunnels = [];
|
|
|
|
for (let i = 0; i < rooms.length - 1; i++) {
|
|
const room1 = rooms[i];
|
|
const room2 = rooms[i + 1];
|
|
|
|
tunnels.push({
|
|
from: { x: room1.x + room1.width / 2, y: room1.y + room1.height / 2 },
|
|
to: { x: room2.x + room2.width / 2, y: room2.y + room2.height / 2 },
|
|
width: this.settings.tunnelWidth
|
|
});
|
|
}
|
|
|
|
return tunnels;
|
|
}
|
|
|
|
// ========== ORE PLACEMENT ==========
|
|
|
|
placeOres(depth, rooms) {
|
|
const oreVeins = [];
|
|
|
|
for (const room of rooms) {
|
|
const numVeins = 2 + Math.floor(Math.random() * 5);
|
|
|
|
for (let i = 0; i < numVeins; i++) {
|
|
const ore = this.selectOre(depth);
|
|
if (!ore) continue;
|
|
|
|
oreVeins.push({
|
|
type: ore,
|
|
x: room.x + Math.floor(Math.random() * room.width),
|
|
y: room.y + Math.floor(Math.random() * room.height),
|
|
amount: 5 + Math.floor(Math.random() * 10),
|
|
mined: false
|
|
});
|
|
}
|
|
}
|
|
|
|
return oreVeins;
|
|
}
|
|
|
|
selectOre(depth) {
|
|
const validOres = Object.entries(this.oreTypes)
|
|
.filter(([_, ore]) => depth >= ore.depth[0] && depth <= ore.depth[1]);
|
|
|
|
if (validOres.length === 0) return null;
|
|
|
|
// Weighted random selection
|
|
const totalRarity = validOres.reduce((sum, [_, ore]) => sum + ore.rarity, 0);
|
|
let roll = Math.random() * totalRarity;
|
|
|
|
for (const [oreName, ore] of validOres) {
|
|
roll -= ore.rarity;
|
|
if (roll <= 0) return oreName;
|
|
}
|
|
|
|
return validOres[0][0];
|
|
}
|
|
|
|
// ========== ENEMY SPAWNING ==========
|
|
|
|
spawnEnemies(depth, rooms) {
|
|
const enemies = [];
|
|
const enemiesPerRoom = 1 + Math.floor(depth / 5);
|
|
|
|
for (const room of rooms) {
|
|
for (let i = 0; i < enemiesPerRoom; i++) {
|
|
const enemyType = this.selectEnemy(depth);
|
|
const enemyData = this.enemyTypes[enemyType];
|
|
|
|
enemies.push({
|
|
type: enemyType,
|
|
name: enemyData.name,
|
|
hp: enemyData.hp * (1 + depth * 0.1),
|
|
maxHp: enemyData.hp * (1 + depth * 0.1),
|
|
damage: enemyData.damage * (1 + depth * 0.1),
|
|
speed: enemyData.speed,
|
|
x: room.x + Math.floor(Math.random() * room.width),
|
|
y: room.y + Math.floor(Math.random() * room.height),
|
|
xp: enemyData.xp,
|
|
loot: enemyData.loot
|
|
});
|
|
}
|
|
}
|
|
|
|
return enemies;
|
|
}
|
|
|
|
selectEnemy(depth) {
|
|
if (depth < 10) return 'bat';
|
|
if (depth < 20) return Math.random() < 0.5 ? 'bat' : 'spider';
|
|
if (depth < 30) return Math.random() < 0.3 ? 'spider' : 'mole';
|
|
return Math.random() < 0.5 ? 'mole' : 'golem';
|
|
}
|
|
|
|
// ========== BOSS CREATION ==========
|
|
|
|
createBoss(depth) {
|
|
const bossTypes = {
|
|
10: { name: 'Crystal Guardian', hp: 500, damage: 50 },
|
|
20: { name: 'Lava Titan', hp: 1000, damage: 80 },
|
|
30: { name: 'Ice Dragon', hp: 2000, damage: 120 },
|
|
40: { name: 'Shadow Demon', hp: 3500, damage: 150 },
|
|
50: { name: 'Ancient Wyrm', hp: 5000, damage: 200 }
|
|
};
|
|
|
|
const bossData = bossTypes[depth] || bossTypes[50];
|
|
|
|
return {
|
|
name: bossData.name,
|
|
hp: bossData.hp,
|
|
maxHp: bossData.hp,
|
|
damage: bossData.damage,
|
|
phase: 1,
|
|
maxPhases: 3,
|
|
defeated: false,
|
|
loot: this.generateBossLoot(depth)
|
|
};
|
|
}
|
|
|
|
generateBossLoot(depth) {
|
|
return [
|
|
{ item: 'legendary_sword', chance: 0.1 },
|
|
{ item: 'boss_trophy', chance: 1.0 },
|
|
{ item: 'rare_gem', chance: 0.5 },
|
|
{ item: 'gold', amount: depth * 100, chance: 1.0 }
|
|
];
|
|
}
|
|
|
|
// ========== MINING ==========
|
|
|
|
mineOre(oreVeinId) {
|
|
const vein = this.oreVeins.get(oreVeinId);
|
|
if (!vein || vein.mined) return null;
|
|
|
|
// Mine ore
|
|
vein.amount--;
|
|
|
|
if (vein.amount <= 0) {
|
|
vein.mined = true;
|
|
}
|
|
|
|
// Add to inventory
|
|
if (this.scene.inventorySystem) {
|
|
this.scene.inventorySystem.addItem(vein.type, 1);
|
|
}
|
|
|
|
// Track mined ores
|
|
this.minedOres.push({
|
|
type: vein.type,
|
|
time: Date.now()
|
|
});
|
|
|
|
console.log(`⛏️ Mined ${vein.type}!`);
|
|
return vein.type;
|
|
}
|
|
|
|
// ========== ELEVATOR ==========
|
|
|
|
buildElevator(x, y) {
|
|
const elevator = {
|
|
id: `elevator_${x}_${y}`,
|
|
x, y,
|
|
currentDepth: 0,
|
|
maxDepth: 0,
|
|
active: true
|
|
};
|
|
|
|
this.elevators.set(elevator.id, elevator);
|
|
console.log(`🛗 Built elevator at (${x}, ${y})`);
|
|
return elevator;
|
|
}
|
|
|
|
useElevator(elevatorId, targetDepth) {
|
|
const elevator = this.elevators.get(elevatorId);
|
|
if (!elevator) return false;
|
|
|
|
if (targetDepth > elevator.maxDepth) {
|
|
console.log('❌ Depth not unlocked yet');
|
|
return false;
|
|
}
|
|
|
|
// Generate cave if not exists
|
|
let cave = Array.from(this.caves.values()).find(c => c.depth === targetDepth);
|
|
if (!cave) {
|
|
cave = this.generateCave(targetDepth, Date.now());
|
|
}
|
|
|
|
this.currentCave = cave;
|
|
elevator.currentDepth = targetDepth;
|
|
|
|
console.log(`🛗 Descended to depth ${targetDepth}`);
|
|
return true;
|
|
}
|
|
|
|
// ========== MINE CART ==========
|
|
|
|
placeMinecart(x, y) {
|
|
console.log(`🛤️ Placed minecart at (${x}, ${y})`);
|
|
// Minecart for fast transport through tunnels
|
|
}
|
|
|
|
// ========== UPDATE ==========
|
|
|
|
update(delta) {
|
|
// Update cave enemies, etc.
|
|
}
|
|
|
|
// ========== PERSISTENCE ==========
|
|
|
|
saveProgress() {
|
|
const data = {
|
|
caves: Array.from(this.caves.values()).map(c => ({
|
|
id: c.id,
|
|
depth: c.depth,
|
|
explored: c.explored
|
|
})),
|
|
minedOres: this.minedOres.length
|
|
};
|
|
|
|
localStorage.setItem('novafarma_mining', JSON.stringify(data));
|
|
}
|
|
|
|
loadProgress() {
|
|
const saved = localStorage.getItem('novafarma_mining');
|
|
if (saved) {
|
|
try {
|
|
const data = JSON.parse(saved);
|
|
console.log('✅ Mining progress loaded');
|
|
} catch (error) {
|
|
console.error('Failed to load mining progress:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
destroy() {
|
|
this.saveProgress();
|
|
console.log('⛏️ Mining & Dungeons System destroyed');
|
|
}
|
|
}
|