126 lines
4.1 KiB
JavaScript
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()
|
|
});
|
|
}
|
|
}
|