Attempt to resolve issue where failed quests that are restarted retain their previous completed statuses until client restart

New function to purge completed condtions + remove status timers beyond what a newly started quest would have + add updated quest status object to `questsStatus` property on profile changes response object
This commit is contained in:
Dev 2023-11-29 23:36:31 +00:00
parent bfee07d5fe
commit a941a22305
2 changed files with 45 additions and 8 deletions

View File

@ -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;
}

View File

@ -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)