Files
novafarma/src/systems/TownRestorationLogic.js

475 lines
15 KiB
JavaScript

/**
* TOWN RESTORATION LOGIC SYSTEM
* Complete logic for restoring buildings in Mrtva Dolina
* Handles material requirements, construction progress, worker assignments, NPC unlocks
*/
export class TownRestorationLogic {
constructor(scene) {
this.scene = scene;
// Building states
this.buildings = new Map(); //buildingId → buildingData
// Construction queues
this.activeConstructions = [];
// Worker management
this.assignedWorkers = new Map(); // buildingId → [workerIds]
// NPC unlock tracking
this.unlockedNPCs = new Set();
this.init();
}
init() {
this.initializeBuildingDatabase();
}
/**
* Initialize all 14 buildings with restoration data
*/
initializeBuildingDatabase() {
const buildingSpecs = [
{
id: 'hospital',
name: 'Hospital',
npcUnlock: 'Ana', // Doctor Ana unlocked
materials: {
wood: 150,
stone: 100,
metal: 50,
tools: 20
},
constructionTime: 3600, // 1 hour
stages: 3,
benefits: ['healing', 'medical_supplies']
},
{
id: 'police',
name: 'Police Station',
npcUnlock: null,
materials: {
wood: 100,
stone: 150,
metal: 80,
weapons: 10
},
constructionTime: 3600,
stages: 3,
benefits: ['security', 'patrol_unlock']
},
{
id: 'mayor_office',
name: "Mayor's Office",
npcUnlock: 'Župan', // Mayor unlocked
materials: {
wood: 120,
stone: 80,
metal: 40,
papers: 50
},
constructionTime: 2400,
stages: 3,
benefits: ['election_unlock', 'city_management']
},
{
id: 'tech_workshop',
name: 'Tech Workshop',
npcUnlock: 'Tehnik', // Technician unlocked
materials: {
wood: 80,
stone: 60,
metal: 150,
electronics: 30
},
constructionTime: 3000,
stages: 3,
benefits: ['tech_upgrades', 'electronics_crafting']
},
{
id: 'tailor',
name: 'Tailor Shop',
npcUnlock: 'Šivilja', // Seamstress unlocked
materials: {
wood: 60,
fabric: 100,
thread: 50,
tools: 15
},
constructionTime: 1800,
stages: 3,
benefits: ['armor_crafting', 'clothing_upgrades']
},
{
id: 'museum',
name: 'Museum',
npcUnlock: 'Kustos', // Curator unlocked
materials: {
wood: 100,
stone: 120,
glass: 40,
artifacts: 10
},
constructionTime: 4800, // 80 minutes - complex restoration
stages: 3,
benefits: ['lore_unlock', 'artifact_collection']
},
{
id: 'school',
name: 'School',
npcUnlock: 'Teacher', // Teacher unlocked
materials: {
wood: 90,
stone: 70,
books: 50,
tools: 20
},
constructionTime: 3600,
stages: 3,
benefits: ['buff_unlock', 'education_system']
},
{
id: 'church',
name: 'Church',
npcUnlock: 'Župnik', // Priest unlocked
materials: {
wood: 80,
stone: 200,
metal: 30,
religious_items: 5
},
constructionTime: 5400, // 90 minutes - sacred restoration
stages: 3,
benefits: ['blessing_system', 'graveyard_access']
},
{
id: 'blacksmith',
name: 'Blacksmith',
npcUnlock: 'Ivan Kovač', // Already available
materials: {
wood: 50,
stone: 100,
metal: 120,
coal: 80
},
constructionTime: 3000,
stages: 3,
benefits: ['weapon_crafting', 'tool_upgrades']
},
{
id: 'bakery',
name: 'Bakery',
npcUnlock: 'Pek', // Baker unlocked
materials: {
wood: 70,
stone: 50,
flour: 100,
tools: 10
},
constructionTime: 2400,
stages: 3,
benefits: ['food_production', 'energy_bonus']
}
];
buildingSpecs.forEach(spec => {
this.buildings.set(spec.id, {
...spec,
currentState: 'ruined', // ruined, under_construction, restored
currentStage: 0, // 0 = ruined, 1-3 = construction stages
progress: 0, // 0-100% construction progress
workersAssigned: 0,
materialsPaid: false,
completionTime: null
});
});
}
/**
* Check if player can start building restoration
*/
canStartRestoration(buildingId) {
const building = this.buildings.get(buildingId);
if (!building) return { canStart: false, reason: 'Building not found' };
if (building.currentState !== 'ruined') {
return { canStart: false, reason: 'Building already restored or under construction' };
}
// Check materials
const inventory = this.scene.inventorySystem;
for (const [material, amount] of Object.entries(building.materials)) {
if (!inventory.hasItem(material, amount)) {
return {
canStart: false,
reason: `Not enough ${material}. Need ${amount}, have ${inventory.getItemCount(material)}`
};
}
}
return { canStart: true };
}
/**
* Start building restoration
*/
startRestoration(buildingId) {
const check = this.canStartRestoration(buildingId);
if (!check.canStart) {
console.warn(`Cannot start restoration: ${check.reason}`);
return false;
}
const building = this.buildings.get(buildingId);
const inventory = this.scene.inventorySystem;
// Deduct materials
for (const [material, amount] of Object.entries(building.materials)) {
inventory.removeItem(material, amount);
}
// Start construction
building.currentState = 'under_construction';
building.currentStage = 1;
building.progress = 0;
building.materialsPaid = true;
building.completionTime = Date.now() + (building.constructionTime * 1000);
this.activeConstructions.push(buildingId);
// Spawn scaffolding visual
this.spawnConstructionVisuals(buildingId);
console.log(`Started restoration of ${building.name}`);
return true;
}
/**
* Assign workers to speed up construction
*/
assignWorker(buildingId, workerType = 'zombie') {
const building = this.buildings.get(buildingId);
if (!building || building.currentState !== 'under_construction') return false;
const speedBonus = {
'zombie': 0.1, // 10% faster per zombie
'human': 0.25, // 25% faster per human NPC
'kai': 0.5 // Kai works fastest
};
building.workersAssigned++;
if (!this.assignedWorkers.has(buildingId)) {
this.assignedWorkers.set(buildingId, []);
}
this.assignedWorkers.get(buildingId).push({ type: workerType, bonus: speedBonus[workerType] });
console.log(`Assigned ${workerType} to ${building.name}. Speed bonus: +${speedBonus[workerType] * 100}%`);
return true;
}
/**
* Update construction progress
*/
update(deltaTime) {
this.activeConstructions.forEach(buildingId => {
const building = this.buildings.get(buildingId);
// Calculate progress speed (base: 100% over constructionTime)
let baseSpeed = (100 / building.constructionTime) * (deltaTime / 1000);
// Apply worker bonuses
if (this.assignedWorkers.has(buildingId)) {
const workers = this.assignedWorkers.get(buildingId);
const totalBonus = workers.reduce((sum, w) => sum + w.bonus, 0);
baseSpeed *= (1 + totalBonus);
}
building.progress += baseSpeed;
// Check stage transitions
if (building.progress >= 33 && building.currentStage === 1) {
building.currentStage = 2;
this.updateBuildingVisual(buildingId, 2);
} else if (building.progress >= 66 && building.currentStage === 2) {
building.currentStage = 3;
this.updateBuildingVisual(buildingId, 3);
}
// Check completion
if (building.progress >= 100) {
this.completeRestoration(buildingId);
}
});
}
/**
* Complete building restoration
*/
completeRestoration(buildingId) {
const building = this.buildings.get(buildingId);
building.currentState = 'restored';
building.currentStage = 3;
building.progress = 100;
// Remove from active constructions
const index = this.activeConstructions.indexOf(buildingId);
if (index > -1) this.activeConstructions.splice(index, 1);
// Remove scaffolding
this.removeConstructionVisuals(buildingId);
// Update building sprite to restored
this.updateBuildingVisual(buildingId, 'restored');
// VFX: Building restoration sparkles
this.scene.vfxSystem?.playEffect('building_restoration', building.x, building.y);
// Unlock NPC if applicable
if (building.npcUnlock) {
this.unlockNPC(building.npcUnlock);
}
// Grant benefits
this.grantBuildingBenefits(buildingId);
console.log(`${building.name} restored! NPC unlocked: ${building.npcUnlock || 'None'}`);
// Quest completion check
this.scene.questSystem?.checkBuildingRestoration(buildingId);
}
/**
* Unlock NPC after building restoration
*/
unlockNPC(npcName) {
if (this.unlockedNPCs.has(npcName)) return;
this.unlockedNPCs.add(npcName);
// Spawn NPC in town
const npcData = this.getNPCSpawnData(npcName);
this.scene.npcSystem?.spawnNPC(npcName, npcData.x, npcData.y);
// Notification
this.scene.uiSystem?.showNotification(`${npcName} has arrived in Mrtva Dolina!`, 'success');
console.log(`🎉 NPC unlocked: ${npcName}`);
}
/**
* Get NPC spawn location based on their building
*/
getNPCSpawnData(npcName) {
const spawnLocations = {
'Ana': { x: 1200, y: 800 }, // Hospital
'Župan': { x: 1400, y: 700 }, // Mayor's Office
'Tehnik': { x: 1100, y: 900 }, // Tech Workshop
'Šivilja': { x: 1300, y: 1000 }, // Tailor
'Kustos': { x: 1500, y: 600 }, // Museum
'Teacher': { x: 1000, y: 700 }, // School
'Župnik': { x: 1600, y: 500 }, // Church
'Pek': { x: 900, y: 800 } // Bakery
};
return spawnLocations[npcName] || { x: 1200, y: 800 };
}
/**
* Grant building benefits to player
*/
grantBuildingBenefits(buildingId) {
const building = this.buildings.get(buildingId);
building.benefits.forEach(benefit => {
switch (benefit) {
case 'healing':
this.scene.gameState.unlocks.healing = true;
break;
case 'security':
this.scene.defenseSystem?.unlockPatrols();
break;
case 'election_unlock':
this.scene.electionSystem?.unlockElections();
break;
case 'tech_upgrades':
this.scene.craftingSystem?.unlockCategory('electronics');
break;
case 'armor_crafting':
this.scene.craftingSystem?.unlockCategory('armor');
break;
case 'lore_unlock':
this.scene.gameState.unlocks.museum = true;
break;
case 'buff_unlock':
this.scene.schoolSystem?.enable();
break;
case 'blessing_system':
this.scene.churchSystem?.enable();
break;
case 'weapon_crafting':
this.scene.craftingSystem?.unlockCategory('weapons');
break;
case 'food_production':
this.scene.gameState.unlocks.bakery = true;
break;
}
});
}
/**
* Visual updates
*/
spawnConstructionVisuals(buildingId) {
// Spawn scaffolding sprite
// Spawn worker NPCs/zombies
// Add construction sounds
}
removeConstructionVisuals(buildingId) {
// Remove scaffolding
// Remove workers
// Stop construction sounds
}
updateBuildingVisual(buildingId, stageOrState) {
// Update building sprite to show construction progress or restored state
// stages: 1 (10-30% built), 2 (30-70% built), 3 (70-100% built)
// 'restored' = final completed building
}
/**
* Get building restoration status
*/
getBuildingStatus(buildingId) {
return this.buildings.get(buildingId);
}
/**
* Get all restorable buildings
*/
getAllBuildings() {
return Array.from(this.buildings.values());
}
/**
* Get restoration progress summary
*/
getRestorationProgress() {
const total = this.buildings.size;
const restored = Array.from(this.buildings.values()).filter(b => b.currentState === 'restored').length;
const underConstruction = this.activeConstructions.length;
return {
total,
restored,
underConstruction,
ruined: total - restored - underConstruction,
percentComplete: Math.round((restored / total) * 100)
};
}
}