Files
novafarma/src/systems/LootSystem.js

126 lines
4.1 KiB
JavaScript

class LootSystem {
constructor(scene) {
this.scene = scene;
this.drops = []; // Active loot drops
this.iso = scene.terrainSystem ? scene.terrainSystem.iso : null; // Reference to IsoUtils
// Settings
this.pickupRadius = 1.0; // Grid based
this.magnetRadius = 3.0; // Optional: fly towards player
}
spawnLoot(gridX, gridY, type, count = 1) {
if (!this.iso && this.scene.terrainSystem) this.iso = this.scene.terrainSystem.iso;
if (!this.iso) return; // Safety check
console.log(`🎁 Spawning ${count}x ${type} at ${gridX},${gridY}`);
const screenPos = this.iso.toScreen(gridX, gridY);
const x = screenPos.x + (this.scene.terrainOffsetX || 0);
const y = screenPos.y + (this.scene.terrainOffsetY || 0);
// Visual Symbol Mapping
let symbol = '?';
const symbols = {
'wood': '🪵', 'stone': '🪨', 'seeds': '🌱', 'wheat': '🌾',
'axe': '🪓', 'pickaxe': '⛏️', 'sword': '⚔️', 'hoe': '🚜',
'item_bone': '🦴', 'flower': '🌸',
'diamond': '💎', 'emerald': '💚', 'ruby': '❤️', // GEMS!
'gold_coin': '🪙', 'iron': '⚙️'
};
if (symbols[type]) symbol = symbols[type];
// Create Sprite/Text
// Using Text for now as it supports emojis easily, but could be Sprite
const drop = this.scene.add.text(x, y - 20, symbol, { fontSize: '20px' });
drop.setOrigin(0.5);
drop.setDepth(this.iso.getDepth(gridX, gridY) + 500);
// Animation (Bobbing)
this.scene.tweens.add({
targets: drop,
y: y - 40,
duration: 600,
yoyo: true,
ease: 'Sine.easeInOut',
repeat: -1
});
// Add to list
this.drops.push({
gridX, gridY,
x, y,
sprite: drop,
type: type,
count: count,
spawnTime: Date.now()
});
}
update() {
if (!this.scene.player) return;
const playerPos = this.scene.player.getPosition();
// Loop backwards to allow removal
for (let i = this.drops.length - 1; i >= 0; i--) {
const drop = this.drops[i];
// Distance Check
const dist = Math.abs(drop.gridX - playerPos.x) + Math.abs(drop.gridY - playerPos.y); // Manhattan-ish
// Pickup Logic
if (dist < 0.8) {
this.collectLoot(drop, i);
}
// Magnet Logic (Visual fly to player) - Optional
else if (dist < 3.0) {
// Move visual slightly towards player?
// Implementing full physics/velocity might be overkill for now.
}
}
}
collectLoot(drop, index) {
if (this.scene.inventorySystem) {
const leftover = this.scene.inventorySystem.addItem(drop.type, drop.count);
if (leftover === 0) {
// Success - Play Sound
if (this.scene.soundManager) {
this.scene.soundManager.playPickup();
}
// Sparkle Effect
if (this.scene.particleEffects) {
this.scene.particleEffects.sparkle(drop.x, drop.y);
}
// Float text effect
this.showFloatingText(`+${drop.count} ${drop.type}`, drop.x, drop.y);
// Remove
drop.sprite.destroy();
this.drops.splice(index, 1);
} else {
// Config full? Update count?
drop.count = leftover;
}
}
}
showFloatingText(text, x, y) {
const txt = this.scene.add.text(x, y - 50, text, {
fontSize: '14px', fill: '#ffff00', stroke: '#000', strokeThickness: 2
}).setOrigin(0.5).setDepth(20000);
this.scene.tweens.add({
targets: txt,
y: y - 100,
alpha: 0,
duration: 800,
onComplete: () => txt.destroy()
});
}
}