From 9b16af7cb669c4d97347ee27dcbded39bb39800e Mon Sep 17 00:00:00 2001 From: Chomp Date: Tue, 7 Jan 2025 12:47:32 +0000 Subject: [PATCH] On quest completion, store hideout customisation unlocks inside profile json Append the unlock customisations to results of `client/customization/storage` call Added `hideoutCustomisationUnlocks` to profile on creation --- .../controllers/CustomizationController.ts | 9 ++++- project/src/helpers/ProfileHelper.ts | 38 +++++++++++++++++++ project/src/helpers/QuestHelper.ts | 11 +++++- .../common/tables/ICustomisationStorage.ts | 2 +- project/src/models/eft/profile/ISptProfile.ts | 2 + 5 files changed, 59 insertions(+), 3 deletions(-) diff --git a/project/src/controllers/CustomizationController.ts b/project/src/controllers/CustomizationController.ts index 04797bcb..52a1ce44 100644 --- a/project/src/controllers/CustomizationController.ts +++ b/project/src/controllers/CustomizationController.ts @@ -230,8 +230,12 @@ export class CustomizationController { public getCustomisationStorage(sessionID: string, info: IEmptyRequestData): ICustomisationStorage[] { const customisationResultsClone = this.cloner.clone(this.databaseService.getTemplates().customisationStorage); - // Some game versions have additional dogtag variants, add them const profile = this.profileHelper.getFullProfile(sessionID); + if (!profile) { + return customisationResultsClone; + } + + // Some game versions have additional dogtag variants, add them switch (this.getGameEdition(profile)) { case GameEditions.EDGE_OF_DARKNESS: // Gets EoD tags @@ -295,6 +299,9 @@ export class CustomizationController { } } + // Append on customisations unlocked by player to results + customisationResultsClone.push(...(profile.hideoutCustomisationUnlocks ?? [])); + return customisationResultsClone; } diff --git a/project/src/helpers/ProfileHelper.ts b/project/src/helpers/ProfileHelper.ts index e0b3cb8e..344007d8 100644 --- a/project/src/helpers/ProfileHelper.ts +++ b/project/src/helpers/ProfileHelper.ts @@ -1,7 +1,9 @@ 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 { ICustomisationStorage } from "@spt/models/eft/common/tables/ICustomisationStorage"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { IQuestReward } from "@spt/models/eft/common/tables/IQuest"; import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISpt, ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; @@ -607,4 +609,40 @@ export class ProfileHelper { return fullFavorites; } + + /** + * Store a hideout customisation unlock inside a profile + * @param fullProfile Profile to add unlock to + * @param reward reward given to player with customisation data + * @param source Source of reward, e.g. "unlockedInGame" for quests and "achievement" for achievements + */ + public addHideoutCustomisationUnlock(fullProfile: ISptProfile, reward: IQuestReward, source: string): void { + // Get matching db data for reward + const hideoutCustomisationDb = this.databaseService + .getHideout() + .customisation.globals.find((customisation) => customisation.itemId === reward.target); + if (!hideoutCustomisationDb) { + this.logger.warning( + `Unable to add hideout customisaiton reward: ${reward.target} to profile: ${fullProfile.info.id} as matching object cannot be found in hideout/customisation.json`, + ); + + return; + } + + fullProfile.hideoutCustomisationUnlocks ||= []; + if (fullProfile.hideoutCustomisationUnlocks?.some((unlock) => unlock.id === hideoutCustomisationDb.id)) { + this.logger.warning( + `Profile: ${fullProfile.info.id} already has hideout customisaiton reward: ${reward.target}, skipping`, + ); + return; + } + + const rewardToStore: ICustomisationStorage = { + id: hideoutCustomisationDb.id, + source: source, + type: hideoutCustomisationDb.type, + }; + + fullProfile.hideoutCustomisationUnlocks.push(rewardToStore); + } } diff --git a/project/src/helpers/QuestHelper.ts b/project/src/helpers/QuestHelper.ts index 55c3d709..35b0bfa0 100644 --- a/project/src/helpers/QuestHelper.ts +++ b/project/src/helpers/QuestHelper.ts @@ -919,7 +919,13 @@ export class QuestHelper { ): IItem[] { // Repeatable quest base data is always in PMCProfile, `profileData` may be scav profile // TODO: consider moving repeatable quest data to profile-agnostic location - const pmcProfile = this.profileHelper.getPmcProfile(sessionId); + const fullProfile = this.profileHelper.getFullProfile(sessionId); + const pmcProfile = fullProfile?.characters.pmc; + if (!pmcProfile) { + this.logger.error(`Unable to get pmc profile for: ${sessionId}, no rewards given`); + return []; + } + let questDetails = this.getQuestFromDb(questId, pmcProfile); if (!questDetails) { this.logger.warning( @@ -990,6 +996,9 @@ export class QuestHelper { case QuestRewardType.POCKETS: this.profileHelper.replaceProfilePocketTpl(pmcProfile, reward.target); break; + case QuestRewardType.CUSTOMIZATION_DIRECT: + this.profileHelper.addHideoutCustomisationUnlock(fullProfile, reward, "unlockedInGame"); + break; default: this.logger.error( this.localisationService.getText("quest-reward_type_not_handled", { diff --git a/project/src/models/eft/common/tables/ICustomisationStorage.ts b/project/src/models/eft/common/tables/ICustomisationStorage.ts index 1ef230fa..b3297988 100644 --- a/project/src/models/eft/common/tables/ICustomisationStorage.ts +++ b/project/src/models/eft/common/tables/ICustomisationStorage.ts @@ -1,5 +1,5 @@ export interface ICustomisationStorage { - id: string; + id: string; // Customiastion.json/itemId source: string; type: string; } diff --git a/project/src/models/eft/profile/ISptProfile.ts b/project/src/models/eft/profile/ISptProfile.ts index 9c47acd7..4171c88b 100644 --- a/project/src/models/eft/profile/ISptProfile.ts +++ b/project/src/models/eft/profile/ISptProfile.ts @@ -1,4 +1,5 @@ import { IPmcData } from "@spt/models/eft/common/IPmcData"; +import { ICustomisationStorage } from "@spt/models/eft/common/tables/ICustomisationStorage"; import { IItem } from "@spt/models/eft/common/tables/IItem"; import { EquipmentBuildType } from "@spt/models/enums/EquipmentBuildType"; import { MemberCategory } from "@spt/models/enums/MemberCategory"; @@ -24,6 +25,7 @@ export interface ISptProfile { achievements: Record; /** List of friend profile IDs */ friends: string[]; + hideoutCustomisationUnlocks: ICustomisationStorage[]; } export class ITraderPurchaseData {