824 lines
27 KiB
JavaScript
824 lines
27 KiB
JavaScript
/**
|
|
* Galaxy Strike Online - Server Quest System
|
|
* Manages quests, progress tracking, and rewards
|
|
*/
|
|
|
|
class QuestSystem {
|
|
constructor() {
|
|
this.quests = new Map();
|
|
this.playerQuests = new Map(); // userId -> quest data
|
|
this.initializeQuests();
|
|
}
|
|
|
|
initializeQuests() {
|
|
// Tutorial quests
|
|
this.addQuest('tutorial_first_battle', {
|
|
name: 'First Battle',
|
|
description: 'Complete your first battle to learn the basics',
|
|
type: 'tutorial',
|
|
difficulty: 'easy',
|
|
requirements: {
|
|
battlesWon: 1
|
|
},
|
|
rewards: {
|
|
experience: 100,
|
|
credits: 500,
|
|
items: ['health_kit', 'energy_pack']
|
|
},
|
|
prerequisites: [],
|
|
repeatable: false,
|
|
timeLimit: null
|
|
});
|
|
|
|
// Main Story quests
|
|
this.addQuest('main_story_beginning', {
|
|
name: 'The Beginning',
|
|
description: 'Start your journey as a space pilot',
|
|
type: 'main',
|
|
difficulty: 'easy',
|
|
requirements: {
|
|
level: 1,
|
|
battlesWon: 1
|
|
},
|
|
rewards: {
|
|
experience: 200,
|
|
credits: 1000,
|
|
skillPoints: 2
|
|
},
|
|
prerequisites: [],
|
|
repeatable: false,
|
|
timeLimit: null
|
|
});
|
|
|
|
this.addQuest('main_story_first_dungeon', {
|
|
name: 'First Dungeon',
|
|
description: 'Complete your first dungeon run',
|
|
type: 'main',
|
|
difficulty: 'medium',
|
|
requirements: {
|
|
level: 5,
|
|
dungeonsCleared: 1
|
|
},
|
|
rewards: {
|
|
experience: 500,
|
|
credits: 2000,
|
|
items: ['rare_weapon']
|
|
},
|
|
prerequisites: ['main_story_beginning'],
|
|
repeatable: false,
|
|
timeLimit: null
|
|
});
|
|
|
|
this.addQuest('main_story_space_exploration', {
|
|
name: 'Space Explorer',
|
|
description: 'Explore 10 different sectors',
|
|
type: 'main',
|
|
difficulty: 'medium',
|
|
requirements: {
|
|
level: 10,
|
|
sectorsExplored: 10
|
|
},
|
|
rewards: {
|
|
experience: 1000,
|
|
credits: 5000,
|
|
items: ['explorer_badge']
|
|
},
|
|
prerequisites: ['main_story_first_dungeon'],
|
|
repeatable: false,
|
|
timeLimit: null
|
|
});
|
|
|
|
// Daily quests
|
|
this.addQuest('daily_battles', {
|
|
name: 'Daily Battles',
|
|
description: 'Win 5 battles today',
|
|
type: 'daily',
|
|
difficulty: 'easy',
|
|
requirements: {
|
|
battlesWon: 5
|
|
},
|
|
rewards: {
|
|
experience: 150,
|
|
credits: 750,
|
|
gems: 5
|
|
},
|
|
prerequisites: [],
|
|
repeatable: true,
|
|
timeLimit: 24 * 60 * 60 * 1000 // 24 hours
|
|
});
|
|
|
|
this.addQuest('daily_exploration', {
|
|
name: 'Daily Exploration',
|
|
description: 'Explore 3 new sectors today',
|
|
type: 'daily',
|
|
difficulty: 'easy',
|
|
requirements: {
|
|
sectorsExplored: 3
|
|
},
|
|
rewards: {
|
|
experience: 100,
|
|
credits: 500,
|
|
gems: 3
|
|
},
|
|
prerequisites: [],
|
|
repeatable: true,
|
|
timeLimit: 24 * 60 * 60 * 1000 // 24 hours
|
|
});
|
|
|
|
this.addQuest('daily_resources', {
|
|
name: 'Daily Resource Collection',
|
|
description: 'Collect 1000 resources today',
|
|
type: 'daily',
|
|
difficulty: 'medium',
|
|
requirements: {
|
|
resourcesCollected: 1000
|
|
},
|
|
rewards: {
|
|
experience: 200,
|
|
credits: 1000,
|
|
gems: 8
|
|
},
|
|
prerequisites: [],
|
|
repeatable: true,
|
|
timeLimit: 24 * 60 * 60 * 1000 // 24 hours
|
|
});
|
|
|
|
// Weekly quests
|
|
this.addQuest('weekly_champion', {
|
|
name: 'Weekly Champion',
|
|
description: 'Win 50 battles this week',
|
|
type: 'weekly',
|
|
difficulty: 'hard',
|
|
requirements: {
|
|
battlesWon: 50
|
|
},
|
|
rewards: {
|
|
experience: 2000,
|
|
credits: 10000,
|
|
gems: 50,
|
|
items: ['champion_title']
|
|
},
|
|
prerequisites: [],
|
|
repeatable: true,
|
|
timeLimit: 7 * 24 * 60 * 60 * 1000 // 7 days
|
|
});
|
|
|
|
this.addQuest('weekly_dungeon_master', {
|
|
name: 'Weekly Dungeon Master',
|
|
description: 'Complete 10 dungeons this week',
|
|
type: 'weekly',
|
|
difficulty: 'hard',
|
|
requirements: {
|
|
dungeonsCleared: 10
|
|
},
|
|
rewards: {
|
|
experience: 3000,
|
|
credits: 15000,
|
|
gems: 75,
|
|
items: ['dungeon_master_cape']
|
|
},
|
|
prerequisites: [],
|
|
repeatable: true,
|
|
timeLimit: 7 * 24 * 60 * 60 * 1000 // 7 days
|
|
});
|
|
|
|
this.addQuest('weekly_wealth_collector', {
|
|
name: 'Weekly Wealth Collector',
|
|
description: 'Earn 10000 credits this week',
|
|
type: 'weekly',
|
|
difficulty: 'medium',
|
|
requirements: {
|
|
creditsEarned: 10000
|
|
},
|
|
rewards: {
|
|
experience: 1500,
|
|
credits: 5000,
|
|
gems: 25
|
|
},
|
|
prerequisites: [],
|
|
repeatable: true,
|
|
timeLimit: 7 * 24 * 60 * 60 * 1000 // 7 days
|
|
});
|
|
|
|
// Combat quests
|
|
this.addQuest('warrior_path', {
|
|
name: 'Warrior Path',
|
|
description: 'Win 10 battles to prove your combat skills',
|
|
type: 'combat',
|
|
difficulty: 'medium',
|
|
requirements: {
|
|
battlesWon: 10,
|
|
enemiesDefeated: 50
|
|
},
|
|
rewards: {
|
|
experience: 500,
|
|
credits: 2000,
|
|
items: ['basic_armor']
|
|
},
|
|
prerequisites: ['tutorial_first_battle'],
|
|
repeatable: false,
|
|
timeLimit: null
|
|
});
|
|
|
|
// Crafting quests
|
|
this.addQuest('novice_crafter', {
|
|
name: 'Novice Crafter',
|
|
description: 'Craft 5 items to learn the basics of crafting',
|
|
type: 'crafting',
|
|
difficulty: 'easy',
|
|
requirements: {
|
|
itemsCrafted: 5
|
|
},
|
|
rewards: {
|
|
experience: 200,
|
|
credits: 1000,
|
|
craftingExperience: 100
|
|
},
|
|
prerequisites: [],
|
|
repeatable: false,
|
|
timeLimit: null
|
|
});
|
|
|
|
// Exploration quests
|
|
this.addQuest('explorer_spirit', {
|
|
name: 'Explorer Spirit',
|
|
description: 'Discover 5 different locations in the galaxy',
|
|
type: 'exploration',
|
|
difficulty: 'medium',
|
|
requirements: {
|
|
locationsDiscovered: 5
|
|
},
|
|
rewards: {
|
|
experience: 300,
|
|
credits: 1500,
|
|
items: ['navigation_device']
|
|
},
|
|
prerequisites: ['tutorial_first_battle'],
|
|
repeatable: false,
|
|
timeLimit: null
|
|
});
|
|
|
|
// Daily quests
|
|
this.addQuest('daily_bounty', {
|
|
name: 'Daily Bounty',
|
|
description: 'Complete 3 battles today',
|
|
type: 'daily',
|
|
difficulty: 'easy',
|
|
requirements: {
|
|
battlesWon: 3
|
|
},
|
|
rewards: {
|
|
experience: 150,
|
|
credits: 750
|
|
},
|
|
prerequisites: [],
|
|
repeatable: true,
|
|
timeLimit: 86400000 // 24 hours
|
|
});
|
|
|
|
// Weekly quests
|
|
this.addQuest('weekly_champion', {
|
|
name: 'Weekly Champion',
|
|
description: 'Win 20 battles this week',
|
|
type: 'weekly',
|
|
difficulty: 'hard',
|
|
requirements: {
|
|
battlesWon: 20
|
|
},
|
|
rewards: {
|
|
experience: 1000,
|
|
credits: 5000,
|
|
items: ['rare_weapon_part']
|
|
},
|
|
prerequisites: [],
|
|
repeatable: true,
|
|
timeLimit: 604800000 // 7 days
|
|
});
|
|
}
|
|
|
|
addQuest(id, quest) {
|
|
this.quests.set(id, {
|
|
id,
|
|
...quest,
|
|
createdAt: new Date().toISOString()
|
|
});
|
|
}
|
|
|
|
getQuest(id) {
|
|
return this.quests.get(id);
|
|
}
|
|
|
|
getAllQuests() {
|
|
return Array.from(this.quests.values());
|
|
}
|
|
|
|
getQuestsByType(type) {
|
|
return Array.from(this.quests.values()).filter(quest => quest.type === type);
|
|
}
|
|
|
|
getQuestsByDifficulty(difficulty) {
|
|
return Array.from(this.quests.values()).filter(quest => quest.difficulty === difficulty);
|
|
}
|
|
|
|
initializePlayerData(userId) {
|
|
if (!this.playerQuests.has(userId)) {
|
|
const playerData = {
|
|
activeQuests: new Map(),
|
|
completedQuests: new Map(),
|
|
questHistory: [],
|
|
totalQuestsCompleted: 0,
|
|
dailyQuestsCompleted: 0,
|
|
weeklyQuestsCompleted: 0
|
|
};
|
|
|
|
// Assign starting quests to new players
|
|
this.assignStartingQuests(userId, playerData);
|
|
|
|
this.playerQuests.set(userId, playerData);
|
|
}
|
|
return this.playerQuests.get(userId);
|
|
}
|
|
|
|
assignStartingQuests(userId, playerData) {
|
|
console.log(`[QUEST SYSTEM] Assigning starting quests to player ${userId}`);
|
|
|
|
// Assign main story quests
|
|
const mainStoryQuests = ['main_story_beginning', 'main_story_first_dungeon'];
|
|
mainStoryQuests.forEach(questId => {
|
|
const quest = this.quests.get(questId);
|
|
if (quest && !playerData.activeQuests.has(questId) && !playerData.completedQuests.has(questId)) {
|
|
playerData.activeQuests.set(questId, {
|
|
...quest,
|
|
progress: 0,
|
|
startedAt: Date.now()
|
|
});
|
|
console.log(`[QUEST SYSTEM] Assigned main story quest: ${quest.name}`);
|
|
}
|
|
});
|
|
|
|
// Assign daily quests
|
|
this.generateDailyQuests(userId, playerData);
|
|
|
|
// Assign weekly quests
|
|
this.generateWeeklyQuests(userId, playerData);
|
|
|
|
console.log(`[QUEST SYSTEM] Player now has ${playerData.activeQuests.size} active quests`);
|
|
}
|
|
|
|
generateDailyQuests(userId, playerData) {
|
|
console.log(`[QUEST SYSTEM] Generating daily quests for player ${userId}`);
|
|
|
|
const dailyQuestTemplates = ['daily_battles', 'daily_exploration', 'daily_resources'];
|
|
|
|
dailyQuestTemplates.forEach(questId => {
|
|
const quest = this.quests.get(questId);
|
|
if (quest) {
|
|
playerData.activeQuests.set(questId, {
|
|
...quest,
|
|
progress: 0,
|
|
startedAt: Date.now(),
|
|
type: 'daily',
|
|
resetTime: Date.now() + (24 * 60 * 60 * 1000) // 24 hours from now
|
|
});
|
|
console.log(`[QUEST SYSTEM] Assigned daily quest: ${quest.name}`);
|
|
}
|
|
});
|
|
}
|
|
|
|
generateWeeklyQuests(userId, playerData) {
|
|
console.log(`[QUEST SYSTEM] Generating weekly quests for player ${userId}`);
|
|
|
|
const weeklyQuestTemplates = ['weekly_champion', 'weekly_dungeon_master', 'weekly_wealth_collector'];
|
|
|
|
weeklyQuestTemplates.forEach(questId => {
|
|
const quest = this.quests.get(questId);
|
|
if (quest) {
|
|
playerData.activeQuests.set(questId, {
|
|
...quest,
|
|
progress: 0,
|
|
startedAt: Date.now(),
|
|
type: 'weekly',
|
|
resetTime: Date.now() + (7 * 24 * 60 * 60 * 1000) // 7 days from now
|
|
});
|
|
console.log(`[QUEST SYSTEM] Assigned weekly quest: ${quest.name}`);
|
|
}
|
|
});
|
|
}
|
|
|
|
getPlayerData(userId) {
|
|
return this.playerQuests.get(userId) || this.initializePlayerData(userId);
|
|
}
|
|
|
|
getAvailableQuests(userId) {
|
|
const playerData = this.getPlayerData(userId);
|
|
const availableQuests = [];
|
|
|
|
for (const [questId, quest] of this.quests) {
|
|
// Skip if already active or completed (for non-repeatable quests)
|
|
if (playerData.activeQuests.has(questId)) continue;
|
|
if (playerData.completedQuests.has(questId) && !quest.repeatable) continue;
|
|
|
|
// Check prerequisites
|
|
const prerequisitesMet = quest.prerequisites.every(prereqId =>
|
|
playerData.completedQuests.has(prereqId)
|
|
);
|
|
|
|
if (prerequisitesMet) {
|
|
availableQuests.push({
|
|
...quest,
|
|
status: playerData.activeQuests.has(questId) ? 'active' : 'available'
|
|
});
|
|
}
|
|
}
|
|
|
|
return availableQuests;
|
|
}
|
|
|
|
startQuest(userId, questId) {
|
|
const quest = this.getQuest(questId);
|
|
if (!quest) {
|
|
throw new Error('Quest not found');
|
|
}
|
|
|
|
const playerData = this.getPlayerData(userId);
|
|
|
|
// Check if quest is already active
|
|
if (playerData.activeQuests.has(questId)) {
|
|
throw new Error('Quest already active');
|
|
}
|
|
|
|
// Check if quest is completed and not repeatable
|
|
if (playerData.completedQuests.has(questId) && !quest.repeatable) {
|
|
throw new Error('Quest already completed');
|
|
}
|
|
|
|
// Check prerequisites
|
|
const prerequisitesMet = quest.prerequisites.every(prereqId =>
|
|
playerData.completedQuests.has(prereqId)
|
|
);
|
|
|
|
if (!prerequisitesMet) {
|
|
throw new Error('Prerequisites not met');
|
|
}
|
|
|
|
// Start the quest
|
|
const questProgress = {
|
|
questId,
|
|
startedAt: new Date().toISOString(),
|
|
progress: {},
|
|
completed: false,
|
|
expiredAt: quest.timeLimit ? new Date(Date.now() + quest.timeLimit).toISOString() : null
|
|
};
|
|
|
|
// Initialize progress tracking
|
|
for (const requirement of Object.keys(quest.requirements)) {
|
|
questProgress.progress[requirement] = 0;
|
|
}
|
|
|
|
playerData.activeQuests.set(questId, questProgress);
|
|
|
|
return {
|
|
success: true,
|
|
quest,
|
|
progress: questProgress
|
|
};
|
|
}
|
|
|
|
updateQuestProgress(userId, questId, progressUpdates) {
|
|
const playerData = this.getPlayerData(userId);
|
|
const activeQuest = playerData.activeQuests.get(questId);
|
|
|
|
if (!activeQuest) {
|
|
throw new Error('Quest not active');
|
|
}
|
|
|
|
// Check if quest is expired
|
|
if (activeQuest.expiredAt && new Date() > new Date(activeQuest.expiredAt)) {
|
|
playerData.activeQuests.delete(questId);
|
|
throw new Error('Quest expired');
|
|
}
|
|
|
|
const quest = this.getQuest(questId);
|
|
let updated = false;
|
|
|
|
// Update progress
|
|
for (const [requirement, amount] of Object.entries(progressUpdates)) {
|
|
if (quest.requirements[requirement] !== undefined) {
|
|
activeQuest.progress[requirement] = Math.min(
|
|
activeQuest.progress[requirement] + amount,
|
|
quest.requirements[requirement]
|
|
);
|
|
updated = true;
|
|
}
|
|
}
|
|
|
|
// Check if quest is completed
|
|
const isCompleted = Object.entries(quest.requirements).every(
|
|
([requirement, requiredAmount]) =>
|
|
activeQuest.progress[requirement] >= requiredAmount
|
|
);
|
|
|
|
if (isCompleted && !activeQuest.completed) {
|
|
activeQuest.completed = true;
|
|
activeQuest.completedAt = new Date().toISOString();
|
|
|
|
return {
|
|
success: true,
|
|
questCompleted: true,
|
|
quest,
|
|
progress: activeQuest.progress
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
questCompleted: false,
|
|
quest,
|
|
progress: activeQuest.progress,
|
|
updated
|
|
};
|
|
}
|
|
|
|
completeQuest(userId, questId) {
|
|
const playerData = this.getPlayerData(userId);
|
|
const activeQuest = playerData.activeQuests.get(questId);
|
|
|
|
if (!activeQuest) {
|
|
throw new Error('Quest not active');
|
|
}
|
|
|
|
if (!activeQuest.completed) {
|
|
throw new Error('Quest requirements not met');
|
|
}
|
|
|
|
const quest = this.getQuest(questId);
|
|
|
|
// Move to completed quests
|
|
playerData.completedQuests.set(questId, {
|
|
...activeQuest,
|
|
quest,
|
|
completedAt: new Date().toISOString()
|
|
});
|
|
|
|
// Remove from active quests
|
|
playerData.activeQuests.delete(questId);
|
|
|
|
// Update statistics
|
|
playerData.totalQuestsCompleted += 1;
|
|
|
|
if (quest.type === 'daily') {
|
|
playerData.dailyQuestsCompleted += 1;
|
|
} else if (quest.type === 'weekly') {
|
|
playerData.weeklyQuestsCompleted += 1;
|
|
}
|
|
|
|
// Add to history
|
|
playerData.questHistory.push({
|
|
questId,
|
|
questName: quest.name,
|
|
completedAt: new Date().toISOString(),
|
|
rewards: quest.rewards
|
|
});
|
|
|
|
// Keep only last 100 quest records
|
|
if (playerData.questHistory.length > 100) {
|
|
playerData.questHistory = playerData.questHistory.slice(-100);
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
quest,
|
|
rewards: quest.rewards,
|
|
statistics: {
|
|
totalCompleted: playerData.totalQuestsCompleted,
|
|
dailyCompleted: playerData.dailyQuestsCompleted,
|
|
weeklyCompleted: playerData.weeklyQuestsCompleted
|
|
}
|
|
};
|
|
}
|
|
|
|
getPlayerActiveQuests(userId) {
|
|
const playerData = this.getPlayerData(userId);
|
|
const activeQuests = [];
|
|
|
|
for (const [questId, progress] of playerData.activeQuests) {
|
|
const quest = this.getQuest(questId);
|
|
activeQuests.push({
|
|
...quest,
|
|
progress: progress.progress,
|
|
startedAt: progress.startedAt,
|
|
expiredAt: progress.expiredAt
|
|
});
|
|
}
|
|
|
|
return activeQuests;
|
|
}
|
|
|
|
getPlayerCompletedQuests(userId) {
|
|
const playerData = this.getPlayerData(userId);
|
|
const completedQuests = [];
|
|
|
|
for (const [questId, completion] of playerData.completedQuests) {
|
|
completedQuests.push({
|
|
...completion.quest,
|
|
completedAt: completion.completedAt,
|
|
progress: completion.progress
|
|
});
|
|
}
|
|
|
|
return completedQuests;
|
|
}
|
|
|
|
getQuestStatistics(userId) {
|
|
const playerData = this.getPlayerData(userId);
|
|
const availableQuests = this.getAvailableQuests(userId);
|
|
|
|
return {
|
|
activeQuests: playerData.activeQuests.size,
|
|
completedQuests: playerData.completedQuests.size,
|
|
availableQuests: availableQuests.length,
|
|
totalCompleted: playerData.totalQuestsCompleted,
|
|
dailyCompleted: playerData.dailyQuestsCompleted,
|
|
weeklyCompleted: playerData.weeklyQuestsCompleted,
|
|
recentHistory: playerData.questHistory.slice(-10)
|
|
};
|
|
}
|
|
|
|
resetDailyQuests(userId) {
|
|
const playerData = this.getPlayerData(userId);
|
|
|
|
// Remove completed daily quests
|
|
for (const [questId, quest] of this.quests) {
|
|
if (quest.type === 'daily') {
|
|
playerData.completedQuests.delete(questId);
|
|
playerData.activeQuests.delete(questId);
|
|
}
|
|
}
|
|
|
|
playerData.dailyQuestsCompleted = 0;
|
|
|
|
return { success: true, message: 'Daily quests reset' };
|
|
}
|
|
|
|
getPlayerQuests(userId) {
|
|
console.log('[QUEST SYSTEM] Getting quests for user:', userId);
|
|
|
|
// Get or create player data
|
|
let playerData = this.playerQuests.get(userId);
|
|
if (!playerData) {
|
|
playerData = {
|
|
activeQuests: new Map(),
|
|
completedQuests: new Map(),
|
|
failedQuests: new Map()
|
|
};
|
|
this.playerQuests.set(userId, playerData);
|
|
}
|
|
|
|
// Prepare quest data for client
|
|
const questData = {
|
|
mainQuests: [],
|
|
dailyQuests: [],
|
|
weeklyQuests: [],
|
|
activeQuests: [],
|
|
completedQuests: [],
|
|
failedQuests: []
|
|
};
|
|
|
|
// Add main quests
|
|
for (const [questId, quest] of this.quests) {
|
|
if (quest.type === 'main') {
|
|
const playerQuest = playerData.activeQuests.get(questId) || playerData.completedQuests.get(questId) || playerData.failedQuests.get(questId);
|
|
const status = playerQuest ? playerQuest.status : 'available';
|
|
|
|
questData.mainQuests.push({
|
|
...quest,
|
|
status: status,
|
|
objectives: quest.objectives.map(obj => ({
|
|
...obj,
|
|
current: playerQuest && playerQuest.objectives && playerQuest.objectives[obj.id] ? playerQuest.objectives[obj.id].current || 0 : 0
|
|
}))
|
|
});
|
|
}
|
|
}
|
|
|
|
// Add daily quests
|
|
for (const [questId, quest] of this.quests) {
|
|
if (quest.type === 'daily') {
|
|
const playerQuest = playerData.activeQuests.get(questId) || playerData.completedQuests.get(questId) || playerData.failedQuests.get(questId);
|
|
const status = playerQuest ? playerQuest.status : 'available';
|
|
|
|
questData.dailyQuests.push({
|
|
...quest,
|
|
status: status,
|
|
objectives: quest.objectives.map(obj => ({
|
|
...obj,
|
|
current: playerQuest && playerQuest.objectives && playerQuest.objectives[obj.id] ? playerQuest.objectives[obj.id].current || 0 : 0
|
|
}))
|
|
});
|
|
}
|
|
}
|
|
|
|
// Add weekly quests
|
|
for (const [questId, quest] of this.quests) {
|
|
if (quest.type === 'weekly') {
|
|
const playerQuest = playerData.activeQuests.get(questId) || playerData.completedQuests.get(questId) || playerData.failedQuests.get(questId);
|
|
const status = playerQuest ? playerQuest.status : 'available';
|
|
|
|
questData.weeklyQuests.push({
|
|
...quest,
|
|
status: status,
|
|
objectives: quest.objectives.map(obj => ({
|
|
...obj,
|
|
current: playerQuest && playerQuest.objectives && playerQuest.objectives[obj.id] ? playerQuest.objectives[obj.id].current || 0 : 0
|
|
}))
|
|
});
|
|
}
|
|
}
|
|
|
|
// Add active quests (for compatibility)
|
|
questData.activeQuests = Array.from(playerData.activeQuests.values());
|
|
questData.completedQuests = Array.from(playerData.completedQuests.values());
|
|
questData.failedQuests = Array.from(playerData.failedQuests.values());
|
|
|
|
console.log('[QUEST SYSTEM] Returning quest data:', {
|
|
mainQuests: questData.mainQuests.length,
|
|
dailyQuests: questData.dailyQuests.length,
|
|
weeklyQuests: questData.weeklyQuests.length,
|
|
activeQuests: questData.activeQuests.length,
|
|
completedQuests: questData.completedQuests.length
|
|
});
|
|
|
|
return questData;
|
|
}
|
|
|
|
completeQuest(userId, questId, rewards = null) {
|
|
console.log('[QUEST SYSTEM] Completing quest:', questId, 'for user:', userId);
|
|
|
|
const playerData = this.playerQuests.get(userId);
|
|
if (!playerData) {
|
|
console.log('[QUEST SYSTEM] Player data not found for user:', userId);
|
|
return { success: false, error: 'Player not found' };
|
|
}
|
|
|
|
const quest = this.quests.get(questId);
|
|
if (!quest) {
|
|
console.log('[QUEST SYSTEM] Quest not found:', questId);
|
|
return { success: false, error: 'Quest not found' };
|
|
}
|
|
|
|
// Move quest from active to completed
|
|
const activeQuest = playerData.activeQuests.get(questId);
|
|
if (activeQuest) {
|
|
// Mark all objectives as completed
|
|
const completedQuest = {
|
|
...activeQuest,
|
|
status: 'completed',
|
|
completedAt: Date.now(),
|
|
objectives: quest.objectives.map(obj => ({
|
|
...obj,
|
|
current: obj.target
|
|
}))
|
|
};
|
|
|
|
playerData.activeQuests.delete(questId);
|
|
playerData.completedQuests.set(questId, completedQuest);
|
|
|
|
console.log('[QUEST SYSTEM] Quest completed successfully:', questId);
|
|
return { success: true, quest: completedQuest };
|
|
} else {
|
|
// Quest might not be active, try to complete it anyway
|
|
const completedQuest = {
|
|
...quest,
|
|
status: 'completed',
|
|
completedAt: Date.now(),
|
|
objectives: quest.objectives.map(obj => ({
|
|
...obj,
|
|
current: obj.target
|
|
}))
|
|
};
|
|
|
|
playerData.completedQuests.set(questId, completedQuest);
|
|
console.log('[QUEST SYSTEM] Quest force-completed:', questId);
|
|
return { success: true, quest: completedQuest };
|
|
}
|
|
}
|
|
|
|
resetWeeklyQuests(userId) {
|
|
const playerData = this.getPlayerData(userId);
|
|
|
|
// Remove completed weekly quests
|
|
for (const [questId, quest] of this.quests) {
|
|
if (quest.type === 'weekly') {
|
|
playerData.completedQuests.delete(questId);
|
|
playerData.activeQuests.delete(questId);
|
|
}
|
|
}
|
|
|
|
playerData.weeklyQuestsCompleted = 0;
|
|
|
|
return { success: true, message: 'Weekly quests reset' };
|
|
}
|
|
}
|
|
|
|
module.exports = QuestSystem;
|