mirror of
https://github.com/sp-tarkov/server.git
synced 2025-02-13 05:50:44 -05:00
Added more questHelper fixes
This commit is contained in:
parent
2e8cdce3c2
commit
86d303fcf9
@ -1,5 +1,4 @@
|
||||
import { ItemHelper } from "@spt/helpers/ItemHelper";
|
||||
import { PresetHelper } from "@spt/helpers/PresetHelper";
|
||||
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||
import { QuestConditionHelper } from "@spt/helpers/QuestConditionHelper";
|
||||
import { QuestRewardHelper } from "@spt/helpers/QuestRewardHelper";
|
||||
@ -7,7 +6,7 @@ import { TraderHelper } from "@spt/helpers/TraderHelper";
|
||||
import { IPmcData } from "@spt/models/eft/common/IPmcData";
|
||||
import { Common, IQuestStatus } from "@spt/models/eft/common/tables/IBotBase";
|
||||
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 { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse";
|
||||
import { IAcceptQuestRequestData } from "@spt/models/eft/quests/IAcceptQuestRequestData";
|
||||
import { ICompleteQuestRequestData } from "@spt/models/eft/quests/ICompleteQuestRequestData";
|
||||
@ -49,7 +48,6 @@ export class QuestHelper {
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService,
|
||||
@inject("TraderHelper") protected traderHelper: TraderHelper,
|
||||
@inject("PresetHelper") protected presetHelper: PresetHelper,
|
||||
@inject("MailSendService") protected mailSendService: MailSendService,
|
||||
@inject("PlayerService") protected playerService: PlayerService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@ -234,116 +232,6 @@ export class QuestHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Take reward item from quest and set FiR status + fix stack sizes + fix mod Ids
|
||||
* @param questReward Reward item to fix
|
||||
* @returns Fixed rewards
|
||||
*/
|
||||
protected processReward(questReward: IQuestReward): IItem[] {
|
||||
/** item with mods to return */
|
||||
let rewardItems: IItem[] = [];
|
||||
let targets: IItem[] = [];
|
||||
const mods: IItem[] = [];
|
||||
|
||||
// Is armor item that may need inserts / plates
|
||||
if (questReward.items.length === 1 && this.itemHelper.armorItemCanHoldMods(questReward.items[0]._tpl)) {
|
||||
// Only process items with slots
|
||||
if (this.itemHelper.itemHasSlots(questReward.items[0]._tpl)) {
|
||||
// Attempt to pull default preset from globals and add child items to reward (clones questReward.items)
|
||||
this.generateArmorRewardChildSlots(questReward.items[0], questReward);
|
||||
}
|
||||
}
|
||||
|
||||
for (const rewardItem of questReward.items) {
|
||||
this.itemHelper.addUpdObjectToItem(rewardItem);
|
||||
|
||||
// Reward items are granted Found in Raid status
|
||||
rewardItem.upd.SpawnedInSession = true;
|
||||
|
||||
// Is root item, fix stacks
|
||||
if (rewardItem._id === questReward.target) {
|
||||
// Is base reward item
|
||||
if (
|
||||
rewardItem.parentId !== undefined &&
|
||||
rewardItem.parentId === "hideout" && // Has parentId of hideout
|
||||
rewardItem.upd !== undefined &&
|
||||
rewardItem.upd.StackObjectsCount !== undefined && // Has upd with stackobject count
|
||||
rewardItem.upd.StackObjectsCount > 1 // More than 1 item in stack
|
||||
) {
|
||||
rewardItem.upd.StackObjectsCount = 1;
|
||||
}
|
||||
targets = this.itemHelper.splitStack(rewardItem);
|
||||
// splitStack created new ids for the new stacks. This would destroy the relation to possible children.
|
||||
// Instead, we reset the id to preserve relations and generate a new id in the downstream loop, where we are also reparenting if required
|
||||
for (const target of targets) {
|
||||
target._id = rewardItem._id;
|
||||
}
|
||||
} else {
|
||||
// Is child mod
|
||||
if (questReward.items[0].upd.SpawnedInSession) {
|
||||
// Propigate FiR status into child items
|
||||
rewardItem.upd.SpawnedInSession = questReward.items[0].upd.SpawnedInSession;
|
||||
}
|
||||
|
||||
mods.push(rewardItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Add mods to the base items, fix ids
|
||||
for (const target of targets) {
|
||||
// This has all the original id relations since we reset the id to the original after the splitStack
|
||||
const itemsClone = [this.cloner.clone(target)];
|
||||
// Here we generate a new id for the root item
|
||||
target._id = this.hashUtil.generate();
|
||||
|
||||
for (const mod of mods) {
|
||||
itemsClone.push(this.cloner.clone(mod));
|
||||
}
|
||||
|
||||
rewardItems = rewardItems.concat(this.itemHelper.reparentItemAndChildren(target, itemsClone));
|
||||
}
|
||||
|
||||
return rewardItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add missing mod items to a quest armor reward
|
||||
* @param originalRewardRootItem Original armor reward item from IQuestReward.items object
|
||||
* @param questReward Armor reward from quest
|
||||
*/
|
||||
protected generateArmorRewardChildSlots(originalRewardRootItem: IItem, questReward: IQuestReward): void {
|
||||
// Look for a default preset from globals for armor
|
||||
const defaultPreset = this.presetHelper.getDefaultPreset(originalRewardRootItem._tpl);
|
||||
if (defaultPreset) {
|
||||
// Found preset, use mods to hydrate reward item
|
||||
const presetAndMods: IItem[] = this.itemHelper.replaceIDs(defaultPreset._items);
|
||||
const newRootId = this.itemHelper.remapRootItemId(presetAndMods);
|
||||
|
||||
questReward.items = presetAndMods;
|
||||
|
||||
// Find root item and set its stack count
|
||||
const rootItem = questReward.items.find((item) => item._id === newRootId);
|
||||
|
||||
// Remap target id to the new presets root id
|
||||
questReward.target = rootItem._id;
|
||||
|
||||
// Copy over stack count otherwise reward shows as missing in client
|
||||
this.itemHelper.addUpdObjectToItem(rootItem);
|
||||
|
||||
rootItem.upd.StackObjectsCount = originalRewardRootItem.upd.StackObjectsCount;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.warning(
|
||||
`Unable to find default preset for armor ${originalRewardRootItem._tpl}, adding mods manually`,
|
||||
);
|
||||
const itemDbData = this.itemHelper.getItem(originalRewardRootItem._tpl)[1];
|
||||
|
||||
// Hydrate reward with only 'required' mods - necessary for things like helmets otherwise you end up with nvgs/visors etc
|
||||
questReward.items = this.itemHelper.addChildSlotItems(questReward.items, itemDbData, undefined, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up quest in db by accepted quest id and construct a profile-ready object ready to store in profile
|
||||
* @param pmcData Player profile
|
||||
@ -975,7 +863,13 @@ export class QuestHelper {
|
||||
|
||||
const newQuestState = QuestStatus.Success;
|
||||
this.updateQuestState(pmcData, newQuestState, completedQuestId);
|
||||
const questRewards = this.applyQuestReward(pmcData, body.qid, newQuestState, sessionID, completeQuestResponse);
|
||||
const questRewards = this.questRewardHelper.applyQuestReward(
|
||||
pmcData,
|
||||
body.qid,
|
||||
newQuestState,
|
||||
sessionID,
|
||||
completeQuestResponse,
|
||||
);
|
||||
|
||||
// Check for linked failed + unrestartable quests (only get quests not already failed
|
||||
const questsToFail = this.getQuestsFromProfileFailedByCompletingQuest(completedQuestId, pmcData);
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { ItemHelper } from "@spt/helpers/ItemHelper";
|
||||
import { PaymentHelper } from "@spt/helpers/PaymentHelper";
|
||||
import { PresetHelper } from "@spt/helpers/PresetHelper";
|
||||
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||
import { TraderHelper } from "@spt/helpers/TraderHelper";
|
||||
import { IPmcData } from "@spt/models/eft/common/IPmcData";
|
||||
@ -14,6 +15,7 @@ import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { EventOutputHolder } from "@spt/routers/EventOutputHolder";
|
||||
import { DatabaseService } from "@spt/services/DatabaseService";
|
||||
import { LocalisationService } from "@spt/services/LocalisationService";
|
||||
import { HashUtil } from "@spt/utils/HashUtil";
|
||||
import type { ICloner } from "@spt/utils/cloners/ICloner";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
@ -21,6 +23,7 @@ import { inject, injectable } from "tsyringe";
|
||||
export class QuestRewardHelper {
|
||||
constructor(
|
||||
@inject("PrimaryLogger") protected logger: ILogger,
|
||||
@inject("HashUtil") protected hashUtil: HashUtil,
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("DatabaseService") protected databaseService: DatabaseService,
|
||||
@inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder,
|
||||
@ -28,6 +31,7 @@ export class QuestRewardHelper {
|
||||
@inject("PaymentHelper") protected paymentHelper: PaymentHelper,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("TraderHelper") protected traderHelper: TraderHelper,
|
||||
@inject("PresetHelper") protected presetHelper: PresetHelper,
|
||||
@inject("PrimaryCloner") protected cloner: ICloner,
|
||||
) {}
|
||||
|
||||
@ -323,4 +327,114 @@ export class QuestRewardHelper {
|
||||
|
||||
return questRewards;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take reward item from quest and set FiR status + fix stack sizes + fix mod Ids
|
||||
* @param questReward Reward item to fix
|
||||
* @returns Fixed rewards
|
||||
*/
|
||||
protected processReward(questReward: IQuestReward): IItem[] {
|
||||
/** item with mods to return */
|
||||
let rewardItems: IItem[] = [];
|
||||
let targets: IItem[] = [];
|
||||
const mods: IItem[] = [];
|
||||
|
||||
// Is armor item that may need inserts / plates
|
||||
if (questReward.items.length === 1 && this.itemHelper.armorItemCanHoldMods(questReward.items[0]._tpl)) {
|
||||
// Only process items with slots
|
||||
if (this.itemHelper.itemHasSlots(questReward.items[0]._tpl)) {
|
||||
// Attempt to pull default preset from globals and add child items to reward (clones questReward.items)
|
||||
this.generateArmorRewardChildSlots(questReward.items[0], questReward);
|
||||
}
|
||||
}
|
||||
|
||||
for (const rewardItem of questReward.items) {
|
||||
this.itemHelper.addUpdObjectToItem(rewardItem);
|
||||
|
||||
// Reward items are granted Found in Raid status
|
||||
rewardItem.upd.SpawnedInSession = true;
|
||||
|
||||
// Is root item, fix stacks
|
||||
if (rewardItem._id === questReward.target) {
|
||||
// Is base reward item
|
||||
if (
|
||||
rewardItem.parentId !== undefined &&
|
||||
rewardItem.parentId === "hideout" && // Has parentId of hideout
|
||||
rewardItem.upd !== undefined &&
|
||||
rewardItem.upd.StackObjectsCount !== undefined && // Has upd with stackobject count
|
||||
rewardItem.upd.StackObjectsCount > 1 // More than 1 item in stack
|
||||
) {
|
||||
rewardItem.upd.StackObjectsCount = 1;
|
||||
}
|
||||
targets = this.itemHelper.splitStack(rewardItem);
|
||||
// splitStack created new ids for the new stacks. This would destroy the relation to possible children.
|
||||
// Instead, we reset the id to preserve relations and generate a new id in the downstream loop, where we are also reparenting if required
|
||||
for (const target of targets) {
|
||||
target._id = rewardItem._id;
|
||||
}
|
||||
} else {
|
||||
// Is child mod
|
||||
if (questReward.items[0].upd.SpawnedInSession) {
|
||||
// Propigate FiR status into child items
|
||||
rewardItem.upd.SpawnedInSession = questReward.items[0].upd.SpawnedInSession;
|
||||
}
|
||||
|
||||
mods.push(rewardItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Add mods to the base items, fix ids
|
||||
for (const target of targets) {
|
||||
// This has all the original id relations since we reset the id to the original after the splitStack
|
||||
const itemsClone = [this.cloner.clone(target)];
|
||||
// Here we generate a new id for the root item
|
||||
target._id = this.hashUtil.generate();
|
||||
|
||||
for (const mod of mods) {
|
||||
itemsClone.push(this.cloner.clone(mod));
|
||||
}
|
||||
|
||||
rewardItems = rewardItems.concat(this.itemHelper.reparentItemAndChildren(target, itemsClone));
|
||||
}
|
||||
|
||||
return rewardItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add missing mod items to a quest armor reward
|
||||
* @param originalRewardRootItem Original armor reward item from IQuestReward.items object
|
||||
* @param questReward Armor reward from quest
|
||||
*/
|
||||
protected generateArmorRewardChildSlots(originalRewardRootItem: IItem, questReward: IQuestReward): void {
|
||||
// Look for a default preset from globals for armor
|
||||
const defaultPreset = this.presetHelper.getDefaultPreset(originalRewardRootItem._tpl);
|
||||
if (defaultPreset) {
|
||||
// Found preset, use mods to hydrate reward item
|
||||
const presetAndMods: IItem[] = this.itemHelper.replaceIDs(defaultPreset._items);
|
||||
const newRootId = this.itemHelper.remapRootItemId(presetAndMods);
|
||||
|
||||
questReward.items = presetAndMods;
|
||||
|
||||
// Find root item and set its stack count
|
||||
const rootItem = questReward.items.find((item) => item._id === newRootId);
|
||||
|
||||
// Remap target id to the new presets root id
|
||||
questReward.target = rootItem._id;
|
||||
|
||||
// Copy over stack count otherwise reward shows as missing in client
|
||||
this.itemHelper.addUpdObjectToItem(rootItem);
|
||||
|
||||
rootItem.upd.StackObjectsCount = originalRewardRootItem.upd.StackObjectsCount;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.warning(
|
||||
`Unable to find default preset for armor ${originalRewardRootItem._tpl}, adding mods manually`,
|
||||
);
|
||||
const itemDbData = this.itemHelper.getItem(originalRewardRootItem._tpl)[1];
|
||||
|
||||
// Hydrate reward with only 'required' mods - necessary for things like helmets otherwise you end up with nvgs/visors etc
|
||||
questReward.items = this.itemHelper.addChildSlotItems(questReward.items, itemDbData, undefined, true);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user