Fix ammobox + magazine cartridges being given to player with an incorrect FiR status, shouild match parents status

This commit is contained in:
Dev 2024-01-23 15:24:02 +00:00
parent 4ce26ea870
commit d3f9cea4c1
4 changed files with 43 additions and 85 deletions

View File

@ -11,6 +11,7 @@ import {
MessageItems,
MessagePreview,
} from "@spt-aki/models/eft/profile/IAkiProfile";
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
import { MessageType } from "@spt-aki/models/enums/MessageType";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
@ -104,14 +105,21 @@ export class DialogueHelper
continue;
}
items.data.push(reward);
if ("StackSlots" in itemTemplate._props)
{
const stackSlotItems = this.itemHelper.generateItemsFromStackSlot(itemTemplate, reward._id);
for (const itemToAdd of stackSlotItems)
// Boxes can contain sub-items
if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.AMMO_BOX))
{
items.data.push(itemToAdd);
const boxAndCartridges: Item[] = [reward];
this.itemHelper.addCartridgesToAmmoBox(boxAndCartridges, itemTemplate);
// Push box + cartridge children into array
items.data.push(...boxAndCartridges);
}
else
{
// Item is sanitised and ready to be pushed into holding array
items.data.push(reward);
}
}
}

View File

@ -241,74 +241,6 @@ export class ItemHelper
return item;
}
/**
* AmmoBoxes contain StackSlots which need to be filled for the AmmoBox to have content.
* Here's what a filled AmmoBox looks like:
* {
* _id: "b1bbe982daa00ac841d4ae4d",
* _tpl: "57372c89245977685d4159b1",
* parentId: "5fe49a0e2694b0755a504876",
* slotId: "hideout",
* location: {
* x: 3,
* y: 4,
* r: 0
* },
* upd: {
* StackObjectsCount: 1
* }
* },
* {
* _id: "b997b4117199033afd274a06",
* _tpl: "56dff061d2720bb5668b4567",
* parentId: "b1bbe982daa00ac841d4ae4d",
* slotId: "cartridges",
* location: 0,
* upd: {
* StackObjectsCount: 30
* }
* }
* Given the AmmoBox Item (first object) this function generates the StackSlot (second object) and returns it.
* StackSlots are only used for AmmoBoxes which only have one element in StackSlots. However, it seems to be generic
* to possibly also have more than one StackSlot. As good as possible, without seeing items having more than one
* StackSlot, this function takes account of this and creates and returns an array of StackSlotItems
*
* @param {object} item The item template of the AmmoBox as given in items.json
* @param {string} parentId The id of the AmmoBox instance these StackSlotItems should be children of
* @returns {array} The array of StackSlotItems
*/
public generateItemsFromStackSlot(item: ITemplateItem, parentId: string): Item[]
{
const stackSlotItems: Item[] = [];
// This is a AmmoBox or something other with Stackslots (nothing exists yet besides AmmoBoxes afaik)
for (const stackSlot of item._props.StackSlots)
{
const slotId = stackSlot._name;
const count = stackSlot._max_count;
// those are all arrays. For AmmoBoxes it's only one element each so we take 0 hardcoded
// not sure if at any point there will be more than one element - but what so take then?
const ammoTpl = stackSlot._props.filters[0].Filter[0];
if (ammoTpl)
{
const stackSlotItem: Item = {
_id: this.hashUtil.generate(),
_tpl: ammoTpl,
parentId: parentId,
slotId: slotId,
location: 0,
upd: { StackObjectsCount: count },
};
stackSlotItems.push(stackSlotItem);
}
else
{
this.logger.warning(`No ids found in Filter for StackSlot ${slotId} of Item ${item._id}.`);
}
}
return stackSlotItems;
}
/**
* Get cloned copy of all item data from items.json
* @returns array of ITemplateItem objects
@ -1006,7 +938,7 @@ export class ItemHelper
const cartridgeCountToAdd = (remainingSpace < maxPerStack) ? remainingSpace : maxPerStack;
// Add cartridge item into items array
ammoBox.push(this.createCartridges(ammoBox[0]._id, cartridgeTpl, cartridgeCountToAdd, location));
ammoBox.push(this.createCartridges(ammoBox[0]._id, cartridgeTpl, cartridgeCountToAdd, location, ammoBox[0].upd?.SpawnedInSession));
currentStoredCartridgeCount += cartridgeCountToAdd;
location++;
@ -1129,7 +1061,7 @@ export class ItemHelper
}
// Add cartridge item object into items array
magazine.push(this.createCartridges(magazine[0]._id, cartridgeTpl, cartridgeCountToAdd, location));
magazine.push(this.createCartridges(magazine[0]._id, cartridgeTpl, cartridgeCountToAdd, location, magazine[0].upd?.SpawnedInSession));
currentStoredCartridgeCount += cartridgeCountToAdd;
location++;
@ -1182,9 +1114,10 @@ export class ItemHelper
* @param ammoTpl Cartridge to insert
* @param stackCount Count of cartridges inside parent
* @param location Location inside parent (e.g. 0, 1)
* @param foundInRaid OPTIONAL - Are cartridges found in raid (SpawnedInSession)
* @returns Item
*/
public createCartridges(parentId: string, ammoTpl: string, stackCount: number, location: number): Item
public createCartridges(parentId: string, ammoTpl: string, stackCount: number, location: number, foundInRaid = false): Item
{
return {
_id: this.objectId.generate(),
@ -1192,7 +1125,10 @@ export class ItemHelper
parentId: parentId,
slotId: "cartridges",
location: location,
upd: { StackObjectsCount: stackCount },
upd: {
StackObjectsCount: stackCount,
SpawnedInSession: foundInRaid
},
};
}

View File

@ -306,6 +306,12 @@ export class QuestHelper
else
{
// Is child mod
if (rootItem.upd.SpawnedInSession)
{
// Propigate FiR status into child items
item.upd.SpawnedInSession = rootItem.upd.SpawnedInSession;
}
mods.push(item);
}
}

View File

@ -7,6 +7,7 @@ import { NotifierHelper } from "@spt-aki/helpers/NotifierHelper";
import { TraderHelper } from "@spt-aki/helpers/TraderHelper";
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
import { Dialogue, IUserDialogInfo, Message, MessageItems } from "@spt-aki/models/eft/profile/IAkiProfile";
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
import { MessageType } from "@spt-aki/models/enums/MessageType";
import { Traders } from "@spt-aki/models/enums/Traders";
import { ISendMessageDetails } from "@spt-aki/models/spt/dialog/ISendMessageDetails";
@ -461,17 +462,24 @@ export class MailSendService
reward.slotId = "main";
}
// Item is sanitised and ready to be put into holding array
itemsToSendToPlayer.data.push(reward);
// Boxes can contain sub-items
if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.AMMO_BOX))
{
const boxAndCartridges: Item[] = [reward];
this.itemHelper.addCartridgesToAmmoBox(boxAndCartridges, itemTemplate);
// Item can contain sub-items, add those to array e.g. ammo boxes
if (itemTemplate._props.StackSlots)
{
const stackSlotItems = this.itemHelper.generateItemsFromStackSlot(itemTemplate, reward._id);
for (const itemToAdd of stackSlotItems)
{
itemsToSendToPlayer.data.push(itemToAdd);
// Push box + cartridge children into array
itemsToSendToPlayer.data.push(...boxAndCartridges);
}
else
{
if ("StackSlots" in itemTemplate._props)
{
this.logger.error(`Reward: ${itemTemplate._id} not handled`);
}
// Item is sanitised and ready to be pushed into holding array
itemsToSendToPlayer.data.push(reward);
}
}