/** * QuestSystem — thin wrapper around ContentLoader for quest definitions. */ class QuestSystem { constructor(contentLoader) { this.loader = contentLoader; this.playerQuests = new Map(); } getAllQuests() { return this.loader.getAllQuests(); } getQuest(id) { return this.loader.getQuest(id); } getQuestsByCategory(cat) { return this.loader.getQuestsByCategory(cat); } getQuestCategories() { return this.loader.getQuestCategories(); } initializePlayerData(userId) { if (this.playerQuests.has(userId)) return this.playerQuests.get(userId); const data = { active: {}, completed: [], failed: [] }; this.playerQuests.set(userId, data); return data; } getPlayerData(userId) { return this.initializePlayerData(userId); } getPlayerQuests(userId) { return this.initializePlayerData(userId); } startQuest(userId, questId) { const quest = this.loader.getQuest(questId); if (!quest) return { success: false, error: 'Quest not found' }; const pd = this.initializePlayerData(userId); if (pd.active[questId]) return { success: false, error: 'Already active' }; const objectives = {}; for (const obj of (quest.objectives || [])) { objectives[obj.id] = { progress: 0, complete: false }; } pd.active[questId] = { startedAt: Date.now(), objectives }; return { success: true, quest }; } completeQuest(userId, questId, rewards) { const pd = this.initializePlayerData(userId); delete pd.active[questId]; if (!pd.completed.includes(questId)) pd.completed.push(questId); return { success: true, questId, rewards }; } updateObjective(userId, questId, objectiveId, amount = 1) { const pd = this.initializePlayerData(userId); const state = pd.active[questId]; if (!state) return null; const quest = this.loader.getQuest(questId); const objDef = quest?.objectives?.find(o => o.id === objectiveId); if (!objDef) return null; const obj = state.objectives[objectiveId] || { progress: 0, complete: false }; obj.progress = Math.min(obj.progress + amount, objDef.target); obj.complete = obj.progress >= objDef.target; state.objectives[objectiveId] = obj; const allDone = quest.objectives.every(o => state.objectives[o.id]?.complete); if (allDone) return this.completeQuest(userId, questId, quest.rewards); return { questId, objectiveId, progress: obj.progress, completed: false }; } } module.exports = QuestSystem;