/** * 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) }; } }