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:
511
src/systems/ChurchSystem.js
Normal file
511
src/systems/ChurchSystem.js
Normal 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user