/** * WORKSTATION SYSTEM * Manages processing stations like Furnace, Mint, Campfire. * Handles: Input -> Process Time -> Output */ class WorkstationSystem { constructor(scene) { this.scene = scene; this.stations = new Map(); // Key: "x,y", Value: StationData // Define Recipes this.recipes = { 'furnace': [ { input: 'ore_iron', fuel: 'coal', output: 'iron_bar', time: 5000 }, { input: 'ore_stone', fuel: 'coal', output: 'stone_brick', time: 3000 }, { input: 'sand', fuel: 'coal', output: 'glass', time: 3000 }, { input: 'log', fuel: 'log', output: 'charcoal', time: 4000 } // Wood to charcoal ], 'mint': [ { input: 'iron_bar', fuel: 'coal', output: 'coin_gold', time: 2000, outputCount: 10 } ], 'campfire': [ { input: 'raw_meat', fuel: 'stick', output: 'cooked_meat', time: 3000 } ] }; } /** * Register a new workstation at coordinates */ addStation(x, y, type) { const key = `${x},${y}`; if (this.stations.has(key)) return; this.stations.set(key, { x, y, type, input: null, // { itemId, count } fuel: null, // { itemId, count } output: null, // { itemId, count } isProcessing: false, timer: 0, maxTime: 0, currentRecipe: null }); console.log(`🏭 Created ${type} at ${x},${y}`); } /** * Player interacts with station * (Simple version: Click with item to insert, Click empty to take output) */ interact(x, y, playerItem) { const key = `${x},${y}`; const station = this.stations.get(key); if (!station) return false; // 1. If Output exists, take it (Prioritize taking output) if (station.output) { this.scene.inventorySystem.addItem(station.output.itemId, station.output.count); this.showFloatingText(x, y, `+${station.output.count} ${station.output.itemId}`, '#00FF00'); station.output = null; return true; } // 2. If holding item, try to insert (Input or Fuel) if (playerItem) { // Check if it's Valid Input for this station type const recipe = this.findRecipe(station.type, playerItem.itemId); // Is it Fuel? (Assume 'coal', 'log', 'stick' are fuels) const isFuel = ['coal', 'log', 'stick', 'charcoal'].includes(playerItem.itemId); if (recipe && !station.input) { // Insert Input station.input = { itemId: playerItem.itemId, count: 1 }; this.scene.inventorySystem.removeItem(playerItem.itemId, 1); this.showFloatingText(x, y, `Inserted ${playerItem.itemId}`, '#FFFFFF'); this.tryStartProcess(station); return true; } else if (isFuel && !station.fuel) { // Insert Fuel station.fuel = { itemId: playerItem.itemId, count: 1 }; this.scene.inventorySystem.removeItem(playerItem.itemId, 1); this.showFloatingText(x, y, `Fueled with ${playerItem.itemId}`, '#FFA500'); this.tryStartProcess(station); return true; } } // 3. Status Check if (station.isProcessing) { const progress = Math.floor((station.timer / station.maxTime) * 100); this.showFloatingText(x, y, `Processing... ${progress}%`, '#FFFF00'); } else { this.showFloatingText(x, y, 'Missing Input or Fuel', '#FF0000'); } return true; } findRecipe(stationType, inputItem) { const stationRecipes = this.recipes[stationType]; if (!stationRecipes) return null; return stationRecipes.find(r => r.input === inputItem); } tryStartProcess(station) { if (station.isProcessing) return; if (!station.input || !station.fuel) return; // Find matching recipe const recipe = this.recipes[station.type].find(r => r.input === station.input.itemId && (r.fuel === 'any' || r.fuel === station.fuel.itemId) ); // Specific fuel check can be relaxed later if (recipe) { station.isProcessing = true; station.timer = 0; station.maxTime = recipe.time; station.currentRecipe = recipe; console.log(`🔥 Started processing ${recipe.input} -> ${recipe.output}`); // Visual feedback (Particles?) // this.scene.addParticles... } } update(delta) { for (const station of this.stations.values()) { if (station.isProcessing) { station.timer += delta; // Visual: Float smoke occasionally? if (Math.random() < 0.05) { // emit smoke particle } if (station.timer >= station.maxTime) { // COMPLETE const recipe = station.currentRecipe; const outCount = recipe.outputCount || 1; // Consume inputs // (Actually we keep them in slots until done? Or consume at start? // Let's say inputs are consumed at start visually, but logically here we swap to output) station.output = { itemId: recipe.output, count: outCount }; station.input = null; station.fuel = null; // Consume 1 fuel per operation for now (Simple) station.isProcessing = false; station.timer = 0; station.currentRecipe = null; this.showFloatingText(station.x, station.y, 'DONE!', '#00FF00'); if (this.scene.soundManager) this.scene.soundManager.playSuccess(); // Placeholder sound } } } } showFloatingText(x, y, text, color) { // Convert grid to screen // Assuming interact passes Grid X,Y if (this.scene.events) { const screen = this.scene.iso.toScreen(x, y); this.scene.events.emit('show-floating-text', { x: screen.x + this.scene.terrainOffsetX, y: screen.y + this.scene.terrainOffsetY - 30, text: text, color: color }); } } }