FEATURE: Starter Chest System - seed-based random loot for new game (guaranteed + rare items)
This commit is contained in:
@@ -105,6 +105,7 @@
|
|||||||
<script src="src/systems/PerennialCropSystem.js"></script>
|
<script src="src/systems/PerennialCropSystem.js"></script>
|
||||||
<script src="src/systems/MountSystem.js"></script>
|
<script src="src/systems/MountSystem.js"></script>
|
||||||
<script src="src/systems/SteamIntegrationSystem.js"></script>
|
<script src="src/systems/SteamIntegrationSystem.js"></script>
|
||||||
|
<script src="src/systems/StarterChestSystem.js"></script>
|
||||||
|
|
||||||
<!-- Multiplayer -->
|
<!-- Multiplayer -->
|
||||||
<!-- <script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script> -->
|
<!-- <script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script> -->
|
||||||
|
|||||||
128
src/systems/StarterChestSystem.js
Normal file
128
src/systems/StarterChestSystem.js
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/**
|
||||||
|
* Starter Chest System
|
||||||
|
* Generates seed-based random loot for new game
|
||||||
|
*/
|
||||||
|
|
||||||
|
class StarterChestSystem {
|
||||||
|
constructor(scene) {
|
||||||
|
this.scene = scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate seed-based random loot table
|
||||||
|
* @param {number} seed - Game seed (e.g., Date.now())
|
||||||
|
* @returns {Array} List of items {type, amount}
|
||||||
|
*/
|
||||||
|
generateLoot(seed = Date.now()) {
|
||||||
|
// Simple seeded random generator (LCG)
|
||||||
|
let rng = seed;
|
||||||
|
const random = () => {
|
||||||
|
rng = (rng * 9301 + 49297) % 233280;
|
||||||
|
return rng / 233280;
|
||||||
|
};
|
||||||
|
|
||||||
|
const lootTable = [];
|
||||||
|
|
||||||
|
// GUARANTEED ITEMS (always spawn)
|
||||||
|
lootTable.push({ type: 'wheat_seed', amount: 10 + Math.floor(random() * 10) }); // 10-20 seeds
|
||||||
|
lootTable.push({ type: 'wood', amount: 5 + Math.floor(random() * 10) }); // 5-15 wood
|
||||||
|
|
||||||
|
// RANDOM ITEMS (50% chance each)
|
||||||
|
if (random() > 0.5) {
|
||||||
|
lootTable.push({ type: 'stone', amount: 3 + Math.floor(random() * 5) }); // 3-8 stone
|
||||||
|
}
|
||||||
|
if (random() > 0.5) {
|
||||||
|
lootTable.push({ type: 'bone', amount: 2 + Math.floor(random() * 4) }); // 2-6 bones
|
||||||
|
}
|
||||||
|
if (random() > 0.7) {
|
||||||
|
lootTable.push({ type: 'bread', amount: 1 + Math.floor(random() * 3) }); // 1-4 bread (food)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RARE ITEMS (10% chance each)
|
||||||
|
if (random() > 0.9) {
|
||||||
|
lootTable.push({ type: 'iron', amount: 1 + Math.floor(random() * 2) }); // 1-3 iron
|
||||||
|
}
|
||||||
|
if (random() > 0.9) {
|
||||||
|
lootTable.push({ type: 'gold_coin', amount: 10 + Math.floor(random() * 20) }); // 10-30 gold
|
||||||
|
}
|
||||||
|
|
||||||
|
// ULTRA RARE (1% chance)
|
||||||
|
if (random() > 0.99) {
|
||||||
|
lootTable.push({ type: 'diamond', amount: 1 }); // 1 diamond!
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🎁 Starter Chest Loot Generated:', lootTable);
|
||||||
|
return lootTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Place starter chest at farm location
|
||||||
|
* @param {number} x - Grid X position
|
||||||
|
* @param {number} y - Grid Y position
|
||||||
|
* @param {number} seed - Game seed
|
||||||
|
*/
|
||||||
|
placeStarterChest(x, y, seed) {
|
||||||
|
// Generate loot
|
||||||
|
const lootItems = this.generateLoot(seed);
|
||||||
|
|
||||||
|
// Place chest structure (if TerrainSystem supports it)
|
||||||
|
if (this.scene.terrainSystem && this.scene.terrainSystem.placeStructure) {
|
||||||
|
// Check if placeStructure method exists
|
||||||
|
try {
|
||||||
|
this.scene.terrainSystem.placeStructure(x, y, 'chest');
|
||||||
|
console.log(`🎁 Starter Chest placed at (${x}, ${y})`);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('⚠️ placeStructure not available, chest not placed:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store loot data globally for later retrieval
|
||||||
|
if (!window.gameState) window.gameState = {};
|
||||||
|
window.gameState.starterChestLoot = lootItems;
|
||||||
|
window.gameState.starterChestPosition = { x, y };
|
||||||
|
|
||||||
|
return lootItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open chest and add items to player inventory
|
||||||
|
* @param {Object} player - Player object with inventory
|
||||||
|
*/
|
||||||
|
openChest(player) {
|
||||||
|
if (!window.gameState || !window.gameState.starterChestLoot) {
|
||||||
|
console.warn('⚠️ No starter chest loot found!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const loot = window.gameState.starterChestLoot;
|
||||||
|
|
||||||
|
// Add items to player inventory
|
||||||
|
loot.forEach(item => {
|
||||||
|
if (player.inventory && player.inventory.addItem) {
|
||||||
|
player.inventory.addItem(item.type, item.amount);
|
||||||
|
console.log(`➕ Added ${item.amount}x ${item.type} to inventory`);
|
||||||
|
} else {
|
||||||
|
console.warn('⚠️ Player inventory not available');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show notification
|
||||||
|
if (this.scene.events) {
|
||||||
|
this.scene.events.emit('showFloatingText', {
|
||||||
|
x: window.gameState.starterChestPosition.x,
|
||||||
|
y: window.gameState.starterChestPosition.y,
|
||||||
|
text: '🎁 Starter Chest Opened!',
|
||||||
|
color: '#ffaa00'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear loot (chest is now empty)
|
||||||
|
window.gameState.starterChestLoot = null;
|
||||||
|
console.log('✅ Starter Chest opened and emptied');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export for global use
|
||||||
|
if (typeof module !== 'undefined' && module.exports) {
|
||||||
|
module.exports = StarterChestSystem;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user