diff --git a/project/src/controllers/QuestController.ts b/project/src/controllers/QuestController.ts index 534040b8..51d5c403 100644 --- a/project/src/controllers/QuestController.ts +++ b/project/src/controllers/QuestController.ts @@ -289,7 +289,7 @@ export class QuestController * @param pmcData Profile to update * @param acceptedQuest Quest accepted * @param sessionID Session id - * @returns client response + * @returns Client response */ public acceptQuest( pmcData: IPmcData, @@ -298,30 +298,32 @@ export class QuestController ): IItemEventRouterResponse { const acceptQuestResponse = this.eventOutputHolder.getOutput(sessionID); - - const startedState = QuestStatus.Started; - const newQuest = this.questHelper.getQuestReadyForProfile(pmcData, startedState, acceptedQuest); - + // Does quest exist in profile - if (pmcData.Quests.find((x) => x.qid === acceptedQuest.qid)) + // Restarting a quest can mean quest exists in profile + const existingQuestStatus = pmcData.Quests.find((x) => x.qid === acceptedQuest.qid) + if (existingQuestStatus) { // Update existing - this.questHelper.updateQuestState(pmcData, QuestStatus.Started, acceptedQuest.qid); + this.questHelper.resetQuestState(pmcData, QuestStatus.Started, acceptedQuest.qid); } else { // Add new quest to server profile + const newQuest = this.questHelper.getQuestReadyForProfile(pmcData, QuestStatus.Started, acceptedQuest); pmcData.Quests.push(newQuest); } // Create a dialog message for starting the quest. // Note that for starting quests, the correct locale field is "description", not "startedMessageText". const questFromDb = this.questHelper.getQuestFromDb(acceptedQuest.qid, pmcData); + // Get messageId of text to send to player as text message in game const messageId = this.questHelper.getMessageIdForQuestStart( questFromDb.startedMessageText, questFromDb.description, ); + const startedQuestRewards = this.questHelper.applyQuestReward( pmcData, acceptedQuest.qid, @@ -341,7 +343,14 @@ export class QuestController acceptQuestResponse.profileChanges[sessionID].quests = this.questHelper .getNewlyAccessibleQuestsWhenStartingQuest(acceptedQuest.qid, sessionID); - + + // Quest already existed, probably a fail/restart + // Need to send client an empty list of completedConditions + if (existingQuestStatus) + { + acceptQuestResponse.profileChanges[sessionID].questsStatus = [ existingQuestStatus ]; + } + return acceptQuestResponse; } diff --git a/project/src/helpers/QuestHelper.ts b/project/src/helpers/QuestHelper.ts index 1c884217..d13798a0 100644 --- a/project/src/helpers/QuestHelper.ts +++ b/project/src/helpers/QuestHelper.ts @@ -733,6 +733,34 @@ export class QuestHelper } } + /** + * Resets a quests values back to its chosen state + * @param pmcData Profile to update + * @param newQuestState New state the quest should be in + * @param questId Id of the quest to alter the status of + */ + public resetQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void + { + const questToUpdate = pmcData.Quests.find((quest) => quest.qid === questId); + if (questToUpdate) + { + questToUpdate.status = newQuestState; + questToUpdate.statusTimers[newQuestState] = this.timeUtil.getTimestamp(); + + // Delete all status timers after the new status + for (const statusKey in questToUpdate.statusTimers) + { + if (Number.parseInt(statusKey) > newQuestState) + { + delete questToUpdate.statusTimers[statusKey] + } + } + + // Remove all completed conditions + questToUpdate.completedConditions = []; + } + } + /** * Give player quest rewards - Skills/exp/trader standing/items/assort unlocks - Returns reward items player earned * @param profileData Player profile (scav or pmc)