Server/project/src/services/InsuranceService.ts

554 lines
23 KiB
TypeScript
Raw Normal View History

2023-03-03 15:23:46 +00:00
import { inject, injectable } from "tsyringe";
import { DialogueHelper } from "@spt/helpers/DialogueHelper";
import { HandbookHelper } from "@spt/helpers/HandbookHelper";
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { SecureContainerHelper } from "@spt/helpers/SecureContainerHelper";
import { TraderHelper } from "@spt/helpers/TraderHelper";
import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { Item } from "@spt/models/eft/common/tables/IItem";
import { ITraderBase } from "@spt/models/eft/common/tables/ITrader";
import { IInsuredItemsData } from "@spt/models/eft/inRaid/IInsuredItemsData";
import { ISaveProgressRequestData } from "@spt/models/eft/inRaid/ISaveProgressRequestData";
import { BonusType } from "@spt/models/enums/BonusType";
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
import { MessageType } from "@spt/models/enums/MessageType";
import { IInsuranceConfig } from "@spt/models/spt/config/IInsuranceConfig";
import { ILostOnDeathConfig } from "@spt/models/spt/config/ILostOnDeathConfig";
import { IInsuranceEquipmentPkg } from "@spt/models/spt/services/IInsuranceEquipmentPkg";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
import { DatabaseServer } from "@spt/servers/DatabaseServer";
import { SaveServer } from "@spt/servers/SaveServer";
import { LocaleService } from "@spt/services/LocaleService";
import { LocalisationService } from "@spt/services/LocalisationService";
import { MailSendService } from "@spt/services/MailSendService";
import { ICloner } from "@spt/utils/cloners/ICloner";
import { HashUtil } from "@spt/utils/HashUtil";
import { RandomUtil } from "@spt/utils/RandomUtil";
import { TimeUtil } from "@spt/utils/TimeUtil";
2023-03-03 15:23:46 +00:00
@injectable()
export class InsuranceService
{
protected insured: Record<string, Record<string, Item[]>> = {};
2023-03-03 15:23:46 +00:00
protected insuranceConfig: IInsuranceConfig;
protected lostOnDeathConfig: ILostOnDeathConfig;
2023-03-03 15:23:46 +00:00
constructor(
@inject("WinstonLogger") protected logger: ILogger,
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("SecureContainerHelper") protected secureContainerHelper: SecureContainerHelper,
@inject("RandomUtil") protected randomUtil: RandomUtil,
@inject("ItemHelper") protected itemHelper: ItemHelper,
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
@inject("HashUtil") protected hashUtil: HashUtil,
2023-03-03 15:23:46 +00:00
@inject("TimeUtil") protected timeUtil: TimeUtil,
@inject("SaveServer") protected saveServer: SaveServer,
@inject("TraderHelper") protected traderHelper: TraderHelper,
@inject("DialogueHelper") protected dialogueHelper: DialogueHelper,
@inject("HandbookHelper") protected handbookHelper: HandbookHelper,
@inject("LocalisationService") protected localisationService: LocalisationService,
@inject("LocaleService") protected localeService: LocaleService,
@inject("MailSendService") protected mailSendService: MailSendService,
2023-11-13 11:13:25 -05:00
@inject("ConfigServer") protected configServer: ConfigServer,
@inject("RecursiveCloner") protected cloner: ICloner,
2023-03-03 15:23:46 +00:00
)
{
this.insuranceConfig = this.configServer.getConfig(ConfigTypes.INSURANCE);
this.lostOnDeathConfig = this.configServer.getConfig(ConfigTypes.LOST_ON_DEATH);
2023-03-03 15:23:46 +00:00
}
/**
* Does player have insurance array
* @param sessionId Player id
* @returns True if exists
*/
2023-03-03 15:23:46 +00:00
public insuranceExists(sessionId: string): boolean
{
return this.insured[sessionId] !== undefined;
}
/**
* Get all insured items by all traders for a profile
* @param sessionId Profile id (session id)
* @returns Item array
*/
public getInsurance(sessionId: string): Record<string, Item[]>
2023-03-03 15:23:46 +00:00
{
return this.insured[sessionId];
}
/**
* Get insured items by profile id + trader id
* @param sessionId Profile id (session id)
* @param traderId Trader items were insured with
* @returns Item array
*/
2023-03-03 15:23:46 +00:00
public getInsuranceItems(sessionId: string, traderId: string): Item[]
{
return this.insured[sessionId][traderId];
2023-03-03 15:23:46 +00:00
}
public resetInsurance(sessionId: string): void
{
this.insured[sessionId] = {};
}
/**
* Sends stored insured items as message to player
* @param pmcData profile to send insured items to
2023-03-03 15:23:46 +00:00
* @param sessionID SessionId of current player
* @param mapId Id of the map player died/exited that caused the insurance to be issued on
*/
public sendInsuredItems(pmcData: IPmcData, sessionID: string, mapId: string): void
{
// Check for Mark of The Unheard in special slot (only slot it can fit)
const markOfTheUnheardOnPlayer = pmcData.Inventory.items
.filter((item) => item.slotId?.startsWith("SpecialSlot"))
.find((item) => item._tpl === "65ddcc9cfa85b9f17d0dfb07");
// Get insurance items for each trader
2023-03-03 15:23:46 +00:00
for (const traderId in this.getInsurance(sessionID))
{
const traderBase = this.traderHelper.getTrader(traderId, sessionID);
let insuranceReturnTimestamp = this.getInsuranceReturnTimestamp(pmcData, traderBase);
if (markOfTheUnheardOnPlayer)
{
insuranceReturnTimestamp *= this.databaseServer.getTables()
.globals.config.Insurance.CoefOfHavingMarkOfUnknown;
}
2023-03-03 15:23:46 +00:00
const dialogueTemplates = this.databaseServer.getTables().traders[traderId].dialogue;
const systemData = {
date: this.timeUtil.getDateMailFormat(),
time: this.timeUtil.getTimeMailFormat(),
location: mapId,
2023-03-03 15:23:46 +00:00
};
// Send "i will go look for your stuff" message from trader to player
this.mailSendService.sendLocalisedNpcMessageToPlayer(
sessionID,
this.traderHelper.getTraderById(traderId),
MessageType.NPC_TRADER,
this.randomUtil.getArrayValue(dialogueTemplates.insuranceStart),
null,
this.timeUtil.getHoursAsSeconds(
this.databaseServer.getTables().globals.config.Insurance.MaxStorageTimeInHour,
),
systemData,
);
2023-03-03 15:23:46 +00:00
// Store insurance to send to player later in profile
// Store insurance return details in profile + "hey i found your stuff, here you go!" message details to send to player at a later date
2023-03-03 15:23:46 +00:00
this.saveServer.getProfile(sessionID).insurance.push({
scheduledTime: insuranceReturnTimestamp,
traderId: traderId,
maxStorageTime: this.timeUtil.getHoursAsSeconds(traderBase.insurance.max_storage_time),
systemData: systemData,
messageType: MessageType.INSURANCE_RETURN,
messageTemplateId: this.randomUtil.getArrayValue(dialogueTemplates.insuranceFound),
2023-11-13 11:13:25 -05:00
items: this.getInsurance(sessionID)[traderId],
2023-03-03 15:23:46 +00:00
});
}
this.resetInsurance(sessionID);
}
/**
* Check all root insured items and remove location property + set slotId to 'hideout'
* @param sessionId Session id
* @param traderId Trader id
*/
2023-04-24 14:03:41 +01:00
protected removeLocationProperty(sessionId: string, traderId: string): void
{
const insuredItems = this.getInsurance(sessionId)[traderId];
for (const insuredItem of this.getInsurance(sessionId)[traderId])
2023-04-24 14:03:41 +01:00
{
// Find insured items parent
const insuredItemsParent = insuredItems.find((x) => x._id === insuredItem.parentId);
if (!insuredItemsParent)
2023-04-24 14:03:41 +01:00
{
// Remove location + set slotId of insured items parent
2023-04-24 14:03:41 +01:00
insuredItem.slotId = "hideout";
delete insuredItem.location;
}
}
}
2023-03-03 15:23:46 +00:00
/**
* Get a timestamp of when insurance items should be sent to player based on trader used to insure
* Apply insurance return bonus if found in profile
2023-03-03 15:23:46 +00:00
* @param pmcData Player profile
* @param trader Trader base used to insure items
2023-03-03 15:23:46 +00:00
* @returns Timestamp to return items to player in seconds
*/
protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number
{
// If override inconfig is non-zero, use that instead of trader values
if (this.insuranceConfig.returnTimeOverrideSeconds > 0)
{
2023-11-13 11:13:25 -05:00
this.logger.debug(
`Insurance override used: returning in ${this.insuranceConfig.returnTimeOverrideSeconds} seconds`,
);
2023-03-03 15:23:46 +00:00
return this.timeUtil.getTimestamp() + this.insuranceConfig.returnTimeOverrideSeconds;
}
const insuranceReturnTimeBonus = pmcData.Bonuses.find((b) => b.type === BonusType.INSURANCE_RETURN_TIME);
const insuranceReturnTimeBonusPercent
= 1.0 - (insuranceReturnTimeBonus ? Math.abs(insuranceReturnTimeBonus.value) : 0) / 100;
2023-03-03 15:23:46 +00:00
const traderMinReturnAsSeconds = trader.insurance.min_return_hour * TimeUtil.ONE_HOUR_AS_SECONDS;
const traderMaxReturnAsSeconds = trader.insurance.max_return_hour * TimeUtil.ONE_HOUR_AS_SECONDS;
2023-03-03 15:23:46 +00:00
const randomisedReturnTimeSeconds = this.randomUtil.getInt(traderMinReturnAsSeconds, traderMaxReturnAsSeconds);
// Current time + randomised time calculated above
return this.timeUtil.getTimestamp() + randomisedReturnTimeSeconds * insuranceReturnTimeBonusPercent;
2023-03-03 15:23:46 +00:00
}
/**
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
* Create insurance equipment packages that should be sent to the user. The packages should contain items that have
* been lost in a raid and should be returned to the player through the insurance system.
*
* NOTE: We do not have data on items that were dropped in a raid. This means we have to pull item data from the
* profile at the start of the raid to return to the player in insurance. Because of this, the item
* positioning may differ from the position the item was in when the player died. Apart from removing all
* positioning, this is the best we can do. >:{}
*
* @param pmcData Player profile
* @param offraidData Post-raid data
* @param preRaidGear Pre-raid data
2023-03-03 15:23:46 +00:00
* @param sessionID Session id
* @param playerDied Did player die in raid
* @returns Array of insured items lost in raid
2023-03-03 15:23:46 +00:00
*/
public getGearLostInRaid(
2023-11-13 11:13:25 -05:00
pmcData: IPmcData,
offraidData: ISaveProgressRequestData,
preRaidGear: Item[],
sessionID: string,
playerDied: boolean,
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
): IInsuranceEquipmentPkg[]
2023-03-03 15:23:46 +00:00
{
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
const equipmentPkg: IInsuranceEquipmentPkg[] = [];
const preRaidGearMap = this.itemHelper.generateItemsMap(preRaidGear);
const offRaidGearMap = this.itemHelper.generateItemsMap(offraidData.profile.Inventory.items);
2023-03-03 15:23:46 +00:00
for (const insuredItem of pmcData.InsuredItems)
{
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
// Skip insured items not on player when they started the raid.
if (!preRaidGearMap.has(insuredItem.itemId))
{
continue;
}
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
const preRaidItem = preRaidGearMap.get(insuredItem.itemId);
// Skip slots we should never return as they're never lost on death
if (this.insuranceConfig.blacklistedEquipment.includes(preRaidItem.slotId))
{
continue;
}
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
// Equipment slots can be flagged as never lost on death and shouldn't be saved in an insurance package.
// We need to check if the item is directly equipped to an equipment slot, or if it is a child Item of an
// equipment slot.
const equipmentParentItem = this.itemHelper.getEquipmentParent(preRaidItem._id, preRaidGearMap);
const offraidDataitem = offraidData.insurance?.find(
(insuranceItem) => insuranceItem.id === insuredItem.itemId);
if (offraidDataitem?.usedInQuest)
{
continue;
}
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
// Now that we have the equipment parent item, we can check to see if that item is located in an equipment
// slot that is flagged as lost on death. If it is, then the itemShouldBeLostOnDeath.
const itemShouldBeLostOnDeath = this.lostOnDeathConfig.equipment[equipmentParentItem?.slotId] ?? true;
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
// Was the item found in the player inventory post-raid?
const itemOnPlayerPostRaid = offRaidGearMap.has(insuredItem.itemId);
// Check if item missing in post-raid gear OR player died + item slot flagged as lost on death
2024-01-11 12:48:10 +00:00
// Catches both events: player died with item on + player survived but dropped item in raid
if (!itemOnPlayerPostRaid || (playerDied && itemShouldBeLostOnDeath))
2023-03-03 15:23:46 +00:00
{
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
equipmentPkg.push({
pmcData: pmcData,
itemToReturnToPlayer: this.getInsuredItemDetails(
pmcData,
preRaidItem,
offraidData.insurance?.find((insuranceItem) => insuranceItem.id === insuredItem.itemId),
),
traderId: insuredItem.tid,
2023-11-13 11:13:25 -05:00
sessionID: sessionID,
});
// Armor item with slots, we need to include soft_inserts as they can never be removed from armor items
if (this.itemHelper.armorItemCanHoldMods(preRaidItem._tpl))
{
if (this.itemHelper.itemHasSlots(preRaidItem._tpl))
{
// Get IDs of all soft insert child items on armor from pre raid gear data
const softInsertChildIds = preRaidGear
.filter(
(item) =>
item.parentId === preRaidItem._id
&& this.itemHelper.getSoftInsertSlotIds().includes(item.slotId.toLowerCase()),
)
.map((x) => x._id);
// Add all items found above to return data
for (const softInsertChildModId of softInsertChildIds)
{
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
equipmentPkg.push({
pmcData: pmcData,
itemToReturnToPlayer: this.getInsuredItemDetails(
pmcData,
preRaidGear.find((item) => item._id === softInsertChildModId),
offraidData.insurance?.find(
(insuranceItem) => insuranceItem.id === softInsertChildModId,
),
),
traderId: insuredItem.tid,
sessionID: sessionID,
});
}
}
}
2023-03-03 15:23:46 +00:00
}
}
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
return equipmentPkg;
}
/**
* Take the insurance item packages within a profile session and ensure that each of the items in that package are
* not orphaned from their parent ID.
*
* @param sessionID The session ID to update insurance equipment packages in.
* @returns void
*/
protected adoptOrphanedInsEquipment(sessionID: string): void
{
const rootID = this.getRootItemParentID(sessionID);
const insuranceData = this.getInsurance(sessionID);
for (const [traderId, items] of Object.entries(insuranceData))
{
this.insured[sessionID][traderId] = this.itemHelper.adoptOrphanedItems(rootID, items);
}
}
/**
* Store lost gear post-raid inside profile, ready for later code to pick it up and mail it
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
* @param equipmentPkg Gear to store - generated by getGearLostInRaid()
*/
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
public storeGearLostInRaidToSendLater(sessionID: string, equipmentPkg: IInsuranceEquipmentPkg[]): void
{
// Process all insured items lost in-raid
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
for (const gear of equipmentPkg)
2023-03-03 15:23:46 +00:00
{
this.addGearToSend(gear);
2023-03-03 15:23:46 +00:00
}
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
// Items are separated into their individual trader packages, now we can ensure that they all have valid parents
this.adoptOrphanedInsEquipment(sessionID);
2023-03-03 15:23:46 +00:00
}
2023-04-24 14:03:41 +01:00
/**
* Take preraid item and update properties to ensure its ready to be given to player in insurance return mail
* @param pmcData Player profile
* @param preRaidItemWithChildren Insured item (with children) as it was pre-raid
2024-01-23 20:19:53 +00:00
* @param allItemsFromClient Item data when player left raid (durability values)
* @returns Item (with children) to send to player
2023-04-24 14:03:41 +01:00
*/
2023-11-13 11:13:25 -05:00
protected getInsuredItemDetails(
pmcData: IPmcData,
preRaidItem: Item,
insuredItemFromClient: IInsuredItemsData,
): Item
2023-04-24 14:03:41 +01:00
{
// Get baseline item to return, clone pre raid item
const itemToReturnClone: Item = this.cloner.clone(preRaidItem);
// Add upd if it doesnt exist
this.itemHelper.addUpdObjectToItem(itemToReturnClone);
// Check for slotid values that need to be updated and adjust
this.updateSlotIdValue(pmcData.Inventory.equipment, itemToReturnClone);
// Remove location property
if (itemToReturnClone.slotId === "hideout" && "location" in itemToReturnClone)
{
delete itemToReturnClone.location;
}
// Remove found in raid status when upd exists + SpawnedInSession value exists
if ("SpawnedInSession" in itemToReturnClone.upd)
{
itemToReturnClone.upd.SpawnedInSession = false;
}
// Client item has durability values, Ensure values persist into server data
if (insuredItemFromClient?.durability)
{
// Item didnt have Repairable object pre-raid, add it
if (!itemToReturnClone.upd.Repairable)
{
itemToReturnClone.upd.Repairable = {
Durability: insuredItemFromClient.durability,
MaxDurability: insuredItemFromClient.maxDurability,
};
}
else
{
itemToReturnClone.upd.Repairable.Durability = insuredItemFromClient.durability;
itemToReturnClone.upd.Repairable.MaxDurability = insuredItemFromClient.maxDurability;
}
}
// Client item has FaceShield values, Ensure values persist into server data
if (insuredItemFromClient?.hits)
{
// Item didnt have faceshield object pre-raid, add it
if (!itemToReturnClone.upd.FaceShield)
{
itemToReturnClone.upd.FaceShield = { Hits: insuredItemFromClient.hits };
}
else
{
itemToReturnClone.upd.FaceShield.Hits = insuredItemFromClient.hits;
}
}
return itemToReturnClone;
2023-04-24 14:03:41 +01:00
}
2023-03-03 15:23:46 +00:00
/**
* Reset slotId property to "hideout" when necessary (used to be in )
* @param pmcData Players pmcData.Inventory.equipment value
* @param itemToReturn item we will send to player as insurance return
2023-03-03 15:23:46 +00:00
*/
protected updateSlotIdValue(playerBaseInventoryEquipmentId: string, itemToReturn: Item): void
2023-03-03 15:23:46 +00:00
{
const pocketSlots = ["pocket1", "pocket2", "pocket3", "pocket4"];
2023-03-03 15:23:46 +00:00
// Some pockets can lose items with player death, some don't
2023-11-13 11:13:25 -05:00
if (!("slotId" in itemToReturn) || pocketSlots.includes(itemToReturn.slotId))
2023-03-03 15:23:46 +00:00
{
itemToReturn.slotId = "hideout";
2023-03-03 15:23:46 +00:00
}
// Mark root-level items for later processing
2023-11-13 11:13:25 -05:00
if (itemToReturn.parentId === playerBaseInventoryEquipmentId)
2023-03-03 15:23:46 +00:00
{
itemToReturn.slotId = "hideout";
2023-03-03 15:23:46 +00:00
}
}
2023-03-03 15:23:46 +00:00
/**
* Add gear item to InsuredItems array in player profile
* @param sessionID Session id
* @param pmcData Player profile
* @param itemToReturnToPlayer item to store
* @param traderId Id of trader item was insured with
*/
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
protected addGearToSend(gear: IInsuranceEquipmentPkg): void
{
const sessionId = gear.sessionID;
const pmcData = gear.pmcData;
const itemToReturnToPlayer = gear.itemToReturnToPlayer;
const traderId = gear.traderId;
2023-03-03 15:23:46 +00:00
// Ensure insurance array is init
if (!this.insuranceExists(sessionId))
2023-03-03 15:23:46 +00:00
{
this.resetInsurance(sessionId);
2023-03-03 15:23:46 +00:00
}
// init trader insurance array
if (!this.insuranceTraderArrayExists(sessionId, traderId))
2023-03-03 15:23:46 +00:00
{
this.resetInsuranceTraderArray(sessionId, traderId);
2023-03-03 15:23:46 +00:00
}
this.addInsuranceItemToArray(sessionId, traderId, itemToReturnToPlayer);
2023-03-03 15:23:46 +00:00
// Remove item from insured items array as its been processed
pmcData.InsuredItems = pmcData.InsuredItems.filter((item) =>
{
return item.itemId !== itemToReturnToPlayer._id;
});
2023-03-03 15:23:46 +00:00
}
/**
* Does insurance exist for a player and by trader
* @param sessionId Player id (session id)
* @param traderId Trader items insured with
* @returns True if exists
*/
protected insuranceTraderArrayExists(sessionId: string, traderId: string): boolean
{
return this.insured[sessionId][traderId] !== undefined;
}
/**
* Empty out array holding insured items by sessionid + traderid
* @param sessionId Player id (session id)
* @param traderId Trader items insured with
*/
public resetInsuranceTraderArray(sessionId: string, traderId: string): void
{
this.insured[sessionId][traderId] = [];
}
/**
* Store insured item
* @param sessionId Player id (session id)
* @param traderId Trader item insured with
* @param itemToAdd Insured item (with children)
*/
public addInsuranceItemToArray(sessionId: string, traderId: string, itemToAdd: Item): void
{
this.insured[sessionId][traderId].push(itemToAdd);
}
/**
* Get price of insurance * multiplier from config
* @param pmcData Player profile
* @param inventoryItem Item to be insured
* @param traderId Trader item is insured with
* @returns price in roubles
*/
2023-03-03 15:23:46 +00:00
public getPremium(pmcData: IPmcData, inventoryItem: Item, traderId: string): number
{
let insuranceMultiplier = this.insuranceConfig.insuranceMultiplier[traderId];
if (!insuranceMultiplier)
{
insuranceMultiplier = 0.3;
2023-11-13 11:13:25 -05:00
this.logger.warning(
this.localisationService.getText("insurance-missing_insurance_price_multiplier", traderId),
);
2023-03-03 15:23:46 +00:00
}
// Multiply item handbook price by multiplier in config to get the new insurance price
let pricePremium = this.itemHelper.getStaticItemPrice(inventoryItem._tpl) * insuranceMultiplier;
2023-03-03 15:23:46 +00:00
const coef = this.traderHelper.getLoyaltyLevel(traderId, pmcData).insurance_price_coef;
if (coef > 0)
{
2023-11-13 11:13:25 -05:00
pricePremium *= 1 - this.traderHelper.getLoyaltyLevel(traderId, pmcData).insurance_price_coef / 100;
2023-03-03 15:23:46 +00:00
}
return Math.round(pricePremium);
2023-03-03 15:23:46 +00:00
}
Refactor Insurance Processing for Gear Lost in Raids Notable coding Changes: - Added `getRootItemParentID` method in `InsuranceService` to standardize the determination of the root insurance container. - Added `IInsuranceEquipmentPkg` model for structuring insurance packages, a type used to store insurance item data before it's saved in the profile. - Added `HashUtil` in `InsuranceController` and `InsuranceService` for generating an ID for the root insurance container in the case that the root ID cannot be found. - Updated and normalized item map generation and usage across `InsuranceService` and `InsuranceController`. - Updated `ItemHelper` with new methods `adoptOrphanedItems` and `generateItemsMap`, facilitating better management of item relationships and efficient item look-ups. - Updated `InsuranceController.findItemsToDelete` and related methods to use the new `rootItemParentID` parameter to ensure that all root level items share the same parent ID. - Updated logic in `InsuranceService` for creating insurance packages and handling orphaned items. Uh-huh, but what would you say you do here? - Resolves an issue that arose when `lostondeath.json` equipment configuration options were set to `false`. On death, the equipment's children items would be sent back to the player through insurance, duplicating them. - Resolves an issue that prevented items from appearing in an insurance return even though they passed an insurance roll. - Improved debug logging. Remaining Oopses: - We do not have data on items that were dropped in a raid. This means we have to pull item data from the profile at the start of the raid to return to the player in insurance. Because of this, the item positioning may differ from the position the item was in when the player died. Apart from removing all positioning, this is the best we can do. Resolves #425
2024-02-08 15:56:45 -05:00
/**
* Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance.
*
* @returns The ID.
*/
public getRootItemParentID(sessionID: string): string
{
// Try to use the equipment id from the profile. I'm not sure this is strictly required, but it feels neat.
return this.saveServer.getProfile(sessionID)?.characters?.pmc?.Inventory?.equipment ?? this.hashUtil.generate();
}
2023-11-13 11:13:25 -05:00
}