FEATURE: Gem Drop System - Diamond, Emerald, Ruby, Sapphire rare drops with rarity chances + sell values
This commit is contained in:
187
src/systems/GemDropSystem.js
Normal file
187
src/systems/GemDropSystem.js
Normal file
@@ -0,0 +1,187 @@
|
||||
/**
|
||||
* GEM DROP SYSTEM
|
||||
* Handles rare gem drops from enemies, mining, etc.
|
||||
* Gems: Diamond, Emerald, Ruby (high value items for selling)
|
||||
*/
|
||||
|
||||
class GemDropSystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
|
||||
// Gem definitions with rarity and value
|
||||
this.gems = {
|
||||
'diamond': {
|
||||
name: 'Diamond',
|
||||
rarity: 'legendary', // 0.5% drop
|
||||
value: 500, // Sell price in gold
|
||||
icon: '💎'
|
||||
},
|
||||
'emerald': {
|
||||
name: 'Emerald',
|
||||
rarity: 'epic', // 2% drop
|
||||
value: 200,
|
||||
icon: '💚'
|
||||
},
|
||||
'ruby': {
|
||||
name: 'Ruby',
|
||||
rarity: 'rare', // 5% drop
|
||||
value: 100,
|
||||
icon: '❤️'
|
||||
},
|
||||
'sapphire': {
|
||||
name: 'Sapphire',
|
||||
rarity: 'uncommon', // 10% drop
|
||||
value: 50,
|
||||
icon: '💙'
|
||||
}
|
||||
};
|
||||
|
||||
// Drop chance by rarity
|
||||
this.rarityChances = {
|
||||
'legendary': 0.005, // 0.5%
|
||||
'epic': 0.02, // 2%
|
||||
'rare': 0.05, // 5%
|
||||
'uncommon': 0.10 // 10%
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll for gem drop from enemy/resource
|
||||
* @param {string} source - 'zombie', 'elite', 'stone_ore', 'iron_ore'
|
||||
* @param {number} x - Grid X
|
||||
* @param {number} y - Grid Y
|
||||
* @param {number} luckBonus - Player luck modifier (0-1)
|
||||
*/
|
||||
rollGemDrop(source, x, y, luckBonus = 0) {
|
||||
const dropTable = this.getDropTableForSource(source);
|
||||
if (!dropTable || dropTable.length === 0) return;
|
||||
|
||||
// Roll for each possible gem
|
||||
for (const gemEntry of dropTable) {
|
||||
const gemType = gemEntry.gem;
|
||||
const gem = this.gems[gemType];
|
||||
if (!gem) continue;
|
||||
|
||||
const baseChance = this.rarityChances[gem.rarity];
|
||||
const finalChance = baseChance * (1 + luckBonus);
|
||||
|
||||
if (Math.random() < finalChance) {
|
||||
// GEM DROPPED!
|
||||
console.log(`💎 RARE DROP: ${gem.name} from ${source}!`);
|
||||
this.spawnGem(gemType, x, y);
|
||||
|
||||
// Play special sound/effect
|
||||
if (this.scene.particleEffects) {
|
||||
this.scene.particleEffects.gemSparkle(x, y, gem.icon);
|
||||
}
|
||||
if (this.scene.soundManager) {
|
||||
this.scene.soundManager.playRareDrop();
|
||||
}
|
||||
|
||||
// Only drop 1 gem per source
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get drop table based on source
|
||||
*/
|
||||
getDropTableForSource(source) {
|
||||
const tables = {
|
||||
'zombie': [
|
||||
{ gem: 'sapphire', weight: 1 }
|
||||
],
|
||||
'elite_zombie': [
|
||||
{ gem: 'ruby', weight: 2 },
|
||||
{ gem: 'emerald', weight: 1 }
|
||||
],
|
||||
'troll': [
|
||||
{ gem: 'emerald', weight: 2 },
|
||||
{ gem: 'diamond', weight: 0.5 }
|
||||
],
|
||||
'stone_ore': [
|
||||
{ gem: 'sapphire', weight: 1 }
|
||||
],
|
||||
'iron_ore': [
|
||||
{ gem: 'ruby', weight: 1 }
|
||||
],
|
||||
'gold_ore': [
|
||||
{ gem: 'emerald', weight: 1.5 },
|
||||
{ gem: 'diamond', weight: 0.3 }
|
||||
],
|
||||
'boss': [
|
||||
{ gem: 'diamond', weight: 5 } // Guaranteed almost!
|
||||
]
|
||||
};
|
||||
|
||||
return tables[source] || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn gem as loot item
|
||||
*/
|
||||
spawnGem(gemType, gridX, gridY) {
|
||||
if (this.scene.lootSystem) {
|
||||
this.scene.lootSystem.spawnLoot(gridX, gridY, gemType, 1);
|
||||
} else {
|
||||
console.warn('⚠️ LootSystem not found - gem cannot spawn!');
|
||||
}
|
||||
|
||||
// Show floating text
|
||||
const gem = this.gems[gemType];
|
||||
if (this.scene.events) {
|
||||
const screenPos = this.scene.terrainSystem.iso.toScreen(gridX, gridY);
|
||||
this.scene.events.emit('show-floating-text', {
|
||||
x: screenPos.x,
|
||||
y: screenPos.y - 50,
|
||||
text: `${gem.icon} ${gem.name}!`,
|
||||
color: '#ff00ff', // Purple for rare
|
||||
size: '20px'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gem sell value
|
||||
*/
|
||||
getGemValue(gemType) {
|
||||
const gem = this.gems[gemType];
|
||||
return gem ? gem.value : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sell gem to merchant
|
||||
*/
|
||||
sellGem(gemType, amount, playerInventory) {
|
||||
const gem = this.gems[gemType];
|
||||
if (!gem) {
|
||||
console.warn('⚠️ Unknown gem type:', gemType);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if player has gem
|
||||
const hasAmount = playerInventory.getItemCount(gemType);
|
||||
if (hasAmount < amount) {
|
||||
console.warn(`⚠️ Not enough ${gem.name} to sell!`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calculate total value
|
||||
const totalValue = gem.value * amount;
|
||||
|
||||
// Remove from inventory
|
||||
playerInventory.removeItem(gemType, amount);
|
||||
|
||||
// Add gold
|
||||
playerInventory.addItem('gold_coin', totalValue);
|
||||
|
||||
console.log(`💰 Sold ${amount}x ${gem.name} for ${totalValue} gold`);
|
||||
return totalValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Export
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = GemDropSystem;
|
||||
}
|
||||
Reference in New Issue
Block a user