180 lines
6.6 KiB
JavaScript
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
|
|
});
|
|
}
|
|
}
|
|
}
|