0
0
mirror of https://github.com/sp-tarkov/server.git synced 2025-02-13 09:50:43 -05:00

Rename IQuestReward and QuestRewardType to be generic

This commit is contained in:
DrakiaXYZ 2025-01-11 22:21:08 -08:00
parent accedf24c9
commit bc7935e943
12 changed files with 94 additions and 91 deletions

View File

@ -7,7 +7,7 @@ import { QuestHelper } from "@spt/helpers/QuestHelper";
import { TraderHelper } from "@spt/helpers/TraderHelper"; import { TraderHelper } from "@spt/helpers/TraderHelper";
import { CustomisationSource } from "@spt/models/eft/common/tables/ICustomisationStorage"; import { CustomisationSource } from "@spt/models/eft/common/tables/ICustomisationStorage";
import { IPrestige } from "@spt/models/eft/common/tables/IPrestige"; import { IPrestige } from "@spt/models/eft/common/tables/IPrestige";
import { IQuestReward } from "@spt/models/eft/common/tables/IQuest"; import { IReward } from "@spt/models/eft/common/tables/IReward";
import { IAddItemDirectRequest } from "@spt/models/eft/inventory/IAddItemDirectRequest"; import { IAddItemDirectRequest } from "@spt/models/eft/inventory/IAddItemDirectRequest";
import { IAddItemsDirectRequest } from "@spt/models/eft/inventory/IAddItemsDirectRequest"; import { IAddItemsDirectRequest } from "@spt/models/eft/inventory/IAddItemsDirectRequest";
import { IObtainPrestigeRequest } from "@spt/models/eft/prestige/IObtainPrestigeRequest"; import { IObtainPrestigeRequest } from "@spt/models/eft/prestige/IObtainPrestigeRequest";
@ -145,7 +145,7 @@ export class PrestigeController {
} }
} }
protected addPrestigeRewardsToProfile(sessionId: string, newProfile: ISptProfile, rewards: IQuestReward[]) { protected addPrestigeRewardsToProfile(sessionId: string, newProfile: ISptProfile, rewards: IReward[]) {
for (const reward of rewards) { for (const reward of rewards) {
switch (reward.type) { switch (reward.type) {
case "CustomizationDirect": { case "CustomizationDirect": {

View File

@ -2,12 +2,13 @@ import { HandbookHelper } from "@spt/helpers/HandbookHelper";
import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper";
import { PresetHelper } from "@spt/helpers/PresetHelper"; import { PresetHelper } from "@spt/helpers/PresetHelper";
import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItem } from "@spt/models/eft/common/tables/IItem";
import { IQuestReward, IQuestRewards } from "@spt/models/eft/common/tables/IQuest"; import { IQuestRewards } from "@spt/models/eft/common/tables/IQuest";
import { IReward } from "@spt/models/eft/common/tables/IReward";
import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem";
import { BaseClasses } from "@spt/models/enums/BaseClasses"; import { BaseClasses } from "@spt/models/enums/BaseClasses";
import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
import { Money } from "@spt/models/enums/Money"; import { Money } from "@spt/models/enums/Money";
import { QuestRewardType } from "@spt/models/enums/QuestRewardType"; import { RewardType } from "@spt/models/enums/RewardType";
import { Traders } from "@spt/models/enums/Traders"; import { Traders } from "@spt/models/enums/Traders";
import { import {
IBaseQuestConfig, IBaseQuestConfig,
@ -104,7 +105,7 @@ export class RepeatableQuestRewardGenerator {
availableInGameEditions: [], availableInGameEditions: [],
index: rewardIndex, index: rewardIndex,
value: rewardParams.rewardXP, value: rewardParams.rewardXP,
type: QuestRewardType.EXPERIENCE, type: RewardType.EXPERIENCE,
}); });
rewardIndex++; rewardIndex++;
} }
@ -166,14 +167,14 @@ export class RepeatableQuestRewardGenerator {
// Add rep reward to rewards array // Add rep reward to rewards array
if (rewardParams.rewardReputation > 0) { if (rewardParams.rewardReputation > 0) {
const reward: IQuestReward = { const reward: IReward = {
id: this.hashUtil.generate(), id: this.hashUtil.generate(),
unknown: false, unknown: false,
gameMode: [], gameMode: [],
availableInGameEditions: [], availableInGameEditions: [],
target: traderId, target: traderId,
value: rewardParams.rewardReputation, value: rewardParams.rewardReputation,
type: QuestRewardType.TRADER_STANDING, type: RewardType.TRADER_STANDING,
index: rewardIndex, index: rewardIndex,
}; };
rewards.Success.push(reward); rewards.Success.push(reward);
@ -185,14 +186,14 @@ export class RepeatableQuestRewardGenerator {
// Chance of adding skill reward // Chance of adding skill reward
if (this.randomUtil.getChance100(rewardParams.skillRewardChance * 100)) { if (this.randomUtil.getChance100(rewardParams.skillRewardChance * 100)) {
const targetSkill = this.randomUtil.getArrayValue(questConfig.possibleSkillRewards); const targetSkill = this.randomUtil.getArrayValue(questConfig.possibleSkillRewards);
const reward: IQuestReward = { const reward: IReward = {
id: this.hashUtil.generate(), id: this.hashUtil.generate(),
unknown: false, unknown: false,
gameMode: [], gameMode: [],
availableInGameEditions: [], availableInGameEditions: [],
target: targetSkill, target: targetSkill,
value: rewardParams.skillPointReward, value: rewardParams.skillPointReward,
type: QuestRewardType.SKILL, type: RewardType.SKILL,
index: rewardIndex, index: rewardIndex,
}; };
rewards.Success.push(reward); rewards.Success.push(reward);
@ -340,12 +341,12 @@ export class RepeatableQuestRewardGenerator {
* Choose a random Weapon preset that fits inside of a rouble amount limit * Choose a random Weapon preset that fits inside of a rouble amount limit
* @param roublesBudget * @param roublesBudget
* @param rewardIndex * @param rewardIndex
* @returns IQuestReward * @returns IReward
*/ */
protected getRandomWeaponPresetWithinBudget( protected getRandomWeaponPresetWithinBudget(
roublesBudget: number, roublesBudget: number,
rewardIndex: number, rewardIndex: number,
): { weapon: IQuestReward; price: number } | undefined { ): { weapon: IReward; price: number } | undefined {
// Add a random default preset weapon as reward // Add a random default preset weapon as reward
const defaultPresetPool = new ExhaustableArray( const defaultPresetPool = new ExhaustableArray(
Object.values(this.presetHelper.getDefaultWeaponPresets()), Object.values(this.presetHelper.getDefaultWeaponPresets()),
@ -517,9 +518,9 @@ export class RepeatableQuestRewardGenerator {
* @param preset Optional array of preset items * @param preset Optional array of preset items
* @returns {object} Object of "Reward"-item-type * @returns {object} Object of "Reward"-item-type
*/ */
protected generateItemReward(tpl: string, count: number, index: number, foundInRaid = true): IQuestReward { protected generateItemReward(tpl: string, count: number, index: number, foundInRaid = true): IReward {
const id = this.hashUtil.generate(); const id = this.hashUtil.generate();
const questRewardItem: IQuestReward = { const questRewardItem: IReward = {
id: this.hashUtil.generate(), id: this.hashUtil.generate(),
unknown: false, unknown: false,
gameMode: [], gameMode: [],
@ -529,7 +530,7 @@ export class RepeatableQuestRewardGenerator {
value: count, value: count,
isEncoded: false, isEncoded: false,
findInRaid: foundInRaid, findInRaid: foundInRaid,
type: QuestRewardType.ITEM, type: RewardType.ITEM,
items: [], items: [],
}; };
@ -554,9 +555,9 @@ export class RepeatableQuestRewardGenerator {
index: number, index: number,
preset?: IItem[], preset?: IItem[],
foundInRaid = true, foundInRaid = true,
): IQuestReward { ): IReward {
const id = this.hashUtil.generate(); const id = this.hashUtil.generate();
const questRewardItem: IQuestReward = { const questRewardItem: IReward = {
id: this.hashUtil.generate(), id: this.hashUtil.generate(),
unknown: false, unknown: false,
gameMode: [], gameMode: [],
@ -566,7 +567,7 @@ export class RepeatableQuestRewardGenerator {
value: count, value: count,
isEncoded: false, isEncoded: false,
findInRaid: foundInRaid, findInRaid: foundInRaid,
type: QuestRewardType.ITEM, type: RewardType.ITEM,
items: [], items: [],
}; };
@ -667,7 +668,7 @@ export class RepeatableQuestRewardGenerator {
return true; return true;
} }
protected getMoneyReward(traderId: string, rewardRoubles: number, rewardIndex: number): IQuestReward { protected getMoneyReward(traderId: string, rewardRoubles: number, rewardIndex: number): IReward {
// Determine currency based on trader // Determine currency based on trader
// PK and Fence use Euros, everyone else is Roubles // PK and Fence use Euros, everyone else is Roubles
const currency = traderId === Traders.PEACEKEEPER || traderId === Traders.FENCE ? Money.EUROS : Money.ROUBLES; const currency = traderId === Traders.PEACEKEEPER || traderId === Traders.FENCE ? Money.EUROS : Money.ROUBLES;

View File

@ -7,7 +7,7 @@ import {
ICustomisationStorage, ICustomisationStorage,
} from "@spt/models/eft/common/tables/ICustomisationStorage"; } from "@spt/models/eft/common/tables/ICustomisationStorage";
import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItem } from "@spt/models/eft/common/tables/IItem";
import { IQuestReward } from "@spt/models/eft/common/tables/IQuest"; import { IReward } from "@spt/models/eft/common/tables/IReward";
import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse";
import { ISpt, ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { ISpt, ISptProfile } from "@spt/models/eft/profile/ISptProfile";
import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData";
@ -655,11 +655,7 @@ export class ProfileHelper {
* @param reward reward given to player with customisation data * @param reward reward given to player with customisation data
* @param source Source of reward, e.g. "unlockedInGame" for quests and "achievement" for achievements * @param source Source of reward, e.g. "unlockedInGame" for quests and "achievement" for achievements
*/ */
public addHideoutCustomisationUnlock( public addHideoutCustomisationUnlock(fullProfile: ISptProfile, reward: IReward, source: CustomisationSource): void {
fullProfile: ISptProfile,
reward: IQuestReward,
source: CustomisationSource,
): void {
fullProfile.customisationUnlocks ||= []; fullProfile.customisationUnlocks ||= [];
if (fullProfile.customisationUnlocks?.some((unlock) => unlock.id === reward.target)) { if (fullProfile.customisationUnlocks?.some((unlock) => unlock.id === reward.target)) {
this.logger.warning( this.logger.warning(

View File

@ -6,7 +6,8 @@ import { TraderHelper } from "@spt/helpers/TraderHelper";
import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { Common, IQuestStatus } from "@spt/models/eft/common/tables/IBotBase"; import { Common, IQuestStatus } from "@spt/models/eft/common/tables/IBotBase";
import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItem } from "@spt/models/eft/common/tables/IItem";
import { IQuest, IQuestCondition, IQuestReward } from "@spt/models/eft/common/tables/IQuest"; import { IQuest, IQuestCondition } from "@spt/models/eft/common/tables/IQuest";
import { IReward } from "@spt/models/eft/common/tables/IReward";
import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse";
import { IAcceptQuestRequestData } from "@spt/models/eft/quests/IAcceptQuestRequestData"; import { IAcceptQuestRequestData } from "@spt/models/eft/quests/IAcceptQuestRequestData";
import { ICompleteQuestRequestData } from "@spt/models/eft/quests/ICompleteQuestRequestData"; import { ICompleteQuestRequestData } from "@spt/models/eft/quests/ICompleteQuestRequestData";
@ -1058,7 +1059,7 @@ export class QuestHelper {
for (const quest of modifiedQuests) { for (const quest of modifiedQuests) {
// Remove any reward that doesn't pass the game edition check // Remove any reward that doesn't pass the game edition check
for (const rewardType of Object.keys(quest.rewards)) { for (const rewardType of Object.keys(quest.rewards)) {
quest.rewards[rewardType] = quest.rewards[rewardType].filter((reward: IQuestReward) => quest.rewards[rewardType] = quest.rewards[rewardType].filter((reward: IReward) =>
this.questRewardHelper.questRewardIsForGameEdition(reward, gameVersion), this.questRewardHelper.questRewardIsForGameEdition(reward, gameVersion),
); );
} }

View File

@ -6,10 +6,11 @@ import { TraderHelper } from "@spt/helpers/TraderHelper";
import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { CustomisationSource } from "@spt/models/eft/common/tables/ICustomisationStorage"; import { CustomisationSource } from "@spt/models/eft/common/tables/ICustomisationStorage";
import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IItem } from "@spt/models/eft/common/tables/IItem";
import { IQuest, IQuestReward } from "@spt/models/eft/common/tables/IQuest"; import { IQuest } from "@spt/models/eft/common/tables/IQuest";
import { IReward } from "@spt/models/eft/common/tables/IReward";
import { IHideoutProduction } from "@spt/models/eft/hideout/IHideoutProduction"; import { IHideoutProduction } from "@spt/models/eft/hideout/IHideoutProduction";
import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse";
import { QuestRewardType } from "@spt/models/enums/QuestRewardType"; import { RewardType } from "@spt/models/enums/RewardType";
import { QuestStatus } from "@spt/models/enums/QuestStatus"; import { QuestStatus } from "@spt/models/enums/QuestStatus";
import { SkillTypes } from "@spt/models/enums/SkillTypes"; import { SkillTypes } from "@spt/models/enums/SkillTypes";
import type { ILogger } from "@spt/models/spt/utils/ILogger"; import type { ILogger } from "@spt/models/spt/utils/ILogger";
@ -80,46 +81,46 @@ export class QuestRewardHelper {
// e.g. 'Success' or 'AvailableForFinish' // e.g. 'Success' or 'AvailableForFinish'
const questStateAsString = QuestStatus[state]; const questStateAsString = QuestStatus[state];
const gameVersion = pmcProfile.Info.GameVersion; const gameVersion = pmcProfile.Info.GameVersion;
for (const reward of <IQuestReward[]>questDetails.rewards[questStateAsString]) { for (const reward of <IReward[]>questDetails.rewards[questStateAsString]) {
// Handle quest reward availability for different game versions, notAvailableInGameEditions currently not used // Handle quest reward availability for different game versions, notAvailableInGameEditions currently not used
if (!this.questRewardIsForGameEdition(reward, gameVersion)) { if (!this.questRewardIsForGameEdition(reward, gameVersion)) {
continue; continue;
} }
switch (reward.type) { switch (reward.type) {
case QuestRewardType.SKILL: case RewardType.SKILL:
this.profileHelper.addSkillPointsToPlayer( this.profileHelper.addSkillPointsToPlayer(
profileData, profileData,
reward.target as SkillTypes, reward.target as SkillTypes,
Number(reward.value), Number(reward.value),
); );
break; break;
case QuestRewardType.EXPERIENCE: case RewardType.EXPERIENCE:
this.profileHelper.addExperienceToPmc(sessionId, Number.parseInt(<string>reward.value)); // this must occur first as the output object needs to take the modified profile exp value this.profileHelper.addExperienceToPmc(sessionId, Number.parseInt(<string>reward.value)); // this must occur first as the output object needs to take the modified profile exp value
break; break;
case QuestRewardType.TRADER_STANDING: case RewardType.TRADER_STANDING:
this.traderHelper.addStandingToTrader( this.traderHelper.addStandingToTrader(
sessionId, sessionId,
reward.target, reward.target,
Number.parseFloat(<string>reward.value), Number.parseFloat(<string>reward.value),
); );
break; break;
case QuestRewardType.TRADER_UNLOCK: case RewardType.TRADER_UNLOCK:
this.traderHelper.setTraderUnlockedState(reward.target, true, sessionId); this.traderHelper.setTraderUnlockedState(reward.target, true, sessionId);
break; break;
case QuestRewardType.ITEM: case RewardType.ITEM:
// Handled by getQuestRewardItems() below // Handled by getQuestRewardItems() below
break; break;
case QuestRewardType.ASSORTMENT_UNLOCK: case RewardType.ASSORTMENT_UNLOCK:
// Handled by getAssort(), locked assorts are stripped out by `assortHelper.stripLockedLoyaltyAssort()` before being sent to player // Handled by getAssort(), locked assorts are stripped out by `assortHelper.stripLockedLoyaltyAssort()` before being sent to player
break; break;
case QuestRewardType.ACHIEVEMENT: case RewardType.ACHIEVEMENT:
this.profileHelper.addAchievementToProfile(fullProfile, reward.target); this.profileHelper.addAchievementToProfile(fullProfile, reward.target);
break; break;
case QuestRewardType.STASH_ROWS: case RewardType.STASH_ROWS:
this.profileHelper.addStashRowsBonusToProfile(sessionId, Number.parseInt(<string>reward.value)); // Add specified stash rows from quest reward - requires client restart this.profileHelper.addStashRowsBonusToProfile(sessionId, Number.parseInt(<string>reward.value)); // Add specified stash rows from quest reward - requires client restart
break; break;
case QuestRewardType.PRODUCTIONS_SCHEME: case RewardType.PRODUCTIONS_SCHEME:
this.findAndAddHideoutProductionIdToProfile( this.findAndAddHideoutProductionIdToProfile(
pmcProfile, pmcProfile,
reward, reward,
@ -128,10 +129,10 @@ export class QuestRewardHelper {
questResponse, questResponse,
); );
break; break;
case QuestRewardType.POCKETS: case RewardType.POCKETS:
this.profileHelper.replaceProfilePocketTpl(pmcProfile, reward.target); this.profileHelper.replaceProfilePocketTpl(pmcProfile, reward.target);
break; break;
case QuestRewardType.CUSTOMIZATION_DIRECT: case RewardType.CUSTOMIZATION_DIRECT:
this.profileHelper.addHideoutCustomisationUnlock( this.profileHelper.addHideoutCustomisationUnlock(
fullProfile, fullProfile,
reward, reward,
@ -159,7 +160,7 @@ export class QuestRewardHelper {
* @param gameVersion Version of game to check reward against * @param gameVersion Version of game to check reward against
* @returns True if it has requirement, false if it doesnt pass check * @returns True if it has requirement, false if it doesnt pass check
*/ */
public questRewardIsForGameEdition(reward: IQuestReward, gameVersion: string) { public questRewardIsForGameEdition(reward: IReward, gameVersion: string) {
if (reward.availableInGameEditions?.length > 0 && !reward.availableInGameEditions?.includes(gameVersion)) { if (reward.availableInGameEditions?.length > 0 && !reward.availableInGameEditions?.includes(gameVersion)) {
// Reward has edition whitelist and game version isnt in it // Reward has edition whitelist and game version isnt in it
return false; return false;
@ -229,7 +230,7 @@ export class QuestRewardHelper {
* @returns Updated quest * @returns Updated quest
*/ */
public applyMoneyBoost(quest: IQuest, bonusPercent: number, questStatus: QuestStatus): IQuest { public applyMoneyBoost(quest: IQuest, bonusPercent: number, questStatus: QuestStatus): IQuest {
const rewards: IQuestReward[] = quest.rewards?.[QuestStatus[questStatus]] ?? []; const rewards: IReward[] = quest.rewards?.[QuestStatus[questStatus]] ?? [];
const currencyRewards = rewards.filter( const currencyRewards = rewards.filter(
(reward) => reward.type === "Item" && this.paymentHelper.isMoneyTpl(reward.items[0]._tpl), (reward) => reward.type === "Item" && this.paymentHelper.isMoneyTpl(reward.items[0]._tpl),
); );
@ -255,7 +256,7 @@ export class QuestRewardHelper {
*/ */
protected findAndAddHideoutProductionIdToProfile( protected findAndAddHideoutProductionIdToProfile(
pmcData: IPmcData, pmcData: IPmcData,
craftUnlockReward: IQuestReward, craftUnlockReward: IReward,
questDetails: IQuest, questDetails: IQuest,
sessionID: string, sessionID: string,
response: IItemEventRouterResponse, response: IItemEventRouterResponse,
@ -284,7 +285,7 @@ export class QuestRewardHelper {
* @param questDetails Quest with craft unlock reward * @param questDetails Quest with craft unlock reward
* @returns Hideout craft * @returns Hideout craft
*/ */
public getRewardProductionMatch(craftUnlockReward: IQuestReward, questDetails: IQuest): IHideoutProduction[] { public getRewardProductionMatch(craftUnlockReward: IReward, questDetails: IQuest): IHideoutProduction[] {
// Get hideout crafts and find those that match by areatype/required level/end product tpl - hope for just one match // Get hideout crafts and find those that match by areatype/required level/end product tpl - hope for just one match
const craftingRecipes = this.databaseService.getHideout().production.recipes; const craftingRecipes = this.databaseService.getHideout().production.recipes;
@ -324,7 +325,7 @@ export class QuestRewardHelper {
} }
// Iterate over all rewards with the desired status, flatten out items that have a type of Item // Iterate over all rewards with the desired status, flatten out items that have a type of Item
const questRewards = quest.rewards[QuestStatus[status]].flatMap((reward: IQuestReward) => const questRewards = quest.rewards[QuestStatus[status]].flatMap((reward: IReward) =>
reward.type === "Item" && this.questRewardIsForGameEdition(reward, gameVersion) reward.type === "Item" && this.questRewardIsForGameEdition(reward, gameVersion)
? this.processReward(reward) ? this.processReward(reward)
: [], : [],
@ -338,7 +339,7 @@ export class QuestRewardHelper {
* @param questReward Reward item to fix * @param questReward Reward item to fix
* @returns Fixed rewards * @returns Fixed rewards
*/ */
protected processReward(questReward: IQuestReward): IItem[] { protected processReward(questReward: IReward): IItem[] {
/** item with mods to return */ /** item with mods to return */
let rewardItems: IItem[] = []; let rewardItems: IItem[] = [];
let targets: IItem[] = []; let targets: IItem[] = [];
@ -407,10 +408,10 @@ export class QuestRewardHelper {
/** /**
* Add missing mod items to a quest armor reward * Add missing mod items to a quest armor reward
* @param originalRewardRootItem Original armor reward item from IQuestReward.items object * @param originalRewardRootItem Original armor reward item from IReward.items object
* @param questReward Armor reward from quest * @param questReward Armor reward from quest
*/ */
protected generateArmorRewardChildSlots(originalRewardRootItem: IItem, questReward: IQuestReward): void { protected generateArmorRewardChildSlots(originalRewardRootItem: IItem, questReward: IReward): void {
// Look for a default preset from globals for armor // Look for a default preset from globals for armor
const defaultPreset = this.presetHelper.getDefaultPreset(originalRewardRootItem._tpl); const defaultPreset = this.presetHelper.getDefaultPreset(originalRewardRootItem._tpl);
if (defaultPreset) { if (defaultPreset) {

View File

@ -1,10 +1,11 @@
import { IQuestConditionTypes, IQuestReward } from "@spt/models/eft/common/tables/IQuest"; import { IQuestConditionTypes } from "@spt/models/eft/common/tables/IQuest";
import { IReward } from "@spt/models/eft/common/tables/IReward";
export interface IAchievement { export interface IAchievement {
id: string; id: string;
imageUrl: string; imageUrl: string;
assetPath: string; assetPath: string;
rewards: IQuestReward[]; rewards: IReward[];
conditions: IQuestConditionTypes; conditions: IQuestConditionTypes;
instantComplete: boolean; instantComplete: boolean;
showNotificationsInGame: boolean; showNotificationsInGame: boolean;

View File

@ -1,4 +1,5 @@
import type { IQuestCondition, IQuestReward } from "./IQuest"; import type { IQuestCondition } from "@spt/models/eft/common/tables/IQuest";
import type { IReward } from "@spt/models/eft/common/tables/IReward";
export interface IPrestige { export interface IPrestige {
elements: IPretigeElement[]; elements: IPretigeElement[];
@ -7,7 +8,7 @@ export interface IPrestige {
export interface IPretigeElement { export interface IPretigeElement {
id: string; id: string;
conditions: IQuestCondition[]; conditions: IQuestCondition[];
rewards: IQuestReward[]; rewards: IReward[];
transferConfigs: ITransferConfigs; transferConfigs: ITransferConfigs;
image: string; image: string;
bigImage: string; bigImage: string;

View File

@ -1,5 +1,4 @@
import { IItem } from "@spt/models/eft/common/tables/IItem"; import { IReward } from "@spt/models/eft/common/tables/IReward";
import { QuestRewardType } from "@spt/models/enums/QuestRewardType";
import { QuestStatus } from "@spt/models/enums/QuestStatus"; import { QuestStatus } from "@spt/models/enums/QuestStatus";
import { QuestTypeEnum } from "@spt/models/enums/QuestTypeEnum"; import { QuestTypeEnum } from "@spt/models/enums/QuestTypeEnum";
@ -146,33 +145,11 @@ export interface IVisibilityCondition {
} }
export interface IQuestRewards { export interface IQuestRewards {
AvailableForStart?: IQuestReward[]; AvailableForStart?: IReward[];
AvailableForFinish?: IQuestReward[]; AvailableForFinish?: IReward[];
Started?: IQuestReward[]; Started?: IReward[];
Success?: IQuestReward[]; Success?: IReward[];
Fail?: IQuestReward[]; Fail?: IReward[];
FailRestartable?: IQuestReward[]; FailRestartable?: IReward[];
Expired?: IQuestReward[]; Expired?: IReward[];
}
export interface IQuestReward {
value?: string | number;
id?: string;
illustrationConfig?: any;
isHidden?: boolean;
type: QuestRewardType;
index: number;
target?: string;
items?: IItem[];
loyaltyLevel?: number;
/** Hideout area id */
traderId?: string;
isEncoded?: boolean;
unknown?: boolean;
findInRaid?: boolean;
gameMode?: string[];
/** Game editions whitelisted to get reward */
availableInGameEditions?: string[];
/** Game editions blacklisted from getting reward */
notAvailableInGameEditions?: string[];
} }

View File

@ -0,0 +1,24 @@
import { RewardType } from "@spt/models/enums/RewardType";
import { IItem } from "./IItem";
export interface IReward {
value?: string | number;
id?: string;
illustrationConfig?: any;
isHidden?: boolean;
type: RewardType;
index: number;
target?: string;
items?: IItem[];
loyaltyLevel?: number;
/** Hideout area id */
traderId?: string;
isEncoded?: boolean;
unknown?: boolean;
findInRaid?: boolean;
gameMode?: string[];
/** Game editions whitelisted to get reward */
availableInGameEditions?: string[];
/** Game editions blacklisted from getting reward */
notAvailableInGameEditions?: string[];
}

View File

@ -1,4 +1,4 @@
export enum QuestRewardType { export enum RewardType {
SKILL = "Skill", SKILL = "Skill",
EXPERIENCE = "Experience", EXPERIENCE = "Experience",
TRADER_STANDING = "TraderStanding", TRADER_STANDING = "TraderStanding",

View File

@ -6,7 +6,8 @@ import { QuestRewardHelper } from "@spt/helpers/QuestRewardHelper";
import { TraderHelper } from "@spt/helpers/TraderHelper"; import { TraderHelper } from "@spt/helpers/TraderHelper";
import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { IBonus, IHideoutSlot } from "@spt/models/eft/common/tables/IBotBase"; import { IBonus, IHideoutSlot } from "@spt/models/eft/common/tables/IBotBase";
import { IQuest, IQuestReward } from "@spt/models/eft/common/tables/IQuest"; import { IQuest } from "@spt/models/eft/common/tables/IQuest";
import { IReward } from "@spt/models/eft/common/tables/IReward";
import { IPmcDataRepeatableQuest, IRepeatableQuest } from "@spt/models/eft/common/tables/IRepeatableQuests"; import { IPmcDataRepeatableQuest, IRepeatableQuest } from "@spt/models/eft/common/tables/IRepeatableQuests";
import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem";
import { IStageBonus } from "@spt/models/eft/hideout/IHideoutArea"; import { IStageBonus } from "@spt/models/eft/hideout/IHideoutArea";
@ -14,7 +15,7 @@ import { IEquipmentBuild, IMagazineBuild, ISptProfile, IWeaponBuild } from "@spt
import { BonusType } from "@spt/models/enums/BonusType"; import { BonusType } from "@spt/models/enums/BonusType";
import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
import { HideoutAreas } from "@spt/models/enums/HideoutAreas"; import { HideoutAreas } from "@spt/models/enums/HideoutAreas";
import { QuestRewardType } from "@spt/models/enums/QuestRewardType"; import { RewardType } from "@spt/models/enums/RewardType";
import { QuestStatus } from "@spt/models/enums/QuestStatus"; import { QuestStatus } from "@spt/models/enums/QuestStatus";
import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig";
import { IRagfairConfig } from "@spt/models/spt/config/IRagfairConfig"; import { IRagfairConfig } from "@spt/models/spt/config/IRagfairConfig";
@ -325,7 +326,7 @@ export class ProfileFixerService {
// For started or successful quests, check for unlocks in the `Started` rewards // For started or successful quests, check for unlocks in the `Started` rewards
if (profileQuest.status === QuestStatus.Started || profileQuest.status === QuestStatus.Success) { if (profileQuest.status === QuestStatus.Started || profileQuest.status === QuestStatus.Success) {
const productionRewards = quest.rewards.Started?.filter( const productionRewards = quest.rewards.Started?.filter(
(reward) => reward.type === QuestRewardType.PRODUCTIONS_SCHEME, (reward) => reward.type === RewardType.PRODUCTIONS_SCHEME,
); );
if (productionRewards) { if (productionRewards) {
@ -338,7 +339,7 @@ export class ProfileFixerService {
// For successful quests, check for unlocks in the `Success` rewards // For successful quests, check for unlocks in the `Success` rewards
if (profileQuest.status === QuestStatus.Success) { if (profileQuest.status === QuestStatus.Success) {
const productionRewards = quest.rewards.Success?.filter( const productionRewards = quest.rewards.Success?.filter(
(reward) => reward.type === QuestRewardType.PRODUCTIONS_SCHEME, (reward) => reward.type === RewardType.PRODUCTIONS_SCHEME,
); );
if (productionRewards) { if (productionRewards) {
@ -361,7 +362,7 @@ export class ProfileFixerService {
*/ */
protected verifyQuestProductionUnlock( protected verifyQuestProductionUnlock(
pmcProfile: IPmcData, pmcProfile: IPmcData,
productionUnlockReward: IQuestReward, productionUnlockReward: IReward,
questDetails: IQuest, questDetails: IQuest,
): void { ): void {
const matchingProductions = this.questRewardHelper.getRewardProductionMatch( const matchingProductions = this.questRewardHelper.getRewardProductionMatch(

View File

@ -13,7 +13,7 @@
import * as path from "node:path"; import * as path from "node:path";
import { OnLoad } from "@spt/di/OnLoad"; import { OnLoad } from "@spt/di/OnLoad";
import { IHideoutProduction, IRequirement } from "@spt/models/eft/hideout/IHideoutProduction"; import { IHideoutProduction, IRequirement } from "@spt/models/eft/hideout/IHideoutProduction";
import { QuestRewardType } from "@spt/models/enums/QuestRewardType"; import { RewardType } from "@spt/models/enums/RewardType";
import type { ILogger } from "@spt/models/spt/utils/ILogger"; import type { ILogger } from "@spt/models/spt/utils/ILogger";
import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { DatabaseServer } from "@spt/servers/DatabaseServer";
import { FileSystemSync } from "@spt/utils/FileSystemSync"; import { FileSystemSync } from "@spt/utils/FileSystemSync";
@ -129,7 +129,7 @@ export class ProductionQuestsGen {
for (const quest of Object.values(this.databaseServer.getTables().templates.quests)) { for (const quest of Object.values(this.databaseServer.getTables().templates.quests)) {
for (const rewardState of Object.values(quest.rewards)) { for (const rewardState of Object.values(quest.rewards)) {
for (const reward of rewardState) { for (const reward of rewardState) {
if (reward.type !== QuestRewardType.PRODUCTIONS_SCHEME) continue; if (reward.type !== RewardType.PRODUCTIONS_SCHEME) continue;
// Make the assumption all productions only output a single item template // Make the assumption all productions only output a single item template
const output: QuestProductionOutput = { const output: QuestProductionOutput = {