diff --git a/TypeScript/10ScopesAndTypes/types/controllers/InsuranceController.d.ts b/TypeScript/10ScopesAndTypes/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/10ScopesAndTypes/types/controllers/InsuranceController.d.ts +++ b/TypeScript/10ScopesAndTypes/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/10ScopesAndTypes/types/helpers/InventoryHelper.d.ts b/TypeScript/10ScopesAndTypes/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/10ScopesAndTypes/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/10ScopesAndTypes/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/10ScopesAndTypes/types/helpers/ItemHelper.d.ts b/TypeScript/10ScopesAndTypes/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/10ScopesAndTypes/types/helpers/ItemHelper.d.ts +++ b/TypeScript/10ScopesAndTypes/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/10ScopesAndTypes/types/helpers/TraderHelper.d.ts b/TypeScript/10ScopesAndTypes/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/10ScopesAndTypes/types/helpers/TraderHelper.d.ts +++ b/TypeScript/10ScopesAndTypes/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/10ScopesAndTypes/types/services/MailSendService.d.ts b/TypeScript/10ScopesAndTypes/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/10ScopesAndTypes/types/services/MailSendService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/11BundleLoadingSample/types/controllers/InsuranceController.d.ts b/TypeScript/11BundleLoadingSample/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/11BundleLoadingSample/types/controllers/InsuranceController.d.ts +++ b/TypeScript/11BundleLoadingSample/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/11BundleLoadingSample/types/helpers/InventoryHelper.d.ts b/TypeScript/11BundleLoadingSample/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/11BundleLoadingSample/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/11BundleLoadingSample/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/11BundleLoadingSample/types/helpers/ItemHelper.d.ts b/TypeScript/11BundleLoadingSample/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/11BundleLoadingSample/types/helpers/ItemHelper.d.ts +++ b/TypeScript/11BundleLoadingSample/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/11BundleLoadingSample/types/helpers/TraderHelper.d.ts b/TypeScript/11BundleLoadingSample/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/11BundleLoadingSample/types/helpers/TraderHelper.d.ts +++ b/TypeScript/11BundleLoadingSample/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/11BundleLoadingSample/types/services/MailSendService.d.ts b/TypeScript/11BundleLoadingSample/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/11BundleLoadingSample/types/services/MailSendService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/12ClassExtensionOverride/types/controllers/InsuranceController.d.ts b/TypeScript/12ClassExtensionOverride/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/12ClassExtensionOverride/types/controllers/InsuranceController.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/12ClassExtensionOverride/types/helpers/InventoryHelper.d.ts b/TypeScript/12ClassExtensionOverride/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/12ClassExtensionOverride/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/12ClassExtensionOverride/types/helpers/ItemHelper.d.ts b/TypeScript/12ClassExtensionOverride/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/12ClassExtensionOverride/types/helpers/ItemHelper.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/12ClassExtensionOverride/types/helpers/TraderHelper.d.ts b/TypeScript/12ClassExtensionOverride/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/12ClassExtensionOverride/types/helpers/TraderHelper.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/12ClassExtensionOverride/types/services/MailSendService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/MailSendService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/13AddTrader/types/controllers/InsuranceController.d.ts b/TypeScript/13AddTrader/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/13AddTrader/types/controllers/InsuranceController.d.ts +++ b/TypeScript/13AddTrader/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/13AddTrader/types/helpers/InventoryHelper.d.ts b/TypeScript/13AddTrader/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/13AddTrader/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/13AddTrader/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/13AddTrader/types/helpers/ItemHelper.d.ts b/TypeScript/13AddTrader/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/13AddTrader/types/helpers/ItemHelper.d.ts +++ b/TypeScript/13AddTrader/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/13AddTrader/types/helpers/TraderHelper.d.ts b/TypeScript/13AddTrader/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/13AddTrader/types/helpers/TraderHelper.d.ts +++ b/TypeScript/13AddTrader/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/13AddTrader/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/13AddTrader/types/services/MailSendService.d.ts b/TypeScript/13AddTrader/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/13AddTrader/types/services/MailSendService.d.ts +++ b/TypeScript/13AddTrader/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/14AfterDBLoadHook/types/controllers/InsuranceController.d.ts b/TypeScript/14AfterDBLoadHook/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/14AfterDBLoadHook/types/controllers/InsuranceController.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/14AfterDBLoadHook/types/helpers/InventoryHelper.d.ts b/TypeScript/14AfterDBLoadHook/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/14AfterDBLoadHook/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/14AfterDBLoadHook/types/helpers/ItemHelper.d.ts b/TypeScript/14AfterDBLoadHook/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/14AfterDBLoadHook/types/helpers/ItemHelper.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/14AfterDBLoadHook/types/helpers/TraderHelper.d.ts b/TypeScript/14AfterDBLoadHook/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/14AfterDBLoadHook/types/helpers/TraderHelper.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/14AfterDBLoadHook/types/services/MailSendService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/MailSendService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/15HttpListenerExample/types/controllers/InsuranceController.d.ts b/TypeScript/15HttpListenerExample/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/15HttpListenerExample/types/controllers/InsuranceController.d.ts +++ b/TypeScript/15HttpListenerExample/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/15HttpListenerExample/types/helpers/InventoryHelper.d.ts b/TypeScript/15HttpListenerExample/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/15HttpListenerExample/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/15HttpListenerExample/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/15HttpListenerExample/types/helpers/ItemHelper.d.ts b/TypeScript/15HttpListenerExample/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/15HttpListenerExample/types/helpers/ItemHelper.d.ts +++ b/TypeScript/15HttpListenerExample/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/15HttpListenerExample/types/helpers/TraderHelper.d.ts b/TypeScript/15HttpListenerExample/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/15HttpListenerExample/types/helpers/TraderHelper.d.ts +++ b/TypeScript/15HttpListenerExample/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/15HttpListenerExample/types/services/MailSendService.d.ts b/TypeScript/15HttpListenerExample/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/15HttpListenerExample/types/services/MailSendService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/16ImporterUtil/types/controllers/InsuranceController.d.ts b/TypeScript/16ImporterUtil/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/16ImporterUtil/types/controllers/InsuranceController.d.ts +++ b/TypeScript/16ImporterUtil/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/16ImporterUtil/types/helpers/InventoryHelper.d.ts b/TypeScript/16ImporterUtil/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/16ImporterUtil/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/16ImporterUtil/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/16ImporterUtil/types/helpers/ItemHelper.d.ts b/TypeScript/16ImporterUtil/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/16ImporterUtil/types/helpers/ItemHelper.d.ts +++ b/TypeScript/16ImporterUtil/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/16ImporterUtil/types/helpers/TraderHelper.d.ts b/TypeScript/16ImporterUtil/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/16ImporterUtil/types/helpers/TraderHelper.d.ts +++ b/TypeScript/16ImporterUtil/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/16ImporterUtil/types/services/MailSendService.d.ts b/TypeScript/16ImporterUtil/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/16ImporterUtil/types/services/MailSendService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/controllers/InsuranceController.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/controllers/InsuranceController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/17AsyncImporterWithDependency1/types/helpers/InventoryHelper.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/helpers/ItemHelper.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/helpers/ItemHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/17AsyncImporterWithDependency1/types/helpers/TraderHelper.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/helpers/TraderHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/MailSendService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/MailSendService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/controllers/InsuranceController.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/controllers/InsuranceController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/17AsyncImporterWithDependency2/types/helpers/InventoryHelper.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/helpers/ItemHelper.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/helpers/ItemHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/17AsyncImporterWithDependency2/types/helpers/TraderHelper.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/helpers/TraderHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/MailSendService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/MailSendService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/18CustomItemService/types/controllers/InsuranceController.d.ts b/TypeScript/18CustomItemService/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/18CustomItemService/types/controllers/InsuranceController.d.ts +++ b/TypeScript/18CustomItemService/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/18CustomItemService/types/helpers/InventoryHelper.d.ts b/TypeScript/18CustomItemService/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/18CustomItemService/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/18CustomItemService/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/18CustomItemService/types/helpers/ItemHelper.d.ts b/TypeScript/18CustomItemService/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/18CustomItemService/types/helpers/ItemHelper.d.ts +++ b/TypeScript/18CustomItemService/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/18CustomItemService/types/helpers/TraderHelper.d.ts b/TypeScript/18CustomItemService/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/18CustomItemService/types/helpers/TraderHelper.d.ts +++ b/TypeScript/18CustomItemService/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/18CustomItemService/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/18CustomItemService/types/services/MailSendService.d.ts b/TypeScript/18CustomItemService/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/18CustomItemService/types/services/MailSendService.d.ts +++ b/TypeScript/18CustomItemService/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/1LogToConsole/types/controllers/InsuranceController.d.ts b/TypeScript/1LogToConsole/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/1LogToConsole/types/controllers/InsuranceController.d.ts +++ b/TypeScript/1LogToConsole/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/1LogToConsole/types/helpers/InventoryHelper.d.ts b/TypeScript/1LogToConsole/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/1LogToConsole/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/1LogToConsole/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/1LogToConsole/types/helpers/ItemHelper.d.ts b/TypeScript/1LogToConsole/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/1LogToConsole/types/helpers/ItemHelper.d.ts +++ b/TypeScript/1LogToConsole/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/1LogToConsole/types/helpers/TraderHelper.d.ts b/TypeScript/1LogToConsole/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/1LogToConsole/types/helpers/TraderHelper.d.ts +++ b/TypeScript/1LogToConsole/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/1LogToConsole/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/1LogToConsole/types/services/MailSendService.d.ts b/TypeScript/1LogToConsole/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/1LogToConsole/types/services/MailSendService.d.ts +++ b/TypeScript/1LogToConsole/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/2EditDatabase/types/controllers/InsuranceController.d.ts b/TypeScript/2EditDatabase/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/2EditDatabase/types/controllers/InsuranceController.d.ts +++ b/TypeScript/2EditDatabase/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/2EditDatabase/types/helpers/InventoryHelper.d.ts b/TypeScript/2EditDatabase/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/2EditDatabase/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/2EditDatabase/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/2EditDatabase/types/helpers/ItemHelper.d.ts b/TypeScript/2EditDatabase/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/2EditDatabase/types/helpers/ItemHelper.d.ts +++ b/TypeScript/2EditDatabase/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/2EditDatabase/types/helpers/TraderHelper.d.ts b/TypeScript/2EditDatabase/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/2EditDatabase/types/helpers/TraderHelper.d.ts +++ b/TypeScript/2EditDatabase/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/2EditDatabase/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/2EditDatabase/types/services/MailSendService.d.ts b/TypeScript/2EditDatabase/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/2EditDatabase/types/services/MailSendService.d.ts +++ b/TypeScript/2EditDatabase/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/3GetSptConfigFile/types/controllers/InsuranceController.d.ts b/TypeScript/3GetSptConfigFile/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/3GetSptConfigFile/types/controllers/InsuranceController.d.ts +++ b/TypeScript/3GetSptConfigFile/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/3GetSptConfigFile/types/helpers/InventoryHelper.d.ts b/TypeScript/3GetSptConfigFile/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/3GetSptConfigFile/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/3GetSptConfigFile/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/3GetSptConfigFile/types/helpers/ItemHelper.d.ts b/TypeScript/3GetSptConfigFile/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/3GetSptConfigFile/types/helpers/ItemHelper.d.ts +++ b/TypeScript/3GetSptConfigFile/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/3GetSptConfigFile/types/helpers/TraderHelper.d.ts b/TypeScript/3GetSptConfigFile/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/3GetSptConfigFile/types/helpers/TraderHelper.d.ts +++ b/TypeScript/3GetSptConfigFile/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/3GetSptConfigFile/types/services/MailSendService.d.ts b/TypeScript/3GetSptConfigFile/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/3GetSptConfigFile/types/services/MailSendService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/4UseACustomConfigFile/types/controllers/InsuranceController.d.ts b/TypeScript/4UseACustomConfigFile/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/4UseACustomConfigFile/types/controllers/InsuranceController.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/4UseACustomConfigFile/types/helpers/InventoryHelper.d.ts b/TypeScript/4UseACustomConfigFile/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/4UseACustomConfigFile/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/4UseACustomConfigFile/types/helpers/ItemHelper.d.ts b/TypeScript/4UseACustomConfigFile/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/4UseACustomConfigFile/types/helpers/ItemHelper.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/4UseACustomConfigFile/types/helpers/TraderHelper.d.ts b/TypeScript/4UseACustomConfigFile/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/4UseACustomConfigFile/types/helpers/TraderHelper.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/4UseACustomConfigFile/types/services/MailSendService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/MailSendService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/5ReplaceMethod/types/controllers/InsuranceController.d.ts b/TypeScript/5ReplaceMethod/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/5ReplaceMethod/types/controllers/InsuranceController.d.ts +++ b/TypeScript/5ReplaceMethod/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/5ReplaceMethod/types/helpers/InventoryHelper.d.ts b/TypeScript/5ReplaceMethod/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/5ReplaceMethod/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/5ReplaceMethod/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/5ReplaceMethod/types/helpers/ItemHelper.d.ts b/TypeScript/5ReplaceMethod/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/5ReplaceMethod/types/helpers/ItemHelper.d.ts +++ b/TypeScript/5ReplaceMethod/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/5ReplaceMethod/types/helpers/TraderHelper.d.ts b/TypeScript/5ReplaceMethod/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/5ReplaceMethod/types/helpers/TraderHelper.d.ts +++ b/TypeScript/5ReplaceMethod/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/5ReplaceMethod/types/services/MailSendService.d.ts b/TypeScript/5ReplaceMethod/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/5ReplaceMethod/types/services/MailSendService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/6ReferenceAnotherClass/types/controllers/InsuranceController.d.ts b/TypeScript/6ReferenceAnotherClass/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/6ReferenceAnotherClass/types/controllers/InsuranceController.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/6ReferenceAnotherClass/types/helpers/InventoryHelper.d.ts b/TypeScript/6ReferenceAnotherClass/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/6ReferenceAnotherClass/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/6ReferenceAnotherClass/types/helpers/ItemHelper.d.ts b/TypeScript/6ReferenceAnotherClass/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/6ReferenceAnotherClass/types/helpers/ItemHelper.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/6ReferenceAnotherClass/types/helpers/TraderHelper.d.ts b/TypeScript/6ReferenceAnotherClass/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/6ReferenceAnotherClass/types/helpers/TraderHelper.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/6ReferenceAnotherClass/types/services/MailSendService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/MailSendService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/7OnLoadHook/types/controllers/InsuranceController.d.ts b/TypeScript/7OnLoadHook/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/7OnLoadHook/types/controllers/InsuranceController.d.ts +++ b/TypeScript/7OnLoadHook/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/7OnLoadHook/types/helpers/InventoryHelper.d.ts b/TypeScript/7OnLoadHook/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/7OnLoadHook/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/7OnLoadHook/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/7OnLoadHook/types/helpers/ItemHelper.d.ts b/TypeScript/7OnLoadHook/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/7OnLoadHook/types/helpers/ItemHelper.d.ts +++ b/TypeScript/7OnLoadHook/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/7OnLoadHook/types/helpers/TraderHelper.d.ts b/TypeScript/7OnLoadHook/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/7OnLoadHook/types/helpers/TraderHelper.d.ts +++ b/TypeScript/7OnLoadHook/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/7OnLoadHook/types/services/MailSendService.d.ts b/TypeScript/7OnLoadHook/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/7OnLoadHook/types/services/MailSendService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/8OnUpdateHook/types/controllers/InsuranceController.d.ts b/TypeScript/8OnUpdateHook/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/8OnUpdateHook/types/controllers/InsuranceController.d.ts +++ b/TypeScript/8OnUpdateHook/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/8OnUpdateHook/types/helpers/InventoryHelper.d.ts b/TypeScript/8OnUpdateHook/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/8OnUpdateHook/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/8OnUpdateHook/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/8OnUpdateHook/types/helpers/ItemHelper.d.ts b/TypeScript/8OnUpdateHook/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/8OnUpdateHook/types/helpers/ItemHelper.d.ts +++ b/TypeScript/8OnUpdateHook/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/8OnUpdateHook/types/helpers/TraderHelper.d.ts b/TypeScript/8OnUpdateHook/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/8OnUpdateHook/types/helpers/TraderHelper.d.ts +++ b/TypeScript/8OnUpdateHook/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/8OnUpdateHook/types/services/MailSendService.d.ts b/TypeScript/8OnUpdateHook/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/8OnUpdateHook/types/services/MailSendService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void; diff --git a/TypeScript/9RouterHooks/types/controllers/InsuranceController.d.ts b/TypeScript/9RouterHooks/types/controllers/InsuranceController.d.ts index dbb6b4b..061d0c9 100644 --- a/TypeScript/9RouterHooks/types/controllers/InsuranceController.d.ts +++ b/TypeScript/9RouterHooks/types/controllers/InsuranceController.d.ts @@ -1,8 +1,10 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { ProfileHelper } from "../helpers/ProfileHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; import { Item } from "../models/eft/common/tables/IItem"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData"; import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData"; @@ -15,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; +import { MailSendService } from "../services/MailSendService"; import { PaymentService } from "../services/PaymentService"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -28,31 +31,134 @@ export declare class InsuranceController { protected itemHelper: ItemHelper; protected profileHelper: ProfileHelper; protected dialogueHelper: DialogueHelper; + protected traderHelper: TraderHelper; protected paymentService: PaymentService; protected insuranceService: InsuranceService; + protected mailSendService: MailSendService; protected configServer: ConfigServer; protected insuranceConfig: IInsuranceConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer); + constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer); /** - * Process insurance items prior to being given to player in mail - */ + * Process insurance items of all profiles prior to being given back to the player through the mail service. + * + * @returns void + */ processReturn(): void; /** - * Change SlotId of children inside Containers to be a root item - * @param insured Insured Items - */ - protected updateSlotIdOfContainersChildren(insured: Insurance): void; + * Process insurance items of a single profile prior to being given back to the player through the mail service. + * + * @returns void + */ + processReturnByProfile(sessionID: string): void; /** - * Should the passed in item be removed from player inventory - * @param insuredItem Insurued item to roll to lose - * @param traderId Trader the item was insured by - * @param itemsBeingDeleted All items to remove from player - * @returns True if item should be removed + * Get all insured items that are ready to be processed in a specific profile. + * + * @param sessionID Session ID of the profile to check. + * @param time The time to check ready status against. Current time by default. + * @returns All insured items that are ready to be processed. */ - protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected filterInsuredItems(sessionID: string, time?: number): Insurance[]; + /** + * This method orchestrates the processing of insured items in a profile. + * + * @param insuranceDetails The insured items to process. + * @param sessionID The session ID that should receive the processed items. + * @returns void + */ + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; + /** + * Build an array of items to delete from the insured items. + * + * This method orchestrates several steps: + * - Filters items based on their presence in the database and their raid moddability. + * - Sorts base and independent child items to consider for deletion. + * - Groups child items by their parent for later evaluation. + * - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll. + * + * @param insured - The insured items to build a removal array from. + * @returns An array of IDs representing items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): string[]; + /** + * Filters an item based on its existence in the database, raid moddability, and slot requirements. + * + * @param item The item to be filtered. + * @param parentItemDbDetails The database details of the parent item, or null if the item has no parent. + * @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database, + * and the second element is the item details if it does. + * @returns true if the item exists in the database and neither of the following conditions are met: + * - The item has the RaidModdable property set to false. + * - The item is attached to a required slot in its parent item. + * Otherwise, returns false. + */ + protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean; + /** + * Determines if an item is either a base item or a child item that is not equipped to its parent. + * + * @param item The item to check. + * @returns true if the item is a base or an independent child item, otherwise false. + */ + protected isBaseOrIndependentChild(item: Item): boolean; + /** + * Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added + * to the `toDelete` array. + * + * @param item The item for which the roll is made. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array accumulating the IDs of items to be deleted. + * @returns true if the item is marked for deletion, otherwise false. + */ + protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean; + /** + * Groups child items by their parent IDs in a Map data structure. + * + * @param item The child item to be grouped by its parent. + * @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs. + * @returns void + */ + protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + /** + * Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to + * determine if it should be deleted. The method then deletes the most valuable children based on the number of + * successful rolls made. + * + * @param children The array of children items to sort and filter. + * @param traderId The ID of the trader to consider in the rollForItemDelete method. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + * @returns void + */ + protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void; + /** + * Remove items from the insured items that should not be returned to the player. + * + * @param insured The insured items to process. + * @param toDelete The items that should be deleted. + * @returns void + */ + protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + /** + * Handle sending the insurance message to the user that potentially contains the valid insurance items. + * + * @param sessionID The session ID that should receive the insurance message. + * @param insurance The context of insurance to use. + * @param noItems Whether or not there are any items to return to the player. + * @returns void + */ + protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void; + /** + * Determines whether a valid insured item should be removed from the player's inventory based on a random roll and + * trader-specific return chance. + * + * @param insuredItem The insured item being evaluated for removal. + * @param traderId The ID of the trader who insured the item. + * @param itemsBeingDeleted List of items that are already slated for removal. + * @returns true if the insured item should be removed from inventory, false otherwise. + */ + protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; /** * Handle Insure event * Add insurance to an item + * * @param pmcData Player profile * @param body Insurance request * @param sessionID Session id @@ -62,6 +168,7 @@ export declare class InsuranceController { /** * Handle client/insurance/items/list/cost * Calculate insurance cost + * * @param request request object * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client diff --git a/TypeScript/9RouterHooks/types/helpers/InventoryHelper.d.ts b/TypeScript/9RouterHooks/types/helpers/InventoryHelper.d.ts index 3215426..a627c0f 100644 --- a/TypeScript/9RouterHooks/types/helpers/InventoryHelper.d.ts +++ b/TypeScript/9RouterHooks/types/helpers/InventoryHelper.d.ts @@ -84,13 +84,13 @@ export declare class InventoryHelper { * Handle Remove event * Remove item from player inventory + insured items array * Also deletes child items - * @param pmcData Profile to remove item from + * @param profile Profile to remove item from (pmc or scav) * @param itemId Items id to remove * @param sessionID Session id * @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied * @returns IItemEventRouterResponse */ - removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; + removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse; removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse; getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[]; diff --git a/TypeScript/9RouterHooks/types/helpers/ItemHelper.d.ts b/TypeScript/9RouterHooks/types/helpers/ItemHelper.d.ts index 00f190f..f58ca4d 100644 --- a/TypeScript/9RouterHooks/types/helpers/ItemHelper.d.ts +++ b/TypeScript/9RouterHooks/types/helpers/ItemHelper.d.ts @@ -56,6 +56,13 @@ declare class ItemHelper { * @returns Price in roubles */ getItemPrice(tpl: string): number; + /** + * Returns the item price based on the handbook or as a fallback from the prices.json if the item is not + * found in the handbook. If the price can't be found at all return 0 + * @param tpl Item to look price up of + * @returns Price in roubles + */ + getItemMaxPrice(tpl: string): number; /** * Get the static (handbook) price in roubles for an item by tpl * @param tpl Items tpl id to look up price diff --git a/TypeScript/9RouterHooks/types/helpers/TraderHelper.d.ts b/TypeScript/9RouterHooks/types/helpers/TraderHelper.d.ts index 6680ccf..8cdfb76 100644 --- a/TypeScript/9RouterHooks/types/helpers/TraderHelper.d.ts +++ b/TypeScript/9RouterHooks/types/helpers/TraderHelper.d.ts @@ -115,10 +115,31 @@ export declare class TraderHelper { * @returns Traders key */ getTraderById(traderId: string): Traders; + /** + * Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the + * same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string. + * This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key. + * + * For example, instead of this: + * `const traderId = Traders[Traders.PRAPOR];` + * + * You can use safely use this: + * `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);` + * + * @param traderEnumValue The trader enum value to validate + * @returns The validated trader enum value as a string, or an empty string if invalid + */ + getValidTraderIdByEnumValue(traderEnumValue: Traders): string; /** * Does the 'Traders' enum has a value that matches the passed in parameter - * @param value Value to check for + * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - traderEnumHasValue(value: string): boolean; + traderEnumHasKey(key: string): boolean; + /** + * Accepts a trader id + * @param traderId Trader id + * @returns Ttrue if Traders enum has the param as a value + */ + traderEnumHasValue(traderId: string): boolean; } diff --git a/TypeScript/9RouterHooks/types/models/spt/config/IInsuranceConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/IInsuranceConfig.d.ts index 9443cb7..b51dc8b 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/IInsuranceConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/IInsuranceConfig.d.ts @@ -7,8 +7,6 @@ export interface IInsuranceConfig extends IBaseConfig { returnChancePercent: Record; /** Item slots that should never be returned as insurance */ blacklistedEquipment: string[]; - /** Names of equipment slots that could not be returned as insurance */ - slotIdsWithChanceOfNotReturning: string[]; /** Override to control how quickly insurance is processed/returned in second */ returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ diff --git a/TypeScript/9RouterHooks/types/services/MailSendService.d.ts b/TypeScript/9RouterHooks/types/services/MailSendService.d.ts index fe4a7fe..abe8c09 100644 --- a/TypeScript/9RouterHooks/types/services/MailSendService.d.ts +++ b/TypeScript/9RouterHooks/types/services/MailSendService.d.ts @@ -2,6 +2,7 @@ import { DialogueHelper } from "../helpers/DialogueHelper"; import { ItemHelper } from "../helpers/ItemHelper"; import { NotificationSendHelper } from "../helpers/NotificationSendHelper"; import { NotifierHelper } from "../helpers/NotifierHelper"; +import { TraderHelper } from "../helpers/TraderHelper"; import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, IUserDialogInfo, Message, MessageItems } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; @@ -24,56 +25,57 @@ export declare class MailSendService { protected notificationSendHelper: NotificationSendHelper; protected localisationService: LocalisationService; protected itemHelper: ItemHelper; + protected traderHelper: TraderHelper; protected readonly systemSenderId = "59e7125688a45068a6249071"; - constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper); + constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, localisationService: LocalisationService, itemHelper: ItemHelper, traderHelper: TraderHelper); /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param message Text to send to the player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendDirectNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from an NPC (e.g. prapor) to the player with or without items - * @param playerId Players id to send message to - * @param sender The trader sending the message + * @param sessionId The session ID to send the message to + * @param trader The trader sending the message * @param messageType What type the message will assume (e.g. QUEST_SUCCESS) * @param messageLocaleId The localised text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedNpcMessageToPlayer(playerId: string, sender: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; + sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any, systemData?: any, ragfair?: any): void; /** * Send a message from SYSTEM to the player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendSystemMessageToPlayer(playerId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendSystemMessageToPlayer(sessionId: string, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** - * Send a message from SYSTEM to the player with or without items with loalised text - * @param playerId Players id to send message to + * Send a message from SYSTEM to the player with or without items with localised text + * @param sessionId The session ID to send the message to * @param messageLocaleId Id of key from locale file to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendLocalisedSystemMessageToPlayer(playerId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Send a USER message to a player with or without items - * @param playerId Players id to send message to + * @param sessionId The session ID to send the message to * @param senderId Who is sending the message * @param message The text to send to player * @param items Optional items to send to player * @param maxStorageTimeSeconds Optional time to collect items before they expire */ - sendUserMessageToPlayer(playerId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; + sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items?: Item[], maxStorageTimeSeconds?: any): void; /** * Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER) - * Helper functions in this class are availble to simplify common actions + * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ sendMessageToPlayer(messageDetails: ISendMessageDetails): void;