0
0
mirror of https://github.com/sp-tarkov/server.git synced 2025-02-12 16:10:43 -05:00

Fixed issue where player dying with a quest item would prevent the quest item from appearing in a raid again due to the profile flagging the quest item as being picked up

This commit is contained in:
Chomp 2024-11-24 15:47:03 +00:00
parent d2c0775b90
commit 7ba772d458
2 changed files with 73 additions and 1 deletions

View File

@ -1,6 +1,7 @@
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { BanType, Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase";
import { IItem } from "@spt/models/eft/common/tables/IItem";
import { ISptProfile } from "@spt/models/eft/profile/ISptProfile";
import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData";
import { AccountTypes } from "@spt/models/enums/AccountTypes";
@ -523,4 +524,13 @@ export class ProfileHelper {
pocket._tpl = newPocketTpl;
}
}
/**
* Return all quest items current in the supplied profile
* @param profile Profile to get quest items from
* @returns Array of item objects
*/
public getQuestItemsInProfile(profile: IPmcData): IItem[] {
return profile.Inventory.items.filter((item) => item.parentId === profile.Inventory.questRaidItems);
}
}

View File

@ -639,6 +639,10 @@ export class LocationLifecycleService {
const postRaidProfile = request.results.profile;
const preRaidProfileQuestDataClone = this.cloner.clone(pmcProfile.Quests);
// MUST occur BEFORE inventory actions occur
// Player died, quest items presist in the post raid profile
const lostQuestItems = this.profileHelper.getQuestItemsInProfile(postRaidProfile);
// Update inventory
this.inRaidHelper.setInventory(sessionId, pmcProfile, postRaidProfile, isSurvived, isTransfer);
@ -651,6 +655,12 @@ export class LocationLifecycleService {
pmcProfile.Achievements = postRaidProfile.Achievements;
pmcProfile.Quests = this.processPostRaidQuests(postRaidProfile.Quests);
if (lostQuestItems.length > 0) {
// MUST occur AFTER quests have post raid quest data has been merged
// Player is dead + had quest items, check and fix any broken find item quests
this.checkForAndFixPickupQuestsAfterDeath(sessionId, lostQuestItems, pmcProfile.Quests);
}
// Handle edge case - must occur AFTER processPostRaidQuests()
this.lightkeeperQuestWorkaround(sessionId, postRaidProfile.Quests, preRaidProfileQuestDataClone, pmcProfile);
@ -672,7 +682,7 @@ export class LocationLifecycleService {
// Copy fence values to Scav
scavProfile.TradersInfo[fenceId] = pmcProfile.TradersInfo[fenceId];
// Must occur after encyclopedia updated
// MUST occur AFTER encyclopedia updated
this.mergePmcAndScavEncyclopedias(pmcProfile, scavProfile);
// Remove skill fatigue values
@ -709,6 +719,58 @@ export class LocationLifecycleService {
this.handleInsuredItemLostEvent(sessionId, pmcProfile, request, locationName);
}
/**
* On death Quest items are lost, the client does not clean up completed conditions for picking up those quest items,
* If the completed conditions remain in the profile the player is unable to pick the item up again
* @param sessionId Session id
* @param lostQuestItems Quest items lost on player death
* @param profileQuests Quest status data from player profile
*/
protected checkForAndFixPickupQuestsAfterDeath(
sessionId: string,
lostQuestItems: IItem[],
profileQuests: IQuestStatus[],
) {
// Exclude completed quests
const activeQuestIdsInProfile = profileQuests
.filter((quest) => quest.status !== QuestStatus.Success)
.map((status) => status.qid);
// Get db details of quests we found above
const questDb = Object.values(this.databaseService.getQuests()).filter((x) =>
activeQuestIdsInProfile.includes(x._id),
);
for (const lostItem of lostQuestItems) {
for (const quest of questDb) {
// Find a quest in the db that has the lost item in one of its conditions that is also a 'find' type of condition
const matchingCondition = quest.conditions.AvailableForFinish.find(
(questCondition) =>
questCondition.conditionType === "FindItem" && questCondition.target.includes(lostItem._tpl),
);
if (!matchingCondition) {
// Quest doesnt have a matching condition
continue;
}
// We have a match, remove the condition id from profile to reset progress and let player pick item up again
const profileQuestToUpdate = profileQuests.find((questStatus) => questStatus.qid === quest._id);
if (!profileQuestToUpdate) {
// Profile doesnt have a matching quest
continue;
}
// Filter out the matching condition we found
profileQuestToUpdate.completedConditions = profileQuestToUpdate.completedConditions.filter(
(conditionId) => conditionId !== matchingCondition.id,
);
// We found and updated the relevant quest, no more work to do with this lost item
break;
}
}
}
/**
* In 0.15 Lightkeeper quests do not give rewards in PvE, this issue also occurs in spt
* We check for newly completed Lk quests and run them through the servers `CompleteQuest` process