Files
novafarma/EMERGENCY_SYSTEMS_RECOVERY/BiomeEnemySystem.js
2026-01-16 02:43:46 +01:00

275 lines
9.0 KiB
JavaScript

/**
* 👹 BIOME ENEMY SYSTEM
* Spawns biome-specific enemies across the world
* - Different enemies per biome
* - Difficulty scaling
* - Loot drops
* - Combat integration
*/
class BiomeEnemySystem {
constructor(scene) {
this.scene = scene;
// All enemies in the world
this.enemies = [];
// Enemy types per biome
this.enemyTypes = {
'Grassland': [
{ type: 'wolf', hp: 30, damage: 5, speed: 1.5, loot: ['meat', 'fur'], color: 0x8B4513 },
{ type: 'boar', hp: 40, damage: 7, speed: 1.2, loot: ['meat', 'tusk'], color: 0x654321 },
{ type: 'bandit', hp: 50, damage: 10, speed: 1.0, loot: ['gold', 'sword'], color: 0x696969 }
],
'Forest': [
{ type: 'goblin', hp: 25, damage: 6, speed: 1.3, loot: ['gold', 'dagger'], color: 0x228B22 },
{ type: 'spider', hp: 20, damage: 4, speed: 1.8, loot: ['web', 'poison'], color: 0x2F4F4F },
{ type: 'ent', hp: 80, damage: 15, speed: 0.8, loot: ['wood', 'seed'], color: 0x8B4513 }
],
'Desert': [
{ type: 'scorpion', hp: 35, damage: 8, speed: 1.4, loot: ['poison', 'chitin'], color: 0xD2691E },
{ type: 'mummy', hp: 60, damage: 12, speed: 0.9, loot: ['bandage', 'ancient_coin'], color: 0xDEB887 },
{ type: 'sand_worm', hp: 100, damage: 20, speed: 0.7, loot: ['scales', 'tooth'], color: 0xC0B090 }
],
'Mountain': [
{ type: 'troll', hp: 90, damage: 18, speed: 0.8, loot: ['stone', 'club'], color: 0x708090 },
{ type: 'golem', hp: 120, damage: 25, speed: 0.6, loot: ['ore', 'core'], color: 0x696969 },
{ type: 'harpy', hp: 45, damage: 10, speed: 2.0, loot: ['feather', 'talon'], color: 0x9370DB }
],
'Swamp': [
{ type: 'zombie', hp: 50, damage: 10, speed: 0.9, loot: ['bone', 'rotten_flesh'], color: 0x556B2F },
{ type: 'will_o_wisp', hp: 30, damage: 8, speed: 2.5, loot: ['essence', 'spark'], color: 0x00FFFF },
{ type: 'swamp_dragon', hp: 150, damage: 30, speed: 0.7, loot: ['scale', 'heart'], color: 0x2F4F2F }
]
};
// Spawn density per biome
this.spawnDensity = {
'Grassland': 0.02, // 2% per tile
'Forest': 0.03, // 3%
'Desert': 0.015, // 1.5%
'Mountain': 0.025, // 2.5%
'Swamp': 0.035 // 3.5%
};
console.log('👹 BiomeEnemySystem initialized');
}
// Generate enemy spawns across the world
generateSpawns(biomeSystem) {
if (!biomeSystem) return;
let enemiesSpawned = 0;
const sampleRate = 10; // Check every 10th tile
for (let x = 0; x < 500; x += sampleRate) {
for (let y = 0; y < 500; y += sampleRate) {
const biome = biomeSystem.getBiomeAt(x, y);
const density = this.spawnDensity[biome] || 0.02;
if (Math.random() < density) {
this.spawnEnemy(x, y, biome);
enemiesSpawned++;
}
}
}
console.log(`✅ Spawned ${enemiesSpawned} enemies across world`);
}
// Spawn single enemy
spawnEnemy(x, y, biome) {
const enemyList = this.enemyTypes[biome] || this.enemyTypes['Grassland'];
const enemyTemplate = enemyList[Math.floor(Math.random() * enemyList.length)];
const enemy = {
x,
y,
type: enemyTemplate.type,
biome,
hp: enemyTemplate.hp,
maxHp: enemyTemplate.hp,
damage: enemyTemplate.damage,
speed: enemyTemplate.speed,
loot: [...enemyTemplate.loot],
color: enemyTemplate.color,
alive: true,
sprite: null,
lastMoveTime: 0
};
this.enemies.push(enemy);
return enemy;
}
// Create enemy sprite when chunk loads
createEnemySprite(enemy, chunk) {
if (enemy.sprite || !enemy.alive) return;
const worldX = enemy.x * 48 + 24;
const worldY = enemy.y * 48 + 24;
// Simple circle sprite
const sprite = this.scene.add.circle(worldX, worldY, 15, enemy.color);
sprite.setDepth(10 + worldY);
// HP bar
const hpBar = this.scene.add.rectangle(worldX, worldY - 25, 30, 4, 0xFF0000);
hpBar.setOrigin(0, 0.5);
hpBar.setDepth(10 + worldY);
const hpFill = this.scene.add.rectangle(worldX, worldY - 25, 30, 4, 0x00FF00);
hpFill.setOrigin(0, 0.5);
hpFill.setDepth(10 + worldY);
enemy.sprite = sprite;
enemy.hpBar = hpBar;
enemy.hpFill = hpFill;
if (chunk) {
chunk.sprites.push(sprite);
chunk.sprites.push(hpBar);
chunk.sprites.push(hpFill);
}
}
// Update enemies (AI, movement)
update(time, delta, playerX, playerY) {
for (const enemy of this.enemies) {
if (!enemy.alive || !enemy.sprite) continue;
// Simple AI: Move towards player if nearby
const dist = Math.sqrt((enemy.x - playerX) ** 2 + (enemy.y - playerY) ** 2);
if (dist < 10 && time > enemy.lastMoveTime + 500) {
// Move towards player
const dx = playerX - enemy.x;
const dy = playerY - enemy.y;
const len = Math.sqrt(dx * dx + dy * dy);
if (len > 0) {
enemy.x += (dx / len) * enemy.speed * 0.1;
enemy.y += (dy / len) * enemy.speed * 0.1;
// Update sprite position
enemy.sprite.setPosition(enemy.x * 48 + 24, enemy.y * 48 + 24);
if (enemy.hpBar) {
enemy.hpBar.setPosition(enemy.x * 48 + 24, enemy.y * 48 - 1);
enemy.hpFill.setPosition(enemy.x * 48 + 24, enemy.y * 48 - 1);
}
}
enemy.lastMoveTime = time;
}
// Attack player if very close
if (dist < 1.5 && time > enemy.lastAttackTime + 2000) {
this.attackPlayer(enemy);
enemy.lastAttackTime = time;
}
}
}
// Enemy attacks player
attackPlayer(enemy) {
if (this.scene.player) {
console.log(`👹 ${enemy.type} attacks for ${enemy.damage} damage!`);
// TODO: Integrate with player health system
// Visual feedback
if (this.scene.cameras) {
this.scene.cameras.main.shake(200, 0.005);
}
}
}
// Player attacks enemy
damageEnemy(enemy, damage) {
if (!enemy.alive) return;
enemy.hp -= damage;
// Update HP bar
if (enemy.hpFill) {
const hpPercent = Math.max(0, enemy.hp / enemy.maxHp);
enemy.hpFill.setScale(hpPercent, 1);
}
console.log(`⚔️ ${enemy.type} takes ${damage} damage! (${enemy.hp}/${enemy.maxHp} HP)`);
// Death
if (enemy.hp <= 0) {
this.killEnemy(enemy);
}
}
// Kill enemy and drop loot
killEnemy(enemy) {
enemy.alive = false;
console.log(`💀 ${enemy.type} died!`);
// Drop loot
if (this.scene.inventorySystem && enemy.loot.length > 0) {
const lootItem = enemy.loot[Math.floor(Math.random() * enemy.loot.length)];
const amount = Math.floor(Math.random() * 3) + 1;
this.scene.inventorySystem.addItem(lootItem, amount);
console.log(` 💰 Dropped: ${amount}x ${lootItem}`);
}
// Destroy sprite
if (enemy.sprite) {
enemy.sprite.destroy();
if (enemy.hpBar) enemy.hpBar.destroy();
if (enemy.hpFill) enemy.hpFill.destroy();
enemy.sprite = null;
}
}
// Find nearest enemy to point
findNearestEnemy(x, y, maxDistance = 2) {
let nearest = null;
let minDist = maxDistance;
for (const enemy of this.enemies) {
if (!enemy.alive) continue;
const dist = Math.sqrt((enemy.x - x) ** 2 + (enemy.y - y) ** 2);
if (dist < minDist) {
minDist = dist;
nearest = enemy;
}
}
return nearest;
}
// Get statistics
getStats() {
const alive = this.enemies.filter(e => e.alive).length;
const byBiome = {};
for (const enemy of this.enemies) {
if (!enemy.alive) continue;
byBiome[enemy.biome] = (byBiome[enemy.biome] || 0) + 1;
}
return {
totalEnemies: this.enemies.length,
alive,
dead: this.enemies.length - alive,
byBiome
};
}
destroy() {
this.enemies.forEach(enemy => {
if (enemy.sprite) enemy.sprite.destroy();
if (enemy.hpBar) enemy.hpBar.destroy();
if (enemy.hpFill) enemy.hpFill.destroy();
});
this.enemies = [];
}
}