/** * ELECTION & SOCIAL ORDER SYSTEM * Mrtva Dolina - City Evolution Through Democracy * * Features: * - Chaos phase (no leader, messy city) * - Election trigger (after 5+ NPCs arrive) * - Vote gathering & influence system * - Mayor inauguration with visual/audio changes * - Unlocks city improvements (walls, patrols) */ export class ElectionSystem { constructor(scene) { this.scene = scene; // Election state this.electionPhase = 'none'; // none, chaos, campaign, complete this.mayorElected = false; this.currentMayor = null; // Candidates this.candidates = [ { id: 'mayor_default', name: 'Župan', votes: 0, platform: 'Obzidje in varnost', supportingNPCs: [] }, { id: 'ivan_kovac', name: 'Ivan Kovač', votes: 0, platform: 'Proizvodni razvoj', supportingNPCs: [] }, { id: 'tehnik', name: 'Tehnik', votes: 0, platform: 'Tehnološki napredek', supportingNPCs: [] } ]; // City visual state this.cityState = { cleanliness: 0, // 0-100 security: 0, // 0-100 morale: 0 // 0-100 }; // Trash/debris objects for visual chaos this.debrisObjects = []; // Population tracking this.npcCount = 0; this.electionThreshold = 5; // Trigger election at 5 NPCs this.init(); } init() { // Listen for NPC arrival events this.scene.events.on('npc:arrived', this.onNPCArrival, this); this.scene.events.on('quest:completed', this.onQuestCompleted, this); console.log('✅ ElectionSystem initialized'); } /** * NPC ARRIVAL - Track population */ onNPCArrival(npcData) { this.npcCount++; console.log(`👤 NPC arrived: ${npcData.name}. Total: ${this.npcCount}`); // Check if chaos phase should start if (this.npcCount >= 3 && this.electionPhase === 'none') { this.startChaosPhase(); } // Check if election should trigger if (this.npcCount >= this.electionThreshold && this.electionPhase === 'chaos') { this.triggerElection(); } } /** * CHAOS PHASE - City is disorganized */ startChaosPhase() { this.electionPhase = 'chaos'; console.log('💥 CHAOS PHASE STARTED - City needs leadership!'); // Spawn trash/debris around town this.spawnDebris(15); // 15 trash piles // Lower city stats this.cityState.cleanliness = 20; this.cityState.security = 10; this.cityState.morale = 30; // NPCs start discussing need for leader this.startChaosDialogues(); // Show notification this.scene.events.emit('show-notification', { title: 'Stanje Kaosa', message: 'Ljudje potrebujejo vodjo! Uredite red v mestu.', icon: '⚠️', duration: 5000 }); // Update status board this.updateStatusBoard(); } spawnDebris(count) { const debrisTypes = ['trash_pile', 'broken_crate', 'rubble', 'scattered_papers']; for (let i = 0; i < count; i++) { const x = Phaser.Math.Between(100, this.scene.cameras.main.width - 100); const y = Phaser.Math.Between(100, this.scene.cameras.main.height - 100); const type = Phaser.Utils.Array.GetRandom(debrisTypes); const debris = this.scene.add.sprite(x, y, type); debris.setDepth(1); this.debrisObjects.push(debris); } } startChaosDialogues() { // NPCs randomly discuss the chaos const dialogues = [ { npc: 'sivilja', text: 'Ta kaos je neznosn! Rabimo vodjo!' }, { npc: 'pek', text: 'Kdo bo prinesel red v to mesto?' }, { npc: 'ivan_kovac', text: 'Brez organizacije ne moremo preživeti.' } ]; // Emit dialogue events periodically this.chaosDialogueTimer = setInterval(() => { const dialogue = Phaser.Utils.Array.GetRandom(dialogues); this.scene.events.emit('npc:dialogue', dialogue); }, 30000); // Every 30 seconds } /** * TRIGGER ELECTION */ triggerElection() { this.electionPhase = 'campaign'; console.log('🗳️ ELECTION TRIGGERED - Campaign begins!'); // Stop chaos dialogues if (this.chaosDialogueTimer) { clearInterval(this.chaosDialogueTimer); } // Create election quest this.createElectionQuest(); // Show notification this.scene.events.emit('show-notification', { title: 'Volitve za Župana', message: 'Mesto potrebuje vodjo! Pomagaj pri zbiranju glasov.', icon: '🗳️', duration: 5000 }); // NPCs start campaign dialogues this.startCampaignDialogues(); } createElectionQuest() { if (!this.scene.questSystem) return; const electionQuest = { id: 'election_campaign', title: 'Zbiranje Glasov za Župana', type: 'social', priority: 5, description: 'Pomagaj izbrati župana za Mrtvo Dolino.', objectives: [ { id: 'talk_to_npcs', text: 'Pogovor s 5 NPC-ji o volitvah', type: 'interaction', required: 5, current: 0 }, { id: 'support_candidate', text: 'Podpri kandidata z opravljanjem questov', type: 'flag', complete: false } ], rewards: { xp: 1000, unlocks: ['mayor_office', 'city_improvements'] }, dialogue: { start: ['Ljudi potrebujejo vodjo. Kdo bo župan?'], complete: ['Volitve so končane! Novi župan je izvoljen!'] }, npc: 'mayor' }; this.scene.questSystem.registerQuest(electionQuest); this.scene.questSystem.startQuest('election_campaign'); } startCampaignDialogues() { // Each candidate promotes their platform const campaignLines = { mayor_default: 'Glasujte zame! Zgradil bom obzidje in patruljo!', ivan_kovac: 'Potrebujemo proizvodnjo! Podprite me!', tehnik: 'Tehnologija je prihodnost! Volite tehnološki napredek!' }; // NPCs express support for different candidates this.campaignDialogueTimer = setInterval(() => { const candidate = Phaser.Utils.Array.GetRandom(this.candidates); this.scene.events.emit('npc:dialogue', { npc: candidate.id, text: campaignLines[candidate.id] }); }, 45000); // Every 45 seconds } /** * VOTING - Player influences votes through quests */ onQuestCompleted(questId) { if (this.electionPhase !== 'campaign') return; // Check which candidate benefits from this quest const questCandidateMap = { 'obzidje': 'mayor_default', 'pekov_recept': 'mayor_default', 'tehnikova_naprava': 'tehnik', 'siviljina_prosnja': 'ivan_kovac' }; const candidateId = questCandidateMap[questId]; if (candidateId) { this.addVote(candidateId, 1); // Show feedback this.scene.events.emit('show-floating-text', { x: this.scene.player.x, y: this.scene.player.y - 50, text: `+1 glas za ${candidateId}`, color: '#FFD700' }); } } addVote(candidateId, votes = 1) { const candidate = this.candidates.find(c => c.id === candidateId); if (candidate) { candidate.votes += votes; console.log(`🗳️ ${candidate.name} dobil ${votes} glas(ov). Skupaj: ${candidate.votes}`); } } /** * COMPLETE ELECTION - Inaugurate mayor */ completeElection() { if (this.mayorElected) return; // Count votes and determine winner const winner = this.candidates.reduce((prev, current) => (prev.votes > current.votes) ? prev : current ); this.currentMayor = winner; this.mayorElected = true; this.electionPhase = 'complete'; console.log(`🏛️ ${winner.name} je izvoljen za župana!`); // Inauguration sequence this.inauguration(winner); } inauguration(mayor) { // Visual changes this.cleanUpCity(); // Mayor moves to town hall if (this.scene.npcs && this.scene.npcs[mayor.id]) { const mayorNPC = this.scene.npcs[mayor.id]; this.scene.tweens.add({ targets: mayorNPC, x: this.scene.townHallX || 400, y: this.scene.townHallY || 300, duration: 3000, ease: 'Sine.easeInOut' }); } // Change music to ordered/military theme if (this.scene.sound && this.scene.sound.get('background_music')) { this.scene.sound.get('background_music').stop(); } this.scene.sound.play('mayor_anthem', { loop: true, volume: 0.5 }); // Unlock new features this.unlockMayorFeatures(); // Show inauguration cutscene this.scene.events.emit('show-notification', { title: `Župan ${mayor.name}`, message: `${mayor.name} je uradno inauguriran! Mesto je zdaj pod vodstvom.`, icon: '🏛️', duration: 7000 }); // Update city stats this.cityState.cleanliness = 80; this.cityState.security = 70; this.cityState.morale = 90; this.updateStatusBoard(); // Complete election quest if (this.scene.questSystem) { this.scene.questSystem.completeQuest('election_campaign'); } } cleanUpCity() { // Remove all debris with animation this.debrisObjects.forEach((debris, index) => { this.scene.tweens.add({ targets: debris, alpha: 0, scaleX: 0, scaleY: 0, duration: 1000, delay: index * 100, onComplete: () => debris.destroy() }); }); this.debrisObjects = []; // Add clean visual elements (flags, guards, etc.) this.addCityImprovements(); } addCityImprovements() { // Add flags const flagPositions = [ { x: 200, y: 150 }, { x: 400, y: 150 }, { x: 600, y: 150 } ]; flagPositions.forEach(pos => { const flag = this.scene.add.sprite(pos.x, pos.y, 'city_flag'); flag.setDepth(10); // Waving animation this.scene.tweens.add({ targets: flag, scaleX: 1.1, duration: 1000, yoyo: true, repeat: -1, ease: 'Sine.easeInOut' }); }); // Add guards (if available) // ... patrol implementation } unlockMayorFeatures() { // Unlock wall building if (this.scene.buildingSystem) { this.scene.buildingSystem.unlock('wall_wooden'); this.scene.buildingSystem.unlock('wall_stone'); } // Unlock patrol system if (this.scene.defenseSystem) { this.scene.defenseSystem.unlockPatrols(); } // Unlock mayor's office this.scene.events.emit('building:unlocked', 'mayor_office'); console.log('🔓 Mayor features unlocked: walls, patrols, office'); } updateStatusBoard() { // Update city status display this.scene.events.emit('city:stats_updated', { cleanliness: this.cityState.cleanliness, security: this.cityState.security, morale: this.cityState.morale, population: this.npcCount, mayor: this.currentMayor ? this.currentMayor.name : 'None' }); } /** * Get election results for UI display */ getElectionResults() { return { phase: this.electionPhase, candidates: this.candidates, winner: this.currentMayor, cityState: this.cityState }; } destroy() { if (this.chaosDialogueTimer) clearInterval(this.chaosDialogueTimer); if (this.campaignDialogueTimer) clearInterval(this.campaignDialogueTimer); this.debrisObjects.forEach(obj => obj.destroy()); this.debrisObjects = []; } }