diff --git a/assets/sprites/npcs/priest/priest_walk_e_1767621603258.png b/assets/sprites/npcs/priest/priest_walk_e_1767621603258.png new file mode 100644 index 000000000..9ee221eb4 Binary files /dev/null and b/assets/sprites/npcs/priest/priest_walk_e_1767621603258.png differ diff --git a/assets/sprites/npcs/priest/priest_walk_n_1767621571395.png b/assets/sprites/npcs/priest/priest_walk_n_1767621571395.png new file mode 100644 index 000000000..885ed4197 Binary files /dev/null and b/assets/sprites/npcs/priest/priest_walk_n_1767621571395.png differ diff --git a/assets/sprites/npcs/priest/priest_walk_s_1767621587369.png b/assets/sprites/npcs/priest/priest_walk_s_1767621587369.png new file mode 100644 index 000000000..3b5fb50c3 Binary files /dev/null and b/assets/sprites/npcs/priest/priest_walk_s_1767621587369.png differ diff --git a/assets/sprites/npcs/priest/priest_walk_w_1767621616551.png b/assets/sprites/npcs/priest/priest_walk_w_1767621616551.png new file mode 100644 index 000000000..c95705a2b Binary files /dev/null and b/assets/sprites/npcs/priest/priest_walk_w_1767621616551.png differ diff --git a/references/npcs/priest/master_reference.png b/references/npcs/priest/master_reference.png new file mode 100644 index 000000000..a2f0241b4 Binary files /dev/null and b/references/npcs/priest/master_reference.png differ diff --git a/src/systems/ChurchSystem.js b/src/systems/ChurchSystem.js new file mode 100644 index 000000000..ace8283e5 --- /dev/null +++ b/src/systems/ChurchSystem.js @@ -0,0 +1,511 @@ +/** + * CHURCH & SPIRITUAL SYSTEM + * Mrtva Dolina - Cerkev, Pokopališče, Župnik + * + * Features: + * - Župnik NPC with blessing system + * - Church building (ruined → restored) + * - Graveyard with ghost spawns + * - Fog atmosphere effects + * - Zombie Scout graveyard shortcuts + * - Tool blessing for dark forces bonus + */ + +export class ChurchSystem { + constructor(scene) { + this.scene = scene; + + // Župnik NPC + this.priest = { + name: 'Župnik', + x: 0, + y: 0, + sprite: null, + dialogues: [], + blessingCost: 50, // Gold per blessing + blessingDuration: 300000 // 5 minutes + }; + + // Church building states + this.churchStates = { + ruined: { + sprite: 'church_ruined', + accessible: false, + description: 'Uničena cerkev, polna ruševin' + }, + restored: { + sprite: 'church_restored', + accessible: true, + description: 'Obnovljena cerkev, varno zavetje' + } + }; + + this.currentChurchState = 'ruined'; + + // Graveyard + this.graveyard = { + x: 0, + y: 0, + width: 500, + height: 500, + gravestones: [], + ghostSpawnPoints: [], + fogActive: false, + fogParticles: null + }; + + // Blessed tools tracking + this.blessedTools = new Map(); // toolId -> expiryTime + + // Zombie Scout graveyard shortcuts + this.graveyardShortcuts = []; + + this.init(); + } + + init() { + // Setup priest dialogues + this.setupPriestDialogues(); + + // Listen for graveyard entry + this.scene.events.on('player:enter_graveyard', this.onEnterGraveyard, this); + this.scene.events.on('player:exit_graveyard', this.onExitGraveyard, this); + + console.log('✅ ChurchSystem initialized'); + } + + /** + * ŽUPNIK DIALOGUES & BLESSING + */ + setupPriestDialogues() { + this.priest.dialogues = [ + { + id: 'intro', + text: 'Pozdravljen, potnik. Sem Župnik, varovatelj te cerkve od leta 2084...', + responses: [ + { text: 'Povej mi o letu 2084', action: 'lore_2084' }, + { text: 'Lahko blagosloviš moje orodje?', action: 'request_blessing' }, + { text: 'Nasvidenje', action: 'exit' } + ] + }, + { + id: 'lore_2084', + text: 'Leta 2084 je svet padel... Apokalipsa je prišla iz teme. Samo z blagoslovljenim orožjem lahko preživiš proti mračnim silam.', + responses: [ + { text: 'Razumem. Blagoslovi mojo katano!', action: 'request_blessing' }, + { text: 'Hvala za zgodbo', action: 'exit' } + ] + }, + { + id: 'request_blessing', + text: `Blagoslov zahteva darovnino ${this.priest.blessingCost} zlata. Kateri predmet želiš blagosloviti?`, + responses: [ + { text: 'Katano', action: 'bless_katana' }, + { text: 'Sekiro', action: 'bless_axe' }, + { text: 'Kasneje', action: 'exit' } + ] + } + ]; + } + + interactWithPriest() { + // Show dialogue UI + this.showPriestDialogue('intro'); + } + + showPriestDialogue(dialogueId) { + const dialogue = this.priest.dialogues.find(d => d.id === dialogueId); + if (!dialogue) return; + + this.scene.events.emit('show-dialogue', { + npc: 'Župnik', + portrait: 'priest_portrait', + text: dialogue.text, + responses: dialogue.responses.map(r => ({ + text: r.text, + callback: () => this.handleDialogueResponse(r.action) + })) + }); + } + + handleDialogueResponse(action) { + switch (action) { + case 'lore_2084': + this.showPriestDialogue('lore_2084'); + break; + case 'request_blessing': + this.showPriestDialogue('request_blessing'); + break; + case 'bless_katana': + this.blessTool('katana'); + break; + case 'bless_axe': + this.blessTool('axe'); + break; + case 'exit': + this.scene.events.emit('close-dialogue'); + break; + } + } + + blessTool(toolType) { + // Check if player has gold + if (!this.scene.inventorySystem.hasGold(this.priest.blessingCost)) { + this.scene.events.emit('show-notification', { + title: '❌ Premalo zlata', + message: `Rabiš ${this.priest.blessingCost} zlata za blagoslov!`, + icon: '💰', + duration: 3000, + color: '#FF4444' + }); + return; + } + + // Deduct gold + this.scene.inventorySystem.removeGold(this.priest.blessingCost); + + // Add blessing + const expiryTime = Date.now() + this.priest.blessingDuration; + this.blessedTools.set(toolType, expiryTime); + + // Blessing VFX + this.showBlessingEffect(); + + // Update tool stats + this.applyBlessingBonus(toolType); + + this.scene.events.emit('show-notification', { + title: '✨ Blagoslovljeno!', + message: `${toolType.toUpperCase()} je blagoslovljen za 5 minut! +50% damage proti mračnim silam!`, + icon: '🙏', + duration: 5000, + color: '#FFD700' + }); + + console.log(`✨ Blessed ${toolType} for ${this.priest.blessingDuration}ms`); + } + + showBlessingEffect() { + // Golden particles around player + const particles = this.scene.add.particles(0, 0, 'vfx_sparkle_star', { + speed: { min: 50, max: 100 }, + scale: { start: 1, end: 0 }, + alpha: { start: 1, end: 0 }, + lifespan: 1000, + quantity: 20, + tint: 0xFFD700 + }); + + particles.setPosition(this.scene.player.x, this.scene.player.y); + particles.explode(); + + setTimeout(() => particles.destroy(), 2000); + } + + applyBlessingBonus(toolType) { + // Apply bonus to tool + if (this.scene.combatSystem) { + this.scene.combatSystem.setToolBonus(toolType, 'dark_forces', 1.5); // +50% vs dark enemies + } + } + + isBlessedTool(toolType) { + const expiryTime = this.blessedTools.get(toolType); + if (!expiryTime) return false; + + if (Date.now() > expiryTime) { + // Blessing expired + this.blessedTools.delete(toolType); + this.removeBlessingBonus(toolType); + + this.scene.events.emit('show-notification', { + title: '⏰ Blagoslov Potekel', + message: `${toolType.toUpperCase()} blessing has expired.`, + icon: '💫', + duration: 3000, + color: '#999999' + }); + + return false; + } + + return true; + } + + removeBlessingBonus(toolType) { + if (this.scene.combatSystem) { + this.scene.combatSystem.removeToolBonus(toolType, 'dark_forces'); + } + } + + /** + * CHURCH RESTORATION + */ + restoreChurch() { + if (this.currentChurchState === 'restored') { + console.log('Church already restored'); + return; + } + + this.currentChurchState = 'restored'; + + // Update building sprite + if (this.churchSprite) { + this.churchSprite.setTexture('church_restored'); + } + + // Enable priest NPC + this.spawnPriest(); + + this.scene.events.emit('show-notification', { + title: '⛪ Cerkev Obnovljena', + message: 'Župnik je zdaj na voljo za blagoslove!', + icon: '✨', + duration: 5000, + color: '#FFD700' + }); + + console.log('⛪ Church restored'); + } + + spawnPriest() { + // Spawn priest NPC at church entrance + this.priest.sprite = this.scene.add.sprite( + this.priest.x, + this.priest.y, + 'priest_portrait' + ); + this.priest.sprite.setDepth(10); + this.priest.sprite.setInteractive(); + + this.priest.sprite.on('pointerdown', () => { + this.interactWithPriest(); + }); + + console.log('✅ Priest spawned'); + } + + /** + * GRAVEYARD SYSTEM + */ + setupGraveyard(x, y, width, height) { + this.graveyard.x = x; + this.graveyard.y = y; + this.graveyard.width = width; + this.graveyard.height = height; + + // Generate gravestones + this.generateGravestones(); + + // Setup ghost spawn points + this.setupGhostSpawns(); + + // Setup Zombie Scout shortcuts + this.setupGraveyardShortcuts(); + + console.log(`⚰️ Graveyard setup at (${x}, ${y})`); + } + + generateGravestones() { + const count = 20; // 20 gravestones + + for (let i = 0; i < count; i++) { + const gravestone = { + x: this.graveyard.x + Phaser.Math.Between(0, this.graveyard.width), + y: this.graveyard.y + Phaser.Math.Between(0, this.graveyard.height), + type: Phaser.Math.Between(1, 3), // 3 types + sprite: null + }; + + // Create sprite + gravestone.sprite = this.scene.add.sprite( + gravestone.x, + gravestone.y, + `gravestone_${gravestone.type}` + ); + gravestone.sprite.setDepth(5); + + this.graveyard.gravestones.push(gravestone); + } + + console.log(`⚰️ Generated ${count} gravestones`); + } + + setupGhostSpawns() { + // 5 ghost spawn points + for (let i = 0; i < 5; i++) { + this.graveyard.ghostSpawnPoints.push({ + x: this.graveyard.x + Phaser.Math.Between(0, this.graveyard.width), + y: this.graveyard.y + Phaser.Math.Between(0, this.graveyard.height) + }); + } + + // Start ghost spawning + this.startGhostSpawns(); + } + + startGhostSpawns() { + // Spawn ghost every 30 seconds + setInterval(() => { + if (this.isPlayerInGraveyard()) { + this.spawnGhost(); + } + }, 30000); + } + + spawnGhost() { + const spawnPoint = Phaser.Utils.Array.GetRandom(this.graveyard.ghostSpawnPoints); + + this.scene.events.emit('enemy:spawn', { + type: 'ghost', + x: spawnPoint.x, + y: spawnPoint.y, + level: Phaser.Math.Between(1, 5) + }); + + console.log(`👻 Ghost spawned at (${spawnPoint.x}, ${spawnPoint.y})`); + } + + setupGraveyardShortcuts() { + // 3 secret shortcuts for Zombie Scout + for (let i = 0; i < 3; i++) { + this.graveyardShortcuts.push({ + x: this.graveyard.x + Phaser.Math.Between(0, this.graveyard.width), + y: this.graveyard.y + Phaser.Math.Between(0, this.graveyard.height), + leadsTo: 'rare_tomb', + discovered: false + }); + } + + console.log('🔍 Graveyard shortcuts setup for Zombie Scout'); + } + + /** + * FOG ATMOSPHERE + */ + onEnterGraveyard() { + if (this.graveyard.fogActive) return; + + // Activate fog + this.graveyard.fogActive = true; + this.createFogEffect(); + + this.scene.events.emit('show-notification', { + title: '🌫️ Pokopališče', + message: 'Mračna megla te objame...', + icon: '⚰️', + duration: 3000, + color: '#666666' + }); + + console.log('🌫️ Graveyard fog activated'); + } + + createFogEffect() { + // Add fog particle layer + this.graveyard.fogParticles = this.scene.add.particles(0, 0, 'fog_particle', { + x: { min: this.graveyard.x, max: this.graveyard.x + this.graveyard.width }, + y: { min: this.graveyard.y, max: this.graveyard.y + this.graveyard.height }, + speed: 10, + scale: { start: 1, end: 1.5 }, + alpha: { start: 0.3, end: 0 }, + lifespan: 5000, + frequency: 100, + tint: 0x666666 + }); + + this.graveyard.fogParticles.setDepth(20); + + // Darken screen slightly + if (this.scene.cameras.main) { + this.scene.cameras.main.setAlpha(0.8); + } + } + + onExitGraveyard() { + if (!this.graveyard.fogActive) return; + + // Deactivate fog + this.graveyard.fogActive = false; + + if (this.graveyard.fogParticles) { + this.graveyard.fogParticles.destroy(); + this.graveyard.fogParticles = null; + } + + // Restore camera alpha + if (this.scene.cameras.main) { + this.scene.cameras.main.setAlpha(1); + } + + console.log('🌫️ Graveyard fog deactivated'); + } + + isPlayerInGraveyard() { + if (!this.scene.player) return false; + + const px = this.scene.player.x; + const py = this.scene.player.y; + + return ( + px >= this.graveyard.x && + px <= this.graveyard.x + this.graveyard.width && + py >= this.graveyard.y && + py <= this.graveyard.y + this.graveyard.height + ); + } + + /** + * ZOMBIE SCOUT GRAVEYARD SYNERGY + */ + discoverShortcut(zombieScout) { + const undiscovered = this.graveyardShortcuts.filter(s => !s.discovered); + if (undiscovered.length === 0) { + console.log('All shortcuts already discovered'); + return null; + } + + const shortcut = undiscovered[0]; + shortcut.discovered = true; + + this.scene.events.emit('show-notification', { + title: '🔍 Zombie Scout našel bližnjico!', + message: 'Odkrita skrivna pot do redkih grobnic!', + icon: '⚰️', + duration: 5000, + color: '#00FF00' + }); + + console.log(`🔍 Shortcut discovered at (${shortcut.x}, ${shortcut.y})`); + + return shortcut; + } + + update(delta) { + // Check if player entered/exited graveyard + const inGraveyard = this.isPlayerInGraveyard(); + + if (inGraveyard && !this.graveyard.fogActive) { + this.onEnterGraveyard(); + } else if (!inGraveyard && this.graveyard.fogActive) { + this.onExitGraveyard(); + } + + // Update blessed tools expiry + this.blessedTools.forEach((expiryTime, toolType) => { + this.isBlessedTool(toolType); // Auto-removes expired + }); + } + + destroy() { + if (this.graveyard.fogParticles) { + this.graveyard.fogParticles.destroy(); + } + + this.graveyard.gravestones.forEach(g => { + if (g.sprite) g.sprite.destroy(); + }); + + this.blessedTools.clear(); + } +}