diff --git a/assets/sprites/dialogue_portraits/arborist_dialogue_portrait_1767634300470.png b/assets/sprites/dialogue_portraits/arborist_dialogue_portrait_1767634300470.png new file mode 100644 index 000000000..0ad8e2b64 Binary files /dev/null and b/assets/sprites/dialogue_portraits/arborist_dialogue_portrait_1767634300470.png differ diff --git a/assets/sprites/dialogue_portraits/glavni_smetar_dialogue_portrait_1767634482158.png b/assets/sprites/dialogue_portraits/glavni_smetar_dialogue_portrait_1767634482158.png new file mode 100644 index 000000000..0395c2b27 Binary files /dev/null and b/assets/sprites/dialogue_portraits/glavni_smetar_dialogue_portrait_1767634482158.png differ diff --git a/assets/sprites/dialogue_portraits/ivan_kovac_dialogue_portrait_1767634315456.png b/assets/sprites/dialogue_portraits/ivan_kovac_dialogue_portrait_1767634315456.png new file mode 100644 index 000000000..8b1bd4c7d Binary files /dev/null and b/assets/sprites/dialogue_portraits/ivan_kovac_dialogue_portrait_1767634315456.png differ diff --git a/assets/sprites/dialogue_portraits/kustos_dialogue_portrait_1767634330510.png b/assets/sprites/dialogue_portraits/kustos_dialogue_portrait_1767634330510.png new file mode 100644 index 000000000..693b7666d Binary files /dev/null and b/assets/sprites/dialogue_portraits/kustos_dialogue_portrait_1767634330510.png differ diff --git a/assets/sprites/dialogue_portraits/mayor_dialogue_portrait_1767634345650.png b/assets/sprites/dialogue_portraits/mayor_dialogue_portrait_1767634345650.png new file mode 100644 index 000000000..3a534963b Binary files /dev/null and b/assets/sprites/dialogue_portraits/mayor_dialogue_portrait_1767634345650.png differ diff --git a/assets/sprites/dialogue_portraits/miro_pravnik_dialogue_portrait_1767634372078.png b/assets/sprites/dialogue_portraits/miro_pravnik_dialogue_portrait_1767634372078.png new file mode 100644 index 000000000..0be16329b Binary files /dev/null and b/assets/sprites/dialogue_portraits/miro_pravnik_dialogue_portrait_1767634372078.png differ diff --git a/assets/sprites/dialogue_portraits/pek_dialogue_portrait_1767634386513.png b/assets/sprites/dialogue_portraits/pek_dialogue_portrait_1767634386513.png new file mode 100644 index 000000000..1497dbe4e Binary files /dev/null and b/assets/sprites/dialogue_portraits/pek_dialogue_portrait_1767634386513.png differ diff --git a/assets/sprites/dialogue_portraits/priest_dialogue_portrait_1767634464626.png b/assets/sprites/dialogue_portraits/priest_dialogue_portrait_1767634464626.png new file mode 100644 index 000000000..b7d9ac583 Binary files /dev/null and b/assets/sprites/dialogue_portraits/priest_dialogue_portrait_1767634464626.png differ diff --git a/assets/sprites/dialogue_portraits/sivilja_dialogue_portrait_1767634405476.png b/assets/sprites/dialogue_portraits/sivilja_dialogue_portrait_1767634405476.png new file mode 100644 index 000000000..0756dafa8 Binary files /dev/null and b/assets/sprites/dialogue_portraits/sivilja_dialogue_portrait_1767634405476.png differ diff --git a/assets/sprites/dialogue_portraits/teacher_dialogue_portrait_1767634420908.png b/assets/sprites/dialogue_portraits/teacher_dialogue_portrait_1767634420908.png new file mode 100644 index 000000000..7fff2e102 Binary files /dev/null and b/assets/sprites/dialogue_portraits/teacher_dialogue_portrait_1767634420908.png differ diff --git a/assets/sprites/dialogue_portraits/tehnik_dialogue_portrait_1767634448915.png b/assets/sprites/dialogue_portraits/tehnik_dialogue_portrait_1767634448915.png new file mode 100644 index 000000000..faeccc6c1 Binary files /dev/null and b/assets/sprites/dialogue_portraits/tehnik_dialogue_portrait_1767634448915.png differ diff --git a/references/npcs/ivan_kovac/master_reference_SMOOTH_FIXED.png b/references/npcs/ivan_kovac/master_reference_SMOOTH_FIXED.png deleted file mode 100644 index 4e9839539..000000000 Binary files a/references/npcs/ivan_kovac/master_reference_SMOOTH_FIXED.png and /dev/null differ diff --git a/src/systems/MuseumEvolutionSystem.js b/src/systems/MuseumEvolutionSystem.js new file mode 100644 index 000000000..1eaebcae2 --- /dev/null +++ b/src/systems/MuseumEvolutionSystem.js @@ -0,0 +1,344 @@ +/** + * MUSEUM EVOLUTION SYSTEM + * 3-stage museum restoration with artifact collection + * Integrates with Kustos NPC and quest system + */ + +export class MuseumEvolutionSystem { + constructor(scene) { + this.scene = scene; + + // Museum evolution stages + this.currentStage = 0; // 0 = ruined, 1 = partial, 2 = advanced, 3 = complete + + // Artifact collection + this.artifacts = new Map(); // artifactId → artifactData + this.collectedArtifacts = new Set(); + + // Album tracking + this.albumCategories = new Map(); + + this.init(); + } + + init() { + this.initializeArtifactDatabase(); + this.initializeAlbumCategories(); + } + + /** + * Initialize all collectible artifacts + */ + initializeArtifactDatabase() { + const artifacts = [ + // Pre-war artifacts + { id: 'dino_skull', name: 'Dinosaur Skull', category: 'prehistory', rarity: 'legendary', discoveryReward: 500 }, + { id: 'ancient_vase', name: 'Ancient Vase', category: 'prehistory', rarity: 'rare', discoveryReward: 100 }, + { id: 'fossil', name: 'Fossil', category: 'prehistory', rarity: 'common', discoveryReward: 50 }, + + // 2084 tech artifacts + { id: 'ai_core', name: 'AI Core Fragment', category: '2084_tech', rarity: 'legendary', discoveryReward: 800 }, + { id: 'hologram_projector', name: 'Hologram Projector', category: '2084_tech', rarity: 'rare', discoveryReward: 150 }, + { id: 'old_smartphone', name: 'Pre-War Smartphone', category: '2084_tech', rarity: 'uncommon', discoveryReward: 80 }, + + // Cultural artifacts + { id: 'religious_icon', name: 'Religious Icon', category: 'culture', rarity: 'rare', discoveryReward: 120 }, + { id: 'painting', name: 'Old Painting', category: 'culture', rarity: 'uncommon', discoveryReward: 90 }, + { id: 'book_collection', name: 'Rare Book Collection', category: 'culture', rarity: 'rare', discoveryReward: 110 }, + + // Post-apocalypse relics + { id: 'first_cannabis_seed', name: 'First Cannabis Seed', category: 'post_apo', rarity: 'legendary', discoveryReward: 600 }, + { id: 'zombie_variant_sample', name: 'Zombie Variant Sample', category: 'post_apo', rarity: 'rare', discoveryReward: 140 }, + { id: 'survival_journal', name: "Survivor's Journal", category: 'post_apo', rarity: 'uncommon', discoveryReward: 70 } + ]; + + artifacts.forEach(artifact => { + this.artifacts.set(artifact.id, { + ...artifact, + discovered: false, + donatedToMuseum: false, + discoveryDate: null + }); + }); + } + + /** + * Initialize album categories for organization + */ + initializeAlbumCategories() { + this.albumCategories.set('prehistory', { + name: 'Prehistoric Era', + description: 'Artifacts from Earth\'s ancient past', + totalArtifacts: 3, + collected: 0 + }); + + this.albumCategories.set('2084_tech', { + name: '2084 Technology', + description: 'Advanced tech from before The Collapse', + totalArtifacts: 3, + collected: 0 + }); + + this.albumCategories.set('culture', { + name: 'Cultural Heritage', + description: 'Art, religion, and culture of the old world', + totalArtifacts: 3, + collected: 0 + }); + + this.albumCategories.set('post_apo', { + name: 'Post-Apocalypse', + description: 'Relics from the new world', + totalArtifacts: 3, + collected: 0 + }); + } + + /** + * Discover artifact (player finds it) + */ + discoverArtifact(artifactId, location) { + const artifact = this.artifacts.get(artifactId); + if (!artifact) return false; + + if (artifact.discovered) { + console.warn(`Artifact ${artifactId} already discovered`); + return false; + } + + artifact.discovered = true; + artifact.discoveryDate = Date.now(); + artifact.discoveryLocation = location; + + // Add to player inventory + this.scene.inventorySystem.addItem(artifactId, 1); + + // Notification + this.scene.uiSystem?.showNotification( + `Artifact discovered: ${artifact.name}!`, + 'discovery', + { rarity: artifact.rarity } + ); + + // Reward currency + this.scene.economySystem.addCurrency(artifact.discoveryReward); + + // VFX + this.scene.vfxSystem?.playEffect('artifact_discovery', this.scene.player.x, this.scene.player.y); + + console.log(`✨ Discovered artifact: ${artifact.name} (+${artifact.discoveryReward} coins)`); + + // Kustos dialogue trigger + if (!artifact.donatedToMuseum) { + this.triggerKustosDialogue(artifactId); + } + + return true; + } + + /** + * Donate artifact to museum (Kustos interaction) + */ + donateArtifact(artifactId) { + const artifact = this.artifacts.get(artifactId); + if (!artifact || !artifact.discovered || artifact.donatedToMuseum) return false; + + // Remove from player inventory + if (!this.scene.inventorySystem.hasItem(artifactId, 1)) { + console.warn('Player does not have artifact in inventory'); + return false; + } + + this.scene.inventorySystem.removeItem(artifactId, 1); + + // Mark as donated + artifact.donatedToMuseum = true; + this.collectedArtifacts.add(artifactId); + + // Update category progress + const category = this.albumCategories.get(artifact.category); + category.collected++; + + // Kustos thanks dialogue + this.scene.dialogueSystem?.startDialogue('kustos', 'thank_donation', { artifact: artifact.name }); + + // Check for museum evolution + this.checkEvolutionTrigger(); + + // Achievement check + this.checkCompletionAchievements(); + + console.log(`📦 Donated ${artifact.name} to museum`); + return true; + } + + /** + * Check if museum should evolve to next stage + */ + checkEvolutionTrigger() { + const totalDonated = this.collectedArtifacts.size; + + // Stage thresholds + const stageThresholds = { + 1: 4, // Stage 1: 4 artifacts donated + 2: 8, // Stage 2: 8 artifacts donated + 3: 12 // Stage 3: All 12 artifacts donated + }; + + // Check for evolution + for (let stage = 3; stage >= 1; stage--) { + if (totalDonated >= stageThresholds[stage] && this.currentStage < stage) { + this.evolveMuseum(stage); + break; + } + } + } + + /** + * Evolve museum to next stage + */ + evolveMuseum(newStage) { + if (newStage <= this.currentStage) return; + + this.currentStage = newStage; + + // Update building visual + this.updateMuseumVisual(newStage); + + // VFX: Building evolution + this.scene.vfxSystem?.playEffect('museum_evolution', 1500, 600); + + // Notification + const stageNames = { + 1: 'Partial Collection', + 2: 'Advanced Exhibition', + 3: 'World-Class Museum' + }; + + this.scene.uiSystem?.showNotification( + `Museum evolved: ${stageNames[newStage]}!`, + 'success' + ); + + // Kustos special dialogue + this.scene.dialogueSystem?.startDialogue('kustos', `museum_stage_${newStage}`); + + // Grant benefits + this.grantStageBenefits(newStage); + + console.log(`🏛️ Museum evolved to Stage ${newStage}: ${stageNames[newStage]}`); + } + + /** + * Update museum building sprite + */ + updateMuseumVisual(stage) { + // Load corresponding sprite: museum_stage_1, museum_stage_2, museum_stage_3 + const sprite = this.scene.buildingSystem.getBuilding('museum'); + if (sprite) { + sprite.setTexture(`museum_stage_${stage}`); + } + } + + /** + * Grant benefits for reaching museum stage + */ + grantStageBenefits(stage) { + switch (stage) { + case 1: + // Stage 1: Basic lore access + this.scene.gameState.unlocks.lore_system = true; + this.scene.uiSystem?.unlockTab('lore'); + break; + case 2: + // Stage 2: Research bonuses + this.scene.gameState.buffs.research_speed = 1.25; // +25% research + break; + case 3: + // Stage 3: Full collection bonus + this.scene.gameState.buffs.artifact_discovery = 2.0; // 2x artifact find rate + this.scene.achievementSystem?.unlock('master_curator'); + break; + } + } + + /** + * Trigger Kustos dialogue about found artifact + */ + triggerKustosDialogue(artifactId) { + const artifact = this.artifacts.get(artifactId); + + // Show notification to visit Kustos + this.scene.uiSystem?.showNotification( + `Kustos might be interested in the ${artifact.name}`, + 'info', + { icon: 'museum' } + ); + } + + /** + * Check for collection completion achievements + */ + checkCompletionAchievements() { + // Check category completion + this.albumCategories.forEach((category, categoryId) => { + if (category.collected === category.totalArtifacts) { + this.scene.achievementSystem?.unlock(`complete_${categoryId}_collection`); + } + }); + + // Check total completion + if (this.collectedArtifacts.size === this.artifacts.size) { + this.scene.achievementSystem?.unlock('complete_museum_collection'); + } + } + + /** + * Get album progress + */ + getAlbumProgress() { + const categories = {}; + + this.albumCategories.forEach((category, categoryId) => { + categories[categoryId] = { + ...category, + progress: Math.round((category.collected / category.totalArtifacts) * 100) + }; + }); + + return { + categories, + totalArtifacts: this.artifacts.size, + totalCollected: this.collectedArtifacts.size, + overallProgress: Math.round((this.collectedArtifacts.size / this.artifacts.size) * 100) + }; + } + + /** + * Get artifacts by category for UI display + */ + getArtifactsByCategory(categoryId) { + return Array.from(this.artifacts.values()) + .filter(a => a.category === categoryId); + } + + /** + * Get museum stage info + */ + getStageInfo() { + const stageData = { + 0: { name: 'Ruined', description: 'Museum is destroyed' }, + 1: { name: 'Partial Collection', description: '4 artifacts displayed' }, + 2: { name: 'Advanced Exhibition', description: '8 artifacts displayed' }, + 3: { name: 'World-Class Museum', description: 'All 12 artifacts displayed' } + }; + + return { + currentStage: this.currentStage, + ...stageData[this.current Stage], + nextStageRequirement: this.currentStage < 3 ? [4, 8, 12][this.currentStage] : null, + currentArtifacts: this.collectedArtifacts.size + }; + } +} diff --git a/src/systems/TownRestorationLogic.js b/src/systems/TownRestorationLogic.js new file mode 100644 index 000000000..034f7b774 --- /dev/null +++ b/src/systems/TownRestorationLogic.js @@ -0,0 +1,474 @@ +/** + * 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) + }; + } +}