564 lines
16 KiB
JavaScript
564 lines
16 KiB
JavaScript
/**
|
|
* FARM AUTOMATION SYSTEM
|
|
* Complete automation with zombie workers, creature helpers, buildings, and power grid
|
|
*/
|
|
class FarmAutomationSystem {
|
|
constructor(scene) {
|
|
this.scene = scene;
|
|
this.enabled = true;
|
|
|
|
// Workers
|
|
this.zombieWorkers = [];
|
|
this.creatureWorkers = [];
|
|
this.taskQueue = [];
|
|
|
|
// Buildings
|
|
this.automationBuildings = new Map();
|
|
this.powerGrid = new Map();
|
|
|
|
// Power system
|
|
this.totalPower = 0;
|
|
this.powerConsumption = 0;
|
|
|
|
// Settings
|
|
this.settings = {
|
|
maxZombieWorkers: 10,
|
|
maxCreatureWorkers: 5,
|
|
zombieEfficiency: 0.7, // 70% of player speed
|
|
powerUpdateInterval: 1000 // ms
|
|
};
|
|
|
|
this.loadProgress();
|
|
this.init();
|
|
|
|
console.log('✅ Farm Automation System initialized');
|
|
}
|
|
|
|
init() {
|
|
// Start power update loop
|
|
this.startPowerUpdate();
|
|
console.log('🤖 Farm automation ready');
|
|
}
|
|
|
|
// ========== ZOMBIE WORKER SYSTEM ==========
|
|
|
|
hireZombieWorker(name = 'Zombie') {
|
|
if (this.zombieWorkers.length >= this.settings.maxZombieWorkers) {
|
|
console.log('❌ Max zombie workers reached');
|
|
return null;
|
|
}
|
|
|
|
const worker = {
|
|
id: `zombie_${Date.now()}`,
|
|
name,
|
|
type: 'zombie',
|
|
level: 1,
|
|
xp: 0,
|
|
efficiency: this.settings.zombieEfficiency,
|
|
currentTask: null,
|
|
position: { x: 0, y: 0 },
|
|
hunger: 100,
|
|
fatigue: 0,
|
|
sprite: null
|
|
};
|
|
|
|
this.zombieWorkers.push(worker);
|
|
this.saveProgress();
|
|
console.log(`🧟 Hired zombie worker: ${name}`);
|
|
return worker;
|
|
}
|
|
|
|
assignTask(worker, task) {
|
|
if (!worker) return false;
|
|
|
|
worker.currentTask = {
|
|
type: task.type, // 'plant', 'harvest', 'water'
|
|
target: task.target,
|
|
priority: task.priority || 1,
|
|
startTime: Date.now()
|
|
};
|
|
|
|
console.log(`📋 ${worker.name} assigned to ${task.type}`);
|
|
return true;
|
|
}
|
|
|
|
addToTaskQueue(task) {
|
|
this.taskQueue.push({
|
|
...task,
|
|
id: `task_${Date.now()}`,
|
|
status: 'pending'
|
|
});
|
|
|
|
// Assign to available worker
|
|
this.assignNextTask();
|
|
}
|
|
|
|
assignNextTask() {
|
|
// Find idle worker
|
|
const idleWorker = [...this.zombieWorkers, ...this.creatureWorkers]
|
|
.find(w => !w.currentTask);
|
|
|
|
if (!idleWorker || this.taskQueue.length === 0) return;
|
|
|
|
// Get highest priority task
|
|
this.taskQueue.sort((a, b) => b.priority - a.priority);
|
|
const task = this.taskQueue.shift();
|
|
|
|
this.assignTask(idleWorker, task);
|
|
}
|
|
|
|
completeTask(worker) {
|
|
if (!worker || !worker.currentTask) return;
|
|
|
|
const task = worker.currentTask;
|
|
|
|
// Give XP
|
|
this.addWorkerXP(worker, 10);
|
|
|
|
// Increase fatigue
|
|
worker.fatigue += 10;
|
|
|
|
// Clear task
|
|
worker.currentTask = null;
|
|
|
|
// Assign next task
|
|
this.assignNextTask();
|
|
|
|
console.log(`✅ ${worker.name} completed ${task.type}`);
|
|
}
|
|
|
|
addWorkerXP(worker, amount) {
|
|
worker.xp += amount;
|
|
|
|
// Level up check
|
|
const xpNeeded = worker.level * 100;
|
|
if (worker.xp >= xpNeeded) {
|
|
worker.level++;
|
|
worker.xp = 0;
|
|
worker.efficiency += 0.05; // 5% faster per level
|
|
console.log(`⬆️ ${worker.name} leveled up to ${worker.level}!`);
|
|
}
|
|
|
|
this.saveProgress();
|
|
}
|
|
|
|
// ========== CREATURE WORKER SYSTEM ==========
|
|
|
|
tameCreature(creatureType, name) {
|
|
if (this.creatureWorkers.length >= this.settings.maxCreatureWorkers) {
|
|
console.log('❌ Max creature workers reached');
|
|
return null;
|
|
}
|
|
|
|
const specialties = {
|
|
donkey: { specialty: 'transport', efficiency: 1.0 },
|
|
bigfoot: { specialty: 'gathering', efficiency: 1.2 },
|
|
yeti: { specialty: 'snow_tasks', efficiency: 1.1 },
|
|
elf: { specialty: 'crafting', efficiency: 1.3 }
|
|
};
|
|
|
|
const data = specialties[creatureType] || { specialty: 'general', efficiency: 0.8 };
|
|
|
|
const worker = {
|
|
id: `creature_${Date.now()}`,
|
|
name,
|
|
type: creatureType,
|
|
specialty: data.specialty,
|
|
level: 1,
|
|
xp: 0,
|
|
efficiency: data.efficiency,
|
|
currentTask: null,
|
|
position: { x: 0, y: 0 },
|
|
hunger: 100,
|
|
fatigue: 0,
|
|
sprite: null
|
|
};
|
|
|
|
this.creatureWorkers.push(worker);
|
|
this.saveProgress();
|
|
console.log(`🦌 Tamed ${creatureType}: ${name} (${data.specialty})`);
|
|
return worker;
|
|
}
|
|
|
|
// ========== AUTOMATION BUILDINGS ==========
|
|
|
|
buildAutomation(type, x, y) {
|
|
const buildings = {
|
|
'auto_planter': {
|
|
name: 'Auto-Planter',
|
|
powerCost: 10,
|
|
range: 3,
|
|
speed: 2000 // ms per action
|
|
},
|
|
'auto_harvester': {
|
|
name: 'Auto-Harvester',
|
|
powerCost: 15,
|
|
range: 5,
|
|
speed: 1500
|
|
},
|
|
'irrigation': {
|
|
name: 'Irrigation System',
|
|
powerCost: 5,
|
|
range: 10,
|
|
speed: 3000
|
|
},
|
|
'conveyor': {
|
|
name: 'Conveyor Belt',
|
|
powerCost: 3,
|
|
range: 1,
|
|
speed: 500
|
|
},
|
|
'silo': {
|
|
name: 'Storage Silo',
|
|
powerCost: 2,
|
|
capacity: 1000
|
|
},
|
|
'sorter': {
|
|
name: 'Sorting Machine',
|
|
powerCost: 8,
|
|
speed: 1000
|
|
}
|
|
};
|
|
|
|
const buildingData = buildings[type];
|
|
if (!buildingData) return null;
|
|
|
|
const building = {
|
|
id: `${type}_${x}_${y}`,
|
|
type,
|
|
x, y,
|
|
...buildingData,
|
|
active: false,
|
|
lastAction: 0
|
|
};
|
|
|
|
this.automationBuildings.set(building.id, building);
|
|
this.updatePowerConsumption();
|
|
this.saveProgress();
|
|
|
|
console.log(`🏭 Built ${buildingData.name} at (${x}, ${y})`);
|
|
return building;
|
|
}
|
|
|
|
activateBuilding(buildingId) {
|
|
const building = this.automationBuildings.get(buildingId);
|
|
if (!building) return false;
|
|
|
|
// Check power
|
|
if (this.totalPower < this.powerConsumption + building.powerCost) {
|
|
console.log('❌ Not enough power!');
|
|
return false;
|
|
}
|
|
|
|
building.active = true;
|
|
this.updatePowerConsumption();
|
|
console.log(`⚡ Activated ${building.name}`);
|
|
return true;
|
|
}
|
|
|
|
deactivateBuilding(buildingId) {
|
|
const building = this.automationBuildings.get(buildingId);
|
|
if (!building) return false;
|
|
|
|
building.active = false;
|
|
this.updatePowerConsumption();
|
|
console.log(`🔌 Deactivated ${building.name}`);
|
|
return true;
|
|
}
|
|
|
|
// ========== POWER SYSTEM ==========
|
|
|
|
buildPowerSource(type, x, y) {
|
|
const sources = {
|
|
'windmill': { name: 'Windmill', power: 20, cost: { wood: 10, iron: 5 } },
|
|
'water_wheel': { name: 'Water Wheel', power: 15, cost: { wood: 8, iron: 3 } },
|
|
'solar_panel': { name: 'Solar Panel', power: 25, cost: { iron: 10, glass: 5 } },
|
|
'zombie_treadmill': { name: 'Zombie Treadmill', power: 10, cost: { wood: 5 } }
|
|
};
|
|
|
|
const sourceData = sources[type];
|
|
if (!sourceData) return null;
|
|
|
|
const source = {
|
|
id: `${type}_${x}_${y}`,
|
|
type,
|
|
x, y,
|
|
...sourceData,
|
|
active: true,
|
|
currentPower: sourceData.power
|
|
};
|
|
|
|
this.powerGrid.set(source.id, source);
|
|
this.updateTotalPower();
|
|
this.saveProgress();
|
|
|
|
console.log(`⚡ Built ${sourceData.name} (+${sourceData.power} power)`);
|
|
return source;
|
|
}
|
|
|
|
updateTotalPower() {
|
|
this.totalPower = 0;
|
|
|
|
for (const source of this.powerGrid.values()) {
|
|
if (source.active) {
|
|
// Solar panels only work during day
|
|
if (source.type === 'solar_panel') {
|
|
const time = this.scene.weatherSystem?.gameTime || 12;
|
|
if (time >= 6 && time <= 18) {
|
|
this.totalPower += source.currentPower;
|
|
}
|
|
} else {
|
|
this.totalPower += source.currentPower;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
updatePowerConsumption() {
|
|
this.powerConsumption = 0;
|
|
|
|
for (const building of this.automationBuildings.values()) {
|
|
if (building.active) {
|
|
this.powerConsumption += building.powerCost;
|
|
}
|
|
}
|
|
}
|
|
|
|
startPowerUpdate() {
|
|
setInterval(() => {
|
|
this.updateTotalPower();
|
|
this.updatePowerConsumption();
|
|
|
|
// Deactivate buildings if not enough power
|
|
if (this.powerConsumption > this.totalPower) {
|
|
this.handlePowerShortage();
|
|
}
|
|
}, this.settings.powerUpdateInterval);
|
|
}
|
|
|
|
handlePowerShortage() {
|
|
console.log('⚠️ Power shortage! Deactivating low-priority buildings...');
|
|
|
|
// Deactivate buildings until power is sufficient
|
|
for (const building of this.automationBuildings.values()) {
|
|
if (building.active && this.powerConsumption > this.totalPower) {
|
|
this.deactivateBuilding(building.id);
|
|
}
|
|
}
|
|
}
|
|
|
|
getPowerStatus() {
|
|
return {
|
|
total: this.totalPower,
|
|
consumption: this.powerConsumption,
|
|
available: this.totalPower - this.powerConsumption,
|
|
percentage: (this.powerConsumption / this.totalPower) * 100
|
|
};
|
|
}
|
|
|
|
// ========== WORKER MANAGEMENT ==========
|
|
|
|
updateWorkers(delta) {
|
|
// Update zombie workers
|
|
for (const worker of this.zombieWorkers) {
|
|
this.updateWorker(worker, delta);
|
|
}
|
|
|
|
// Update creature workers
|
|
for (const worker of this.creatureWorkers) {
|
|
this.updateWorker(worker, delta);
|
|
}
|
|
}
|
|
|
|
updateWorker(worker, delta) {
|
|
// Decrease hunger over time
|
|
worker.hunger -= delta / 60000; // 1% per minute
|
|
|
|
// Increase fatigue if working
|
|
if (worker.currentTask) {
|
|
worker.fatigue += delta / 30000; // 1% per 30 seconds
|
|
|
|
// Complete task if enough time passed
|
|
const taskDuration = 5000 / worker.efficiency; // Base 5 seconds
|
|
if (Date.now() - worker.currentTask.startTime > taskDuration) {
|
|
this.completeTask(worker);
|
|
}
|
|
} else {
|
|
// Recover fatigue when idle
|
|
worker.fatigue -= delta / 60000;
|
|
}
|
|
|
|
// Clamp values
|
|
worker.hunger = Math.max(0, Math.min(100, worker.hunger));
|
|
worker.fatigue = Math.max(0, Math.min(100, worker.fatigue));
|
|
|
|
// Worker needs rest
|
|
if (worker.fatigue > 80) {
|
|
worker.currentTask = null;
|
|
console.log(`😴 ${worker.name} is too tired to work`);
|
|
}
|
|
|
|
// Worker needs food
|
|
if (worker.hunger < 20) {
|
|
worker.efficiency *= 0.5; // 50% slower when hungry
|
|
}
|
|
}
|
|
|
|
feedWorker(worker, food) {
|
|
if (!worker) return false;
|
|
|
|
worker.hunger = Math.min(100, worker.hunger + 30);
|
|
console.log(`🍖 Fed ${worker.name}`);
|
|
return true;
|
|
}
|
|
|
|
restWorker(worker) {
|
|
if (!worker) return false;
|
|
|
|
worker.currentTask = null;
|
|
worker.fatigue = Math.max(0, worker.fatigue - 50);
|
|
console.log(`😴 ${worker.name} is resting`);
|
|
return true;
|
|
}
|
|
|
|
upgradeWorkerTools(worker, toolTier) {
|
|
if (!worker) return false;
|
|
|
|
const tierBonus = {
|
|
'bronze': 0.1,
|
|
'iron': 0.2,
|
|
'steel': 0.3,
|
|
'enchanted': 0.5
|
|
};
|
|
|
|
const bonus = tierBonus[toolTier] || 0;
|
|
worker.efficiency += bonus;
|
|
|
|
console.log(`⚒️ ${worker.name} upgraded to ${toolTier} tools (+${bonus * 100}% efficiency)`);
|
|
return true;
|
|
}
|
|
|
|
// ========== AUTOMATION UPDATE ==========
|
|
|
|
updateAutomation(delta) {
|
|
const now = Date.now();
|
|
|
|
for (const building of this.automationBuildings.values()) {
|
|
if (!building.active) continue;
|
|
|
|
// Check if enough time passed
|
|
if (now - building.lastAction < building.speed) continue;
|
|
|
|
// Perform building action
|
|
switch (building.type) {
|
|
case 'auto_planter':
|
|
this.autoPlant(building);
|
|
break;
|
|
case 'auto_harvester':
|
|
this.autoHarvest(building);
|
|
break;
|
|
case 'irrigation':
|
|
this.autoWater(building);
|
|
break;
|
|
case 'conveyor':
|
|
this.moveItems(building);
|
|
break;
|
|
case 'sorter':
|
|
this.sortItems(building);
|
|
break;
|
|
}
|
|
|
|
building.lastAction = now;
|
|
}
|
|
}
|
|
|
|
autoPlant(building) {
|
|
// Plant crops in range
|
|
console.log(`🌱 Auto-planter working at (${building.x}, ${building.y})`);
|
|
}
|
|
|
|
autoHarvest(building) {
|
|
// Harvest crops in range
|
|
console.log(`🌾 Auto-harvester working at (${building.x}, ${building.y})`);
|
|
}
|
|
|
|
autoWater(building) {
|
|
// Water crops in range
|
|
console.log(`💧 Irrigation system working at (${building.x}, ${building.y})`);
|
|
}
|
|
|
|
moveItems(building) {
|
|
// Move items along conveyor
|
|
console.log(`📦 Conveyor moving items at (${building.x}, ${building.y})`);
|
|
}
|
|
|
|
sortItems(building) {
|
|
// Sort items in storage
|
|
console.log(`🔀 Sorter organizing items at (${building.x}, ${building.y})`);
|
|
}
|
|
|
|
// ========== UPDATE ==========
|
|
|
|
update(delta) {
|
|
this.updateWorkers(delta);
|
|
this.updateAutomation(delta);
|
|
}
|
|
|
|
// ========== PERSISTENCE ==========
|
|
|
|
saveProgress() {
|
|
const data = {
|
|
zombieWorkers: this.zombieWorkers.map(w => ({
|
|
id: w.id,
|
|
name: w.name,
|
|
level: w.level,
|
|
xp: w.xp,
|
|
efficiency: w.efficiency
|
|
})),
|
|
creatureWorkers: this.creatureWorkers.map(w => ({
|
|
id: w.id,
|
|
name: w.name,
|
|
type: w.type,
|
|
level: w.level,
|
|
xp: w.xp
|
|
})),
|
|
buildings: Array.from(this.automationBuildings.values()).map(b => ({
|
|
id: b.id,
|
|
type: b.type,
|
|
x: b.x,
|
|
y: b.y,
|
|
active: b.active
|
|
})),
|
|
powerSources: Array.from(this.powerGrid.values()).map(p => ({
|
|
id: p.id,
|
|
type: p.type,
|
|
x: p.x,
|
|
y: p.y
|
|
}))
|
|
};
|
|
|
|
localStorage.setItem('novafarma_farm_automation', JSON.stringify(data));
|
|
}
|
|
|
|
loadProgress() {
|
|
const saved = localStorage.getItem('novafarma_farm_automation');
|
|
if (saved) {
|
|
try {
|
|
const data = JSON.parse(saved);
|
|
|
|
// Restore workers (basic data only, full restoration in init)
|
|
this.savedData = data;
|
|
|
|
console.log('✅ Farm automation progress loaded');
|
|
} catch (error) {
|
|
console.error('Failed to load farm automation:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
destroy() {
|
|
this.saveProgress();
|
|
console.log('🤖 Farm Automation System destroyed');
|
|
}
|
|
}
|