Files
novafarma/src/systems/WorkstationSystem.js
2025-12-08 14:01:41 +01:00

180 lines
6.6 KiB
JavaScript

/**
* 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_gold', fuel: 'coal', output: 'gold_bar', time: 8000 },
{ 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 },
{ input: 'gold_bar', fuel: 'coal', output: 'coin_gold', time: 3000, outputCount: 50 }
],
'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
});
}
}
}