Files
novafarma/old_logic/src_backup_1768938138/systems/QuestSystemExpanded.js
2026-01-21 01:08:21 +01:00

428 lines
11 KiB
JavaScript

/**
* QuestSystemExpanded.js
* =======================
* KRVAVA ŽETEV - Enhanced Quest System for Main Campaign
*
* Extends the original QuestSystem to support:
* - Act-based quest structure
* - Location-based objectives
* - Dialogue integration
* - Event triggers
* - Quest chains
* - Bond strength rewards
*
* @author NovaFarma Team
* @date 2025-12-23
*/
class QuestSystemExpanded {
constructor(scene) {
this.scene = scene;
// Load Act 1 Quest Data
this.questDB = typeof Act1QuestData !== 'undefined' ? Act1QuestData : {};
// Quest state
this.activeQuests = new Map(); // questId -> quest instance
this.completedQuests = new Set();
this.questHistory = [];
// Current main quest
this.mainQuest = null;
// UI reference
this.questUI = null;
console.log('📜 QuestSystemExpanded initialized');
console.log(`📚 Loaded ${Object.keys(this.questDB).length} quests`);
}
/**
* Start a quest
*/
startQuest(questId) {
if (this.completedQuests.has(questId)) {
console.log(`⚠️ Quest already completed: ${questId}`);
return false;
}
if (this.activeQuests.has(questId)) {
console.log(`⚠️ Quest already active: ${questId}`);
return false;
}
const questTemplate = this.questDB[questId];
if (!questTemplate) {
console.error(`❌ Quest not found: ${questId}`);
return false;
}
// Create quest instance (deep copy)
const quest = JSON.parse(JSON.stringify(questTemplate));
quest.startTime = Date.now();
quest.status = 'active';
// Add to active quests
this.activeQuests.set(questId, quest);
// If main quest, set as current
if (quest.isMainQuest) {
this.mainQuest = quest;
}
// Show start dialogue
if (quest.startDialogue) {
this.showQuestDialogue(quest.startDialogue);
}
// Trigger any start events
if (quest.triggerEvent) {
this.triggerQuestEvent(quest.triggerEvent);
}
// Notification
this.showQuestNotification({
title: 'New Quest!',
questTitle: quest.title,
description: quest.description,
icon: quest.isMainQuest ? '📖' : '📝'
});
// Update UI
this.updateUI();
console.log(`📜 Quest Started: ${quest.title} (${questId})`);
// Emit event
this.scene.events.emit('questStarted', { quest });
return true;
}
/**
* Complete a quest objective
*/
completeObjective(questId, objectiveId) {
const quest = this.activeQuests.get(questId);
if (!quest) {
console.warn(`Quest not active: ${questId}`);
return false;
}
const objective = quest.objectives.find(obj => obj.id === objectiveId);
if (!objective) {
console.error(`Objective not found: ${objectiveId}`);
return false;
}
if (objective.completed) {
console.log(`Objective already complete: ${objectiveId}`);
return false;
}
objective.completed = true;
objective.completedTime = Date.now();
console.log(`✅ Objective Complete: ${objective.description}`);
// Show notification
this.showObjectiveNotification(objective.description);
// Check if all objectives complete
const allComplete = quest.objectives.every(obj => obj.completed);
if (allComplete) {
this.completeQuest(questId);
} else {
// Update UI
this.updateUI();
}
return true;
}
/**
* Update objective progress
*/
updateObjectiveProgress(questId, objectiveId, amount) {
const quest = this.activeQuests.get(questId);
if (!quest) return false;
const objective = quest.objectives.find(obj => obj.id === objectiveId);
if (!objective) return false;
objective.current = Math.min(objective.required, objective.current + amount);
// Check if objective complete
if (objective.current >= objective.required && !objective.completed) {
this.completeObjective(questId, objectiveId);
} else {
this.updateUI();
}
return true;
}
/**
* Complete a quest
*/
completeQuest(questId) {
const quest = this.activeQuests.get(questId);
if (!quest) {
console.error(`Quest not active: ${questId}`);
return false;
}
// Mark as completed
quest.status = 'completed';
quest.completeTime = Date.now();
// Show completion dialogue
if (quest.completeDialogue) {
this.showQuestDialogue(quest.completeDialogue);
}
// Grant rewards
if (quest.rewards) {
this.grantRewards(quest.rewards);
}
// Move to completed
this.activeQuests.delete(questId);
this.completedQuests.add(questId);
this.questHistory.push(quest);
// Notification
this.showQuestNotification({
title: 'Quest Complete!',
questTitle: quest.title,
description: 'Rewards granted',
icon: '🏆',
color: '#FFD700'
});
// Start next quest if exists
if (quest.nextQuest) {
setTimeout(() => {
this.startQuest(quest.nextQuest);
}, 2000); // 2 second delay
}
// If main quest, clear it
if (quest.isMainQuest) {
this.mainQuest = null;
}
console.log(`🏆 Quest Complete: ${quest.title}`);
// Emit event
this.scene.events.emit('questCompleted', { quest });
// Update UI
this.updateUI();
return true;
}
/**
* Grant quest rewards
*/
grantRewards(rewards) {
// XP
if (rewards.xp && this.scene.player) {
this.scene.player.addXP?.(rewards.xp);
console.log(`💫 Gained ${rewards.xp} XP`);
}
// Items
if (rewards.items && this.scene.inventorySystem) {
rewards.items.forEach(item => {
this.scene.inventorySystem.addItem(item.id, item.amount);
console.log(`📦 Received ${item.amount}x ${item.id}`);
});
}
// Bond Strength
if (rewards.bondStrength && this.scene.twinBondSystem) {
this.scene.twinBondSystem.changeBondStrength(rewards.bondStrength);
console.log(`💞 Bond Strength ${rewards.bondStrength > 0 ? '+' : ''}${rewards.bondStrength}`);
}
// Unlocks
if (rewards.unlocks) {
rewards.unlocks.forEach(unlock => {
this.unlockFeature(unlock);
});
}
}
/**
* Unlock feature/system
*/
unlockFeature(featureId) {
console.log(`🔓 Unlocked: ${featureId}`);
switch (featureId) {
case 'twin_bond_ui':
if (this.scene.twinBondSystem) {
this.scene.twinBondSystem.createBondUI();
}
break;
case 'zombie_commands':
// Already available through ZombieSystem
break;
case 'grave_crafting':
if (this.scene.recipeSystem) {
this.scene.recipeSystem.unlockRecipe('grave');
}
break;
case 'act_2':
console.log('🎬 ACT 2 UNLOCKED!');
// TODO: Transition to Act 2
break;
}
this.scene.events.emit('featureUnlocked', { featureId });
}
/**
* Trigger quest event
*/
triggerQuestEvent(event) {
if (event.type === 'twin_bond_message' && this.scene.twinBondSystem) {
setTimeout(() => {
this.scene.twinBondSystem.showTelepathicMessage(
event.message,
event.emotion
);
}, event.delay || 0);
}
}
/**
* Show quest dialogue
*/
showQuestDialogue(dialogue) {
// Simple text display for now
// TODO: Integrate with DialogueSystem
console.log(`💬 ${dialogue.speaker}: ${dialogue.text}`);
}
/**
* Show quest notification
*/
showQuestNotification(notification) {
const ui = this.scene.scene.get('UIScene');
if (ui && ui.showNotification) {
ui.showNotification(notification);
} else {
// Fallback
console.log(`📢 ${notification.icon} ${notification.title}: ${notification.questTitle}`);
}
}
/**
* Show objective notification
*/
showObjectiveNotification(description) {
const ui = this.scene.scene.get('UIScene');
if (ui && ui.showFloatingText) {
ui.showFloatingText({
x: this.scene.player?.x || 400,
y: this.scene.player?.y - 50 || 300,
text: `${description}`,
color: '#00FF00'
});
}
}
/**
* Check location objective
*/
checkLocationObjective(questId, objectiveId, playerX, playerY) {
const quest = this.activeQuests.get(questId);
if (!quest) return false;
const objective = quest.objectives.find(obj => obj.id === objectiveId);
if (!objective || objective.type !== 'location') return false;
const distance = Phaser.Math.Distance.Between(
playerX, playerY,
objective.target.x, objective.target.y
);
if (distance <= objective.target.radius) {
this.completeObjective(questId, objectiveId);
return true;
}
return false;
}
/**
* Update (check objectives)
*/
update(delta) {
// Check location objectives for active quests
if (this.scene.player) {
const playerX = this.scene.player.x;
const playerY = this.scene.player.y;
this.activeQuests.forEach((quest, questId) => {
quest.objectives.forEach(objective => {
if (objective.completed) return;
if (objective.type === 'location') {
this.checkLocationObjective(questId, objective.id, playerX, playerY);
}
});
});
}
}
/**
* Update UI
*/
updateUI() {
const ui = this.scene.scene.get('UIScene');
if (ui && ui.updateQuestTracker) {
ui.updateQuestTracker(this.mainQuest);
}
}
/**
* Getters
*/
isQuestActive(questId) {
return this.activeQuests.has(questId);
}
isQuestComplete(questId) {
return this.completedQuests.has(questId);
}
getActiveQuests() {
return Array.from(this.activeQuests.values());
}
getMainQuest() {
return this.mainQuest;
}
getQuestProgress(questId) {
const quest = this.activeQuests.get(questId);
if (!quest) return null;
const total = quest.objectives.length;
const completed = quest.objectives.filter(obj => obj.completed).length;
return {
total,
completed,
percentage: Math.round((completed / total) * 100)
};
}
}