Partial Church system: ChurchSystem.js (blessing mechanics, graveyard fog, ghost spawns), Priest reference + 4 walk sprites saved. Will complete spiritual assets later per user request.

This commit is contained in:
2026-01-05 15:02:05 +01:00
parent f4639a2a3b
commit e5cac8579e
6 changed files with 511 additions and 0 deletions

511
src/systems/ChurchSystem.js Normal file
View File

@@ -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();
}
}