diff --git a/README.md b/README.md index e2122ea..3947a46 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Mod examples for v3.7.0 +# Mod examples for v3.7.1 A collection of example mods that perform typical actions in SPT diff --git a/TypeScript/10ScopesAndTypes/README.md b/TypeScript/10ScopesAndTypes/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/10ScopesAndTypes/README.md +++ b/TypeScript/10ScopesAndTypes/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/10ScopesAndTypes/types/controllers/GameController.d.ts b/TypeScript/10ScopesAndTypes/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/10ScopesAndTypes/types/controllers/GameController.d.ts +++ b/TypeScript/10ScopesAndTypes/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/10ScopesAndTypes/types/controllers/InraidController.d.ts b/TypeScript/10ScopesAndTypes/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/10ScopesAndTypes/types/controllers/InraidController.d.ts +++ b/TypeScript/10ScopesAndTypes/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/10ScopesAndTypes/types/controllers/InsuranceController.d.ts b/TypeScript/10ScopesAndTypes/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/10ScopesAndTypes/types/controllers/InsuranceController.d.ts +++ b/TypeScript/10ScopesAndTypes/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/10ScopesAndTypes/types/controllers/MatchController.d.ts b/TypeScript/10ScopesAndTypes/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/10ScopesAndTypes/types/controllers/MatchController.d.ts +++ b/TypeScript/10ScopesAndTypes/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/10ScopesAndTypes/types/controllers/RepeatableQuestController.d.ts b/TypeScript/10ScopesAndTypes/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/10ScopesAndTypes/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/10ScopesAndTypes/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/10ScopesAndTypes/types/di/Serializer.d.ts b/TypeScript/10ScopesAndTypes/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/10ScopesAndTypes/types/di/Serializer.d.ts +++ b/TypeScript/10ScopesAndTypes/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/10ScopesAndTypes/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/10ScopesAndTypes/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/10ScopesAndTypes/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/10ScopesAndTypes/types/helpers/InRaidHelper.d.ts b/TypeScript/10ScopesAndTypes/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/10ScopesAndTypes/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/10ScopesAndTypes/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/10ScopesAndTypes/types/helpers/ItemHelper.d.ts b/TypeScript/10ScopesAndTypes/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/10ScopesAndTypes/types/helpers/ItemHelper.d.ts +++ b/TypeScript/10ScopesAndTypes/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/10ScopesAndTypes/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/10ScopesAndTypes/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/10ScopesAndTypes/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/10ScopesAndTypes/types/loaders/PreAkiModLoader.d.ts b/TypeScript/10ScopesAndTypes/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/10ScopesAndTypes/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/10ScopesAndTypes/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/10ScopesAndTypes/types/models/external/HttpFramework.d.ts b/TypeScript/10ScopesAndTypes/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/10ScopesAndTypes/types/models/external/HttpFramework.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/IItemConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/10ScopesAndTypes/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/10ScopesAndTypes/types/models/spt/services/LootRequest.d.ts b/TypeScript/10ScopesAndTypes/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/10ScopesAndTypes/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/10ScopesAndTypes/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/10ScopesAndTypes/types/routers/EventOutputHolder.d.ts b/TypeScript/10ScopesAndTypes/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/10ScopesAndTypes/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/10ScopesAndTypes/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/10ScopesAndTypes/types/routers/HttpRouter.d.ts b/TypeScript/10ScopesAndTypes/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/10ScopesAndTypes/types/routers/HttpRouter.d.ts +++ b/TypeScript/10ScopesAndTypes/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/10ScopesAndTypes/types/routers/ImageRouter.d.ts b/TypeScript/10ScopesAndTypes/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/10ScopesAndTypes/types/routers/ImageRouter.d.ts +++ b/TypeScript/10ScopesAndTypes/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/10ScopesAndTypes/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/10ScopesAndTypes/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/10ScopesAndTypes/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/10ScopesAndTypes/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/10ScopesAndTypes/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/10ScopesAndTypes/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/10ScopesAndTypes/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/10ScopesAndTypes/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/10ScopesAndTypes/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/10ScopesAndTypes/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/10ScopesAndTypes/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/10ScopesAndTypes/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/10ScopesAndTypes/types/servers/HttpServer.d.ts b/TypeScript/10ScopesAndTypes/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/10ScopesAndTypes/types/servers/HttpServer.d.ts +++ b/TypeScript/10ScopesAndTypes/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/10ScopesAndTypes/types/servers/WebSocketServer.d.ts b/TypeScript/10ScopesAndTypes/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/10ScopesAndTypes/types/servers/WebSocketServer.d.ts +++ b/TypeScript/10ScopesAndTypes/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/10ScopesAndTypes/types/servers/http/AkiHttpListener.d.ts b/TypeScript/10ScopesAndTypes/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/10ScopesAndTypes/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/10ScopesAndTypes/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/10ScopesAndTypes/types/servers/http/IHttpListener.d.ts b/TypeScript/10ScopesAndTypes/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/10ScopesAndTypes/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/10ScopesAndTypes/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/10ScopesAndTypes/types/services/ItemFilterService.d.ts b/TypeScript/10ScopesAndTypes/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/10ScopesAndTypes/types/services/ItemFilterService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/10ScopesAndTypes/types/services/ProfileFixerService.d.ts b/TypeScript/10ScopesAndTypes/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/10ScopesAndTypes/types/services/ProfileFixerService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/10ScopesAndTypes/types/services/SeasonalEventService.d.ts b/TypeScript/10ScopesAndTypes/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/10ScopesAndTypes/types/services/SeasonalEventService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/10ScopesAndTypes/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/10ScopesAndTypes/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/10ScopesAndTypes/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/10ScopesAndTypes/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/10ScopesAndTypes/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/10ScopesAndTypes/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/10ScopesAndTypes/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/10ScopesAndTypes/types/utils/App.d.ts b/TypeScript/10ScopesAndTypes/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/10ScopesAndTypes/types/utils/App.d.ts +++ b/TypeScript/10ScopesAndTypes/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/10ScopesAndTypes/types/utils/HashUtil.d.ts b/TypeScript/10ScopesAndTypes/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/10ScopesAndTypes/types/utils/HashUtil.d.ts +++ b/TypeScript/10ScopesAndTypes/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/10ScopesAndTypes/types/utils/HttpFileUtil.d.ts b/TypeScript/10ScopesAndTypes/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/10ScopesAndTypes/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/10ScopesAndTypes/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/10ScopesAndTypes/types/utils/VFS.d.ts b/TypeScript/10ScopesAndTypes/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/10ScopesAndTypes/types/utils/VFS.d.ts +++ b/TypeScript/10ScopesAndTypes/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/10ScopesAndTypes/types/utils/Watermark.d.ts b/TypeScript/10ScopesAndTypes/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/10ScopesAndTypes/types/utils/Watermark.d.ts +++ b/TypeScript/10ScopesAndTypes/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/10ScopesAndTypes/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/10ScopesAndTypes/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/10ScopesAndTypes/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/10ScopesAndTypes/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/11BundleLoadingSample/README.md b/TypeScript/11BundleLoadingSample/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/11BundleLoadingSample/README.md +++ b/TypeScript/11BundleLoadingSample/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/11BundleLoadingSample/types/controllers/GameController.d.ts b/TypeScript/11BundleLoadingSample/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/11BundleLoadingSample/types/controllers/GameController.d.ts +++ b/TypeScript/11BundleLoadingSample/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/11BundleLoadingSample/types/controllers/InraidController.d.ts b/TypeScript/11BundleLoadingSample/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/11BundleLoadingSample/types/controllers/InraidController.d.ts +++ b/TypeScript/11BundleLoadingSample/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/11BundleLoadingSample/types/controllers/InsuranceController.d.ts b/TypeScript/11BundleLoadingSample/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/11BundleLoadingSample/types/controllers/InsuranceController.d.ts +++ b/TypeScript/11BundleLoadingSample/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/11BundleLoadingSample/types/controllers/MatchController.d.ts b/TypeScript/11BundleLoadingSample/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/11BundleLoadingSample/types/controllers/MatchController.d.ts +++ b/TypeScript/11BundleLoadingSample/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/11BundleLoadingSample/types/controllers/RepeatableQuestController.d.ts b/TypeScript/11BundleLoadingSample/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/11BundleLoadingSample/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/11BundleLoadingSample/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/11BundleLoadingSample/types/di/Serializer.d.ts b/TypeScript/11BundleLoadingSample/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/11BundleLoadingSample/types/di/Serializer.d.ts +++ b/TypeScript/11BundleLoadingSample/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/11BundleLoadingSample/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/11BundleLoadingSample/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/11BundleLoadingSample/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/11BundleLoadingSample/types/helpers/InRaidHelper.d.ts b/TypeScript/11BundleLoadingSample/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/11BundleLoadingSample/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/11BundleLoadingSample/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/11BundleLoadingSample/types/helpers/ItemHelper.d.ts b/TypeScript/11BundleLoadingSample/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/11BundleLoadingSample/types/helpers/ItemHelper.d.ts +++ b/TypeScript/11BundleLoadingSample/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/11BundleLoadingSample/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/11BundleLoadingSample/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/11BundleLoadingSample/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/11BundleLoadingSample/types/loaders/PreAkiModLoader.d.ts b/TypeScript/11BundleLoadingSample/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/11BundleLoadingSample/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/11BundleLoadingSample/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/11BundleLoadingSample/types/models/external/HttpFramework.d.ts b/TypeScript/11BundleLoadingSample/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/11BundleLoadingSample/types/models/external/HttpFramework.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/IItemConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/11BundleLoadingSample/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/11BundleLoadingSample/types/models/spt/services/LootRequest.d.ts b/TypeScript/11BundleLoadingSample/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/11BundleLoadingSample/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/11BundleLoadingSample/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/11BundleLoadingSample/types/routers/EventOutputHolder.d.ts b/TypeScript/11BundleLoadingSample/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/11BundleLoadingSample/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/11BundleLoadingSample/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/11BundleLoadingSample/types/routers/HttpRouter.d.ts b/TypeScript/11BundleLoadingSample/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/11BundleLoadingSample/types/routers/HttpRouter.d.ts +++ b/TypeScript/11BundleLoadingSample/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/11BundleLoadingSample/types/routers/ImageRouter.d.ts b/TypeScript/11BundleLoadingSample/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/11BundleLoadingSample/types/routers/ImageRouter.d.ts +++ b/TypeScript/11BundleLoadingSample/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/11BundleLoadingSample/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/11BundleLoadingSample/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/11BundleLoadingSample/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/11BundleLoadingSample/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/11BundleLoadingSample/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/11BundleLoadingSample/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/11BundleLoadingSample/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/11BundleLoadingSample/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/11BundleLoadingSample/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/11BundleLoadingSample/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/11BundleLoadingSample/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/11BundleLoadingSample/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/11BundleLoadingSample/types/servers/HttpServer.d.ts b/TypeScript/11BundleLoadingSample/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/11BundleLoadingSample/types/servers/HttpServer.d.ts +++ b/TypeScript/11BundleLoadingSample/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/11BundleLoadingSample/types/servers/WebSocketServer.d.ts b/TypeScript/11BundleLoadingSample/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/11BundleLoadingSample/types/servers/WebSocketServer.d.ts +++ b/TypeScript/11BundleLoadingSample/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/11BundleLoadingSample/types/servers/http/AkiHttpListener.d.ts b/TypeScript/11BundleLoadingSample/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/11BundleLoadingSample/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/11BundleLoadingSample/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/11BundleLoadingSample/types/servers/http/IHttpListener.d.ts b/TypeScript/11BundleLoadingSample/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/11BundleLoadingSample/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/11BundleLoadingSample/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/11BundleLoadingSample/types/services/ItemFilterService.d.ts b/TypeScript/11BundleLoadingSample/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/11BundleLoadingSample/types/services/ItemFilterService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/11BundleLoadingSample/types/services/ProfileFixerService.d.ts b/TypeScript/11BundleLoadingSample/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/11BundleLoadingSample/types/services/ProfileFixerService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/11BundleLoadingSample/types/services/SeasonalEventService.d.ts b/TypeScript/11BundleLoadingSample/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/11BundleLoadingSample/types/services/SeasonalEventService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/11BundleLoadingSample/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/11BundleLoadingSample/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/11BundleLoadingSample/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/11BundleLoadingSample/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/11BundleLoadingSample/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/11BundleLoadingSample/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/11BundleLoadingSample/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/11BundleLoadingSample/types/utils/App.d.ts b/TypeScript/11BundleLoadingSample/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/11BundleLoadingSample/types/utils/App.d.ts +++ b/TypeScript/11BundleLoadingSample/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/11BundleLoadingSample/types/utils/HashUtil.d.ts b/TypeScript/11BundleLoadingSample/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/11BundleLoadingSample/types/utils/HashUtil.d.ts +++ b/TypeScript/11BundleLoadingSample/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/11BundleLoadingSample/types/utils/HttpFileUtil.d.ts b/TypeScript/11BundleLoadingSample/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/11BundleLoadingSample/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/11BundleLoadingSample/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/11BundleLoadingSample/types/utils/VFS.d.ts b/TypeScript/11BundleLoadingSample/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/11BundleLoadingSample/types/utils/VFS.d.ts +++ b/TypeScript/11BundleLoadingSample/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/11BundleLoadingSample/types/utils/Watermark.d.ts b/TypeScript/11BundleLoadingSample/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/11BundleLoadingSample/types/utils/Watermark.d.ts +++ b/TypeScript/11BundleLoadingSample/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/11BundleLoadingSample/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/11BundleLoadingSample/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/11BundleLoadingSample/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/11BundleLoadingSample/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/12ClassExtensionOverride/README.md b/TypeScript/12ClassExtensionOverride/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/12ClassExtensionOverride/README.md +++ b/TypeScript/12ClassExtensionOverride/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/12ClassExtensionOverride/types/controllers/GameController.d.ts b/TypeScript/12ClassExtensionOverride/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/12ClassExtensionOverride/types/controllers/GameController.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/12ClassExtensionOverride/types/controllers/InraidController.d.ts b/TypeScript/12ClassExtensionOverride/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/12ClassExtensionOverride/types/controllers/InraidController.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/12ClassExtensionOverride/types/controllers/InsuranceController.d.ts b/TypeScript/12ClassExtensionOverride/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/12ClassExtensionOverride/types/controllers/InsuranceController.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/12ClassExtensionOverride/types/controllers/MatchController.d.ts b/TypeScript/12ClassExtensionOverride/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/12ClassExtensionOverride/types/controllers/MatchController.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/12ClassExtensionOverride/types/controllers/RepeatableQuestController.d.ts b/TypeScript/12ClassExtensionOverride/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/12ClassExtensionOverride/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/12ClassExtensionOverride/types/di/Serializer.d.ts b/TypeScript/12ClassExtensionOverride/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/12ClassExtensionOverride/types/di/Serializer.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/12ClassExtensionOverride/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/12ClassExtensionOverride/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/12ClassExtensionOverride/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/12ClassExtensionOverride/types/helpers/InRaidHelper.d.ts b/TypeScript/12ClassExtensionOverride/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/12ClassExtensionOverride/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/12ClassExtensionOverride/types/helpers/ItemHelper.d.ts b/TypeScript/12ClassExtensionOverride/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/12ClassExtensionOverride/types/helpers/ItemHelper.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/12ClassExtensionOverride/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/12ClassExtensionOverride/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/12ClassExtensionOverride/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/12ClassExtensionOverride/types/loaders/PreAkiModLoader.d.ts b/TypeScript/12ClassExtensionOverride/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/12ClassExtensionOverride/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/12ClassExtensionOverride/types/models/external/HttpFramework.d.ts b/TypeScript/12ClassExtensionOverride/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/external/HttpFramework.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IItemConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/12ClassExtensionOverride/types/models/spt/services/LootRequest.d.ts b/TypeScript/12ClassExtensionOverride/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/12ClassExtensionOverride/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/12ClassExtensionOverride/types/routers/EventOutputHolder.d.ts b/TypeScript/12ClassExtensionOverride/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/12ClassExtensionOverride/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/12ClassExtensionOverride/types/routers/HttpRouter.d.ts b/TypeScript/12ClassExtensionOverride/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/12ClassExtensionOverride/types/routers/HttpRouter.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/12ClassExtensionOverride/types/routers/ImageRouter.d.ts b/TypeScript/12ClassExtensionOverride/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/12ClassExtensionOverride/types/routers/ImageRouter.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/12ClassExtensionOverride/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/12ClassExtensionOverride/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/12ClassExtensionOverride/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/12ClassExtensionOverride/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/12ClassExtensionOverride/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/12ClassExtensionOverride/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/12ClassExtensionOverride/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/12ClassExtensionOverride/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/12ClassExtensionOverride/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/12ClassExtensionOverride/types/servers/HttpServer.d.ts b/TypeScript/12ClassExtensionOverride/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/12ClassExtensionOverride/types/servers/HttpServer.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/12ClassExtensionOverride/types/servers/WebSocketServer.d.ts b/TypeScript/12ClassExtensionOverride/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/12ClassExtensionOverride/types/servers/WebSocketServer.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/12ClassExtensionOverride/types/servers/http/AkiHttpListener.d.ts b/TypeScript/12ClassExtensionOverride/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/12ClassExtensionOverride/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/12ClassExtensionOverride/types/servers/http/IHttpListener.d.ts b/TypeScript/12ClassExtensionOverride/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/12ClassExtensionOverride/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/12ClassExtensionOverride/types/services/ItemFilterService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/ItemFilterService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/12ClassExtensionOverride/types/services/ProfileFixerService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/ProfileFixerService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/12ClassExtensionOverride/types/services/SeasonalEventService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/SeasonalEventService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/12ClassExtensionOverride/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/12ClassExtensionOverride/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/12ClassExtensionOverride/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/12ClassExtensionOverride/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/12ClassExtensionOverride/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/12ClassExtensionOverride/types/utils/App.d.ts b/TypeScript/12ClassExtensionOverride/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/12ClassExtensionOverride/types/utils/App.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/12ClassExtensionOverride/types/utils/HashUtil.d.ts b/TypeScript/12ClassExtensionOverride/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/12ClassExtensionOverride/types/utils/HashUtil.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/12ClassExtensionOverride/types/utils/HttpFileUtil.d.ts b/TypeScript/12ClassExtensionOverride/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/12ClassExtensionOverride/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/12ClassExtensionOverride/types/utils/VFS.d.ts b/TypeScript/12ClassExtensionOverride/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/12ClassExtensionOverride/types/utils/VFS.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/12ClassExtensionOverride/types/utils/Watermark.d.ts b/TypeScript/12ClassExtensionOverride/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/12ClassExtensionOverride/types/utils/Watermark.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/12ClassExtensionOverride/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/12ClassExtensionOverride/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/12ClassExtensionOverride/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/12ClassExtensionOverride/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/13AddTrader/README.md b/TypeScript/13AddTrader/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/13AddTrader/README.md +++ b/TypeScript/13AddTrader/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/13AddTrader/types/controllers/GameController.d.ts b/TypeScript/13AddTrader/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/13AddTrader/types/controllers/GameController.d.ts +++ b/TypeScript/13AddTrader/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/13AddTrader/types/controllers/InraidController.d.ts b/TypeScript/13AddTrader/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/13AddTrader/types/controllers/InraidController.d.ts +++ b/TypeScript/13AddTrader/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/13AddTrader/types/controllers/InsuranceController.d.ts b/TypeScript/13AddTrader/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/13AddTrader/types/controllers/InsuranceController.d.ts +++ b/TypeScript/13AddTrader/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/13AddTrader/types/controllers/MatchController.d.ts b/TypeScript/13AddTrader/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/13AddTrader/types/controllers/MatchController.d.ts +++ b/TypeScript/13AddTrader/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/13AddTrader/types/controllers/RepeatableQuestController.d.ts b/TypeScript/13AddTrader/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/13AddTrader/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/13AddTrader/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/13AddTrader/types/di/Serializer.d.ts b/TypeScript/13AddTrader/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/13AddTrader/types/di/Serializer.d.ts +++ b/TypeScript/13AddTrader/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/13AddTrader/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/13AddTrader/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/13AddTrader/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/13AddTrader/types/helpers/InRaidHelper.d.ts b/TypeScript/13AddTrader/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/13AddTrader/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/13AddTrader/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/13AddTrader/types/helpers/ItemHelper.d.ts b/TypeScript/13AddTrader/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/13AddTrader/types/helpers/ItemHelper.d.ts +++ b/TypeScript/13AddTrader/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/13AddTrader/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/13AddTrader/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/13AddTrader/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/13AddTrader/types/loaders/PreAkiModLoader.d.ts b/TypeScript/13AddTrader/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/13AddTrader/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/13AddTrader/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/13AddTrader/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/13AddTrader/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/13AddTrader/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/13AddTrader/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/13AddTrader/types/models/external/HttpFramework.d.ts b/TypeScript/13AddTrader/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/13AddTrader/types/models/external/HttpFramework.d.ts +++ b/TypeScript/13AddTrader/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/13AddTrader/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/13AddTrader/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/13AddTrader/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/13AddTrader/types/models/spt/config/IItemConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/13AddTrader/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/13AddTrader/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/13AddTrader/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/13AddTrader/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/13AddTrader/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/13AddTrader/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/13AddTrader/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/13AddTrader/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/13AddTrader/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/13AddTrader/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/13AddTrader/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/13AddTrader/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/13AddTrader/types/models/spt/services/LootRequest.d.ts b/TypeScript/13AddTrader/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/13AddTrader/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/13AddTrader/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/13AddTrader/types/routers/EventOutputHolder.d.ts b/TypeScript/13AddTrader/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/13AddTrader/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/13AddTrader/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/13AddTrader/types/routers/HttpRouter.d.ts b/TypeScript/13AddTrader/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/13AddTrader/types/routers/HttpRouter.d.ts +++ b/TypeScript/13AddTrader/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/13AddTrader/types/routers/ImageRouter.d.ts b/TypeScript/13AddTrader/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/13AddTrader/types/routers/ImageRouter.d.ts +++ b/TypeScript/13AddTrader/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/13AddTrader/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/13AddTrader/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/13AddTrader/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/13AddTrader/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/13AddTrader/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/13AddTrader/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/13AddTrader/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/13AddTrader/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/13AddTrader/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/13AddTrader/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/13AddTrader/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/13AddTrader/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/13AddTrader/types/servers/HttpServer.d.ts b/TypeScript/13AddTrader/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/13AddTrader/types/servers/HttpServer.d.ts +++ b/TypeScript/13AddTrader/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/13AddTrader/types/servers/WebSocketServer.d.ts b/TypeScript/13AddTrader/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/13AddTrader/types/servers/WebSocketServer.d.ts +++ b/TypeScript/13AddTrader/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/13AddTrader/types/servers/http/AkiHttpListener.d.ts b/TypeScript/13AddTrader/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/13AddTrader/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/13AddTrader/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/13AddTrader/types/servers/http/IHttpListener.d.ts b/TypeScript/13AddTrader/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/13AddTrader/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/13AddTrader/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/13AddTrader/types/services/ItemFilterService.d.ts b/TypeScript/13AddTrader/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/13AddTrader/types/services/ItemFilterService.d.ts +++ b/TypeScript/13AddTrader/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/13AddTrader/types/services/ProfileFixerService.d.ts b/TypeScript/13AddTrader/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/13AddTrader/types/services/ProfileFixerService.d.ts +++ b/TypeScript/13AddTrader/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/13AddTrader/types/services/SeasonalEventService.d.ts b/TypeScript/13AddTrader/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/13AddTrader/types/services/SeasonalEventService.d.ts +++ b/TypeScript/13AddTrader/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/13AddTrader/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/13AddTrader/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/13AddTrader/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/13AddTrader/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/13AddTrader/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/13AddTrader/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/13AddTrader/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/13AddTrader/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/13AddTrader/types/utils/App.d.ts b/TypeScript/13AddTrader/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/13AddTrader/types/utils/App.d.ts +++ b/TypeScript/13AddTrader/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/13AddTrader/types/utils/HashUtil.d.ts b/TypeScript/13AddTrader/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/13AddTrader/types/utils/HashUtil.d.ts +++ b/TypeScript/13AddTrader/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/13AddTrader/types/utils/HttpFileUtil.d.ts b/TypeScript/13AddTrader/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/13AddTrader/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/13AddTrader/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/13AddTrader/types/utils/VFS.d.ts b/TypeScript/13AddTrader/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/13AddTrader/types/utils/VFS.d.ts +++ b/TypeScript/13AddTrader/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/13AddTrader/types/utils/Watermark.d.ts b/TypeScript/13AddTrader/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/13AddTrader/types/utils/Watermark.d.ts +++ b/TypeScript/13AddTrader/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/13AddTrader/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/13AddTrader/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/13AddTrader/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/13AddTrader/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/14AfterDBLoadHook/README.md b/TypeScript/14AfterDBLoadHook/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/14AfterDBLoadHook/README.md +++ b/TypeScript/14AfterDBLoadHook/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/14AfterDBLoadHook/types/controllers/GameController.d.ts b/TypeScript/14AfterDBLoadHook/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/14AfterDBLoadHook/types/controllers/GameController.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/14AfterDBLoadHook/types/controllers/InraidController.d.ts b/TypeScript/14AfterDBLoadHook/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/14AfterDBLoadHook/types/controllers/InraidController.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/14AfterDBLoadHook/types/controllers/InsuranceController.d.ts b/TypeScript/14AfterDBLoadHook/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/14AfterDBLoadHook/types/controllers/InsuranceController.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/14AfterDBLoadHook/types/controllers/MatchController.d.ts b/TypeScript/14AfterDBLoadHook/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/14AfterDBLoadHook/types/controllers/MatchController.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/14AfterDBLoadHook/types/controllers/RepeatableQuestController.d.ts b/TypeScript/14AfterDBLoadHook/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/14AfterDBLoadHook/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/14AfterDBLoadHook/types/di/Serializer.d.ts b/TypeScript/14AfterDBLoadHook/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/14AfterDBLoadHook/types/di/Serializer.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/14AfterDBLoadHook/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/14AfterDBLoadHook/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/14AfterDBLoadHook/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/14AfterDBLoadHook/types/helpers/InRaidHelper.d.ts b/TypeScript/14AfterDBLoadHook/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/14AfterDBLoadHook/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/14AfterDBLoadHook/types/helpers/ItemHelper.d.ts b/TypeScript/14AfterDBLoadHook/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/14AfterDBLoadHook/types/helpers/ItemHelper.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/14AfterDBLoadHook/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/14AfterDBLoadHook/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/14AfterDBLoadHook/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/14AfterDBLoadHook/types/loaders/PreAkiModLoader.d.ts b/TypeScript/14AfterDBLoadHook/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/14AfterDBLoadHook/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/14AfterDBLoadHook/types/models/external/HttpFramework.d.ts b/TypeScript/14AfterDBLoadHook/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/external/HttpFramework.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IItemConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/14AfterDBLoadHook/types/models/spt/services/LootRequest.d.ts b/TypeScript/14AfterDBLoadHook/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/14AfterDBLoadHook/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/14AfterDBLoadHook/types/routers/EventOutputHolder.d.ts b/TypeScript/14AfterDBLoadHook/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/14AfterDBLoadHook/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/14AfterDBLoadHook/types/routers/HttpRouter.d.ts b/TypeScript/14AfterDBLoadHook/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/14AfterDBLoadHook/types/routers/HttpRouter.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/14AfterDBLoadHook/types/routers/ImageRouter.d.ts b/TypeScript/14AfterDBLoadHook/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/14AfterDBLoadHook/types/routers/ImageRouter.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/14AfterDBLoadHook/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/14AfterDBLoadHook/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/14AfterDBLoadHook/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/14AfterDBLoadHook/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/14AfterDBLoadHook/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/14AfterDBLoadHook/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/14AfterDBLoadHook/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/14AfterDBLoadHook/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/14AfterDBLoadHook/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/14AfterDBLoadHook/types/servers/HttpServer.d.ts b/TypeScript/14AfterDBLoadHook/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/14AfterDBLoadHook/types/servers/HttpServer.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/14AfterDBLoadHook/types/servers/WebSocketServer.d.ts b/TypeScript/14AfterDBLoadHook/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/14AfterDBLoadHook/types/servers/WebSocketServer.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/14AfterDBLoadHook/types/servers/http/AkiHttpListener.d.ts b/TypeScript/14AfterDBLoadHook/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/14AfterDBLoadHook/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/14AfterDBLoadHook/types/servers/http/IHttpListener.d.ts b/TypeScript/14AfterDBLoadHook/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/14AfterDBLoadHook/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/14AfterDBLoadHook/types/services/ItemFilterService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/ItemFilterService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/14AfterDBLoadHook/types/services/ProfileFixerService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/ProfileFixerService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/14AfterDBLoadHook/types/services/SeasonalEventService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/SeasonalEventService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/14AfterDBLoadHook/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/14AfterDBLoadHook/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/14AfterDBLoadHook/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/14AfterDBLoadHook/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/14AfterDBLoadHook/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/14AfterDBLoadHook/types/utils/App.d.ts b/TypeScript/14AfterDBLoadHook/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/14AfterDBLoadHook/types/utils/App.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/14AfterDBLoadHook/types/utils/HashUtil.d.ts b/TypeScript/14AfterDBLoadHook/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/14AfterDBLoadHook/types/utils/HashUtil.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/14AfterDBLoadHook/types/utils/HttpFileUtil.d.ts b/TypeScript/14AfterDBLoadHook/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/14AfterDBLoadHook/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/14AfterDBLoadHook/types/utils/VFS.d.ts b/TypeScript/14AfterDBLoadHook/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/14AfterDBLoadHook/types/utils/VFS.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/14AfterDBLoadHook/types/utils/Watermark.d.ts b/TypeScript/14AfterDBLoadHook/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/14AfterDBLoadHook/types/utils/Watermark.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/14AfterDBLoadHook/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/14AfterDBLoadHook/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/14AfterDBLoadHook/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/14AfterDBLoadHook/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/15HttpListenerExample/README.md b/TypeScript/15HttpListenerExample/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/15HttpListenerExample/README.md +++ b/TypeScript/15HttpListenerExample/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/15HttpListenerExample/types/controllers/GameController.d.ts b/TypeScript/15HttpListenerExample/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/15HttpListenerExample/types/controllers/GameController.d.ts +++ b/TypeScript/15HttpListenerExample/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/15HttpListenerExample/types/controllers/InraidController.d.ts b/TypeScript/15HttpListenerExample/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/15HttpListenerExample/types/controllers/InraidController.d.ts +++ b/TypeScript/15HttpListenerExample/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/15HttpListenerExample/types/controllers/InsuranceController.d.ts b/TypeScript/15HttpListenerExample/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/15HttpListenerExample/types/controllers/InsuranceController.d.ts +++ b/TypeScript/15HttpListenerExample/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/15HttpListenerExample/types/controllers/MatchController.d.ts b/TypeScript/15HttpListenerExample/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/15HttpListenerExample/types/controllers/MatchController.d.ts +++ b/TypeScript/15HttpListenerExample/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/15HttpListenerExample/types/controllers/RepeatableQuestController.d.ts b/TypeScript/15HttpListenerExample/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/15HttpListenerExample/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/15HttpListenerExample/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/15HttpListenerExample/types/di/Serializer.d.ts b/TypeScript/15HttpListenerExample/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/15HttpListenerExample/types/di/Serializer.d.ts +++ b/TypeScript/15HttpListenerExample/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/15HttpListenerExample/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/15HttpListenerExample/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/15HttpListenerExample/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/15HttpListenerExample/types/helpers/InRaidHelper.d.ts b/TypeScript/15HttpListenerExample/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/15HttpListenerExample/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/15HttpListenerExample/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/15HttpListenerExample/types/helpers/ItemHelper.d.ts b/TypeScript/15HttpListenerExample/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/15HttpListenerExample/types/helpers/ItemHelper.d.ts +++ b/TypeScript/15HttpListenerExample/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/15HttpListenerExample/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/15HttpListenerExample/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/15HttpListenerExample/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/15HttpListenerExample/types/loaders/PreAkiModLoader.d.ts b/TypeScript/15HttpListenerExample/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/15HttpListenerExample/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/15HttpListenerExample/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/15HttpListenerExample/types/models/external/HttpFramework.d.ts b/TypeScript/15HttpListenerExample/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/15HttpListenerExample/types/models/external/HttpFramework.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/IItemConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/15HttpListenerExample/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/15HttpListenerExample/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/15HttpListenerExample/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/15HttpListenerExample/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/15HttpListenerExample/types/models/spt/services/LootRequest.d.ts b/TypeScript/15HttpListenerExample/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/15HttpListenerExample/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/15HttpListenerExample/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/15HttpListenerExample/types/routers/EventOutputHolder.d.ts b/TypeScript/15HttpListenerExample/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/15HttpListenerExample/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/15HttpListenerExample/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/15HttpListenerExample/types/routers/HttpRouter.d.ts b/TypeScript/15HttpListenerExample/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/15HttpListenerExample/types/routers/HttpRouter.d.ts +++ b/TypeScript/15HttpListenerExample/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/15HttpListenerExample/types/routers/ImageRouter.d.ts b/TypeScript/15HttpListenerExample/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/15HttpListenerExample/types/routers/ImageRouter.d.ts +++ b/TypeScript/15HttpListenerExample/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/15HttpListenerExample/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/15HttpListenerExample/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/15HttpListenerExample/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/15HttpListenerExample/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/15HttpListenerExample/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/15HttpListenerExample/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/15HttpListenerExample/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/15HttpListenerExample/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/15HttpListenerExample/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/15HttpListenerExample/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/15HttpListenerExample/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/15HttpListenerExample/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/15HttpListenerExample/types/servers/HttpServer.d.ts b/TypeScript/15HttpListenerExample/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/15HttpListenerExample/types/servers/HttpServer.d.ts +++ b/TypeScript/15HttpListenerExample/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/15HttpListenerExample/types/servers/WebSocketServer.d.ts b/TypeScript/15HttpListenerExample/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/15HttpListenerExample/types/servers/WebSocketServer.d.ts +++ b/TypeScript/15HttpListenerExample/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/15HttpListenerExample/types/servers/http/AkiHttpListener.d.ts b/TypeScript/15HttpListenerExample/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/15HttpListenerExample/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/15HttpListenerExample/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/15HttpListenerExample/types/servers/http/IHttpListener.d.ts b/TypeScript/15HttpListenerExample/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/15HttpListenerExample/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/15HttpListenerExample/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/15HttpListenerExample/types/services/ItemFilterService.d.ts b/TypeScript/15HttpListenerExample/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/15HttpListenerExample/types/services/ItemFilterService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/15HttpListenerExample/types/services/ProfileFixerService.d.ts b/TypeScript/15HttpListenerExample/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/15HttpListenerExample/types/services/ProfileFixerService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/15HttpListenerExample/types/services/SeasonalEventService.d.ts b/TypeScript/15HttpListenerExample/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/15HttpListenerExample/types/services/SeasonalEventService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/15HttpListenerExample/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/15HttpListenerExample/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/15HttpListenerExample/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/15HttpListenerExample/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/15HttpListenerExample/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/15HttpListenerExample/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/15HttpListenerExample/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/15HttpListenerExample/types/utils/App.d.ts b/TypeScript/15HttpListenerExample/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/15HttpListenerExample/types/utils/App.d.ts +++ b/TypeScript/15HttpListenerExample/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/15HttpListenerExample/types/utils/HashUtil.d.ts b/TypeScript/15HttpListenerExample/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/15HttpListenerExample/types/utils/HashUtil.d.ts +++ b/TypeScript/15HttpListenerExample/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/15HttpListenerExample/types/utils/HttpFileUtil.d.ts b/TypeScript/15HttpListenerExample/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/15HttpListenerExample/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/15HttpListenerExample/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/15HttpListenerExample/types/utils/VFS.d.ts b/TypeScript/15HttpListenerExample/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/15HttpListenerExample/types/utils/VFS.d.ts +++ b/TypeScript/15HttpListenerExample/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/15HttpListenerExample/types/utils/Watermark.d.ts b/TypeScript/15HttpListenerExample/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/15HttpListenerExample/types/utils/Watermark.d.ts +++ b/TypeScript/15HttpListenerExample/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/15HttpListenerExample/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/15HttpListenerExample/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/15HttpListenerExample/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/15HttpListenerExample/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/16ImporterUtil/README.md b/TypeScript/16ImporterUtil/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/16ImporterUtil/README.md +++ b/TypeScript/16ImporterUtil/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/16ImporterUtil/types/controllers/GameController.d.ts b/TypeScript/16ImporterUtil/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/16ImporterUtil/types/controllers/GameController.d.ts +++ b/TypeScript/16ImporterUtil/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/16ImporterUtil/types/controllers/InraidController.d.ts b/TypeScript/16ImporterUtil/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/16ImporterUtil/types/controllers/InraidController.d.ts +++ b/TypeScript/16ImporterUtil/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/16ImporterUtil/types/controllers/InsuranceController.d.ts b/TypeScript/16ImporterUtil/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/16ImporterUtil/types/controllers/InsuranceController.d.ts +++ b/TypeScript/16ImporterUtil/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/16ImporterUtil/types/controllers/MatchController.d.ts b/TypeScript/16ImporterUtil/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/16ImporterUtil/types/controllers/MatchController.d.ts +++ b/TypeScript/16ImporterUtil/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/16ImporterUtil/types/controllers/RepeatableQuestController.d.ts b/TypeScript/16ImporterUtil/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/16ImporterUtil/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/16ImporterUtil/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/16ImporterUtil/types/di/Serializer.d.ts b/TypeScript/16ImporterUtil/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/16ImporterUtil/types/di/Serializer.d.ts +++ b/TypeScript/16ImporterUtil/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/16ImporterUtil/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/16ImporterUtil/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/16ImporterUtil/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/16ImporterUtil/types/helpers/InRaidHelper.d.ts b/TypeScript/16ImporterUtil/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/16ImporterUtil/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/16ImporterUtil/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/16ImporterUtil/types/helpers/ItemHelper.d.ts b/TypeScript/16ImporterUtil/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/16ImporterUtil/types/helpers/ItemHelper.d.ts +++ b/TypeScript/16ImporterUtil/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/16ImporterUtil/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/16ImporterUtil/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/16ImporterUtil/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/16ImporterUtil/types/loaders/PreAkiModLoader.d.ts b/TypeScript/16ImporterUtil/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/16ImporterUtil/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/16ImporterUtil/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/16ImporterUtil/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/16ImporterUtil/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/16ImporterUtil/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/16ImporterUtil/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/16ImporterUtil/types/models/external/HttpFramework.d.ts b/TypeScript/16ImporterUtil/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/16ImporterUtil/types/models/external/HttpFramework.d.ts +++ b/TypeScript/16ImporterUtil/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/IItemConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/16ImporterUtil/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/16ImporterUtil/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/16ImporterUtil/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/16ImporterUtil/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/16ImporterUtil/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/16ImporterUtil/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/16ImporterUtil/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/16ImporterUtil/types/models/spt/services/LootRequest.d.ts b/TypeScript/16ImporterUtil/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/16ImporterUtil/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/16ImporterUtil/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/16ImporterUtil/types/routers/EventOutputHolder.d.ts b/TypeScript/16ImporterUtil/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/16ImporterUtil/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/16ImporterUtil/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/16ImporterUtil/types/routers/HttpRouter.d.ts b/TypeScript/16ImporterUtil/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/16ImporterUtil/types/routers/HttpRouter.d.ts +++ b/TypeScript/16ImporterUtil/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/16ImporterUtil/types/routers/ImageRouter.d.ts b/TypeScript/16ImporterUtil/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/16ImporterUtil/types/routers/ImageRouter.d.ts +++ b/TypeScript/16ImporterUtil/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/16ImporterUtil/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/16ImporterUtil/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/16ImporterUtil/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/16ImporterUtil/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/16ImporterUtil/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/16ImporterUtil/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/16ImporterUtil/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/16ImporterUtil/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/16ImporterUtil/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/16ImporterUtil/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/16ImporterUtil/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/16ImporterUtil/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/16ImporterUtil/types/servers/HttpServer.d.ts b/TypeScript/16ImporterUtil/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/16ImporterUtil/types/servers/HttpServer.d.ts +++ b/TypeScript/16ImporterUtil/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/16ImporterUtil/types/servers/WebSocketServer.d.ts b/TypeScript/16ImporterUtil/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/16ImporterUtil/types/servers/WebSocketServer.d.ts +++ b/TypeScript/16ImporterUtil/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/16ImporterUtil/types/servers/http/AkiHttpListener.d.ts b/TypeScript/16ImporterUtil/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/16ImporterUtil/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/16ImporterUtil/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/16ImporterUtil/types/servers/http/IHttpListener.d.ts b/TypeScript/16ImporterUtil/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/16ImporterUtil/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/16ImporterUtil/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/16ImporterUtil/types/services/ItemFilterService.d.ts b/TypeScript/16ImporterUtil/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/16ImporterUtil/types/services/ItemFilterService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/16ImporterUtil/types/services/ProfileFixerService.d.ts b/TypeScript/16ImporterUtil/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/16ImporterUtil/types/services/ProfileFixerService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/16ImporterUtil/types/services/SeasonalEventService.d.ts b/TypeScript/16ImporterUtil/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/16ImporterUtil/types/services/SeasonalEventService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/16ImporterUtil/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/16ImporterUtil/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/16ImporterUtil/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/16ImporterUtil/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/16ImporterUtil/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/16ImporterUtil/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/16ImporterUtil/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/16ImporterUtil/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/16ImporterUtil/types/utils/App.d.ts b/TypeScript/16ImporterUtil/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/16ImporterUtil/types/utils/App.d.ts +++ b/TypeScript/16ImporterUtil/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/16ImporterUtil/types/utils/HashUtil.d.ts b/TypeScript/16ImporterUtil/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/16ImporterUtil/types/utils/HashUtil.d.ts +++ b/TypeScript/16ImporterUtil/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/16ImporterUtil/types/utils/HttpFileUtil.d.ts b/TypeScript/16ImporterUtil/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/16ImporterUtil/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/16ImporterUtil/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/16ImporterUtil/types/utils/VFS.d.ts b/TypeScript/16ImporterUtil/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/16ImporterUtil/types/utils/VFS.d.ts +++ b/TypeScript/16ImporterUtil/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/16ImporterUtil/types/utils/Watermark.d.ts b/TypeScript/16ImporterUtil/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/16ImporterUtil/types/utils/Watermark.d.ts +++ b/TypeScript/16ImporterUtil/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/16ImporterUtil/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/16ImporterUtil/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/16ImporterUtil/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/16ImporterUtil/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/17AsyncImporterWithDependency1/README.md b/TypeScript/17AsyncImporterWithDependency1/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/17AsyncImporterWithDependency1/README.md +++ b/TypeScript/17AsyncImporterWithDependency1/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/17AsyncImporterWithDependency1/types/controllers/GameController.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/controllers/GameController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/17AsyncImporterWithDependency1/types/controllers/InraidController.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/controllers/InraidController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/17AsyncImporterWithDependency1/types/controllers/InsuranceController.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/controllers/InsuranceController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/controllers/MatchController.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/controllers/MatchController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/17AsyncImporterWithDependency1/types/controllers/RepeatableQuestController.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/di/Serializer.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/di/Serializer.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency1/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/17AsyncImporterWithDependency1/types/helpers/InRaidHelper.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/17AsyncImporterWithDependency1/types/helpers/ItemHelper.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/helpers/ItemHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/17AsyncImporterWithDependency1/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency1/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/17AsyncImporterWithDependency1/types/loaders/PreAkiModLoader.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/external/HttpFramework.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/external/HttpFramework.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IItemConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/services/LootRequest.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/routers/EventOutputHolder.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/17AsyncImporterWithDependency1/types/routers/HttpRouter.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/routers/HttpRouter.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/routers/ImageRouter.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/routers/ImageRouter.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/17AsyncImporterWithDependency1/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/servers/HttpServer.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/servers/HttpServer.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/servers/WebSocketServer.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/servers/WebSocketServer.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/servers/http/AkiHttpListener.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/servers/http/IHttpListener.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/ItemFilterService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/ItemFilterService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/ProfileFixerService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/ProfileFixerService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/SeasonalEventService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/SeasonalEventService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/utils/App.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/utils/App.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/utils/HashUtil.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/utils/HashUtil.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/utils/HttpFileUtil.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/utils/VFS.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/utils/VFS.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/utils/Watermark.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/utils/Watermark.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/17AsyncImporterWithDependency1/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/17AsyncImporterWithDependency1/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/17AsyncImporterWithDependency1/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/17AsyncImporterWithDependency1/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/17AsyncImporterWithDependency2/README.md b/TypeScript/17AsyncImporterWithDependency2/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/17AsyncImporterWithDependency2/README.md +++ b/TypeScript/17AsyncImporterWithDependency2/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/17AsyncImporterWithDependency2/types/controllers/GameController.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/controllers/GameController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/17AsyncImporterWithDependency2/types/controllers/InraidController.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/controllers/InraidController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/17AsyncImporterWithDependency2/types/controllers/InsuranceController.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/controllers/InsuranceController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/controllers/MatchController.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/controllers/MatchController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/17AsyncImporterWithDependency2/types/controllers/RepeatableQuestController.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/di/Serializer.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/di/Serializer.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency2/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/17AsyncImporterWithDependency2/types/helpers/InRaidHelper.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/17AsyncImporterWithDependency2/types/helpers/ItemHelper.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/helpers/ItemHelper.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/17AsyncImporterWithDependency2/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency2/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/17AsyncImporterWithDependency2/types/loaders/PreAkiModLoader.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/external/HttpFramework.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/external/HttpFramework.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IItemConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/services/LootRequest.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/routers/EventOutputHolder.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/17AsyncImporterWithDependency2/types/routers/HttpRouter.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/routers/HttpRouter.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/routers/ImageRouter.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/routers/ImageRouter.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/17AsyncImporterWithDependency2/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/servers/HttpServer.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/servers/HttpServer.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/servers/WebSocketServer.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/servers/WebSocketServer.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/servers/http/AkiHttpListener.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/servers/http/IHttpListener.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/ItemFilterService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/ItemFilterService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/ProfileFixerService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/ProfileFixerService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/SeasonalEventService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/SeasonalEventService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/utils/App.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/utils/App.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/utils/HashUtil.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/utils/HashUtil.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/utils/HttpFileUtil.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/utils/VFS.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/utils/VFS.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/utils/Watermark.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/utils/Watermark.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/17AsyncImporterWithDependency2/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/17AsyncImporterWithDependency2/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/17AsyncImporterWithDependency2/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/17AsyncImporterWithDependency2/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/18CustomItemService/README.md b/TypeScript/18CustomItemService/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/18CustomItemService/README.md +++ b/TypeScript/18CustomItemService/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/18CustomItemService/types/controllers/GameController.d.ts b/TypeScript/18CustomItemService/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/18CustomItemService/types/controllers/GameController.d.ts +++ b/TypeScript/18CustomItemService/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/18CustomItemService/types/controllers/InraidController.d.ts b/TypeScript/18CustomItemService/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/18CustomItemService/types/controllers/InraidController.d.ts +++ b/TypeScript/18CustomItemService/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/18CustomItemService/types/controllers/InsuranceController.d.ts b/TypeScript/18CustomItemService/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/18CustomItemService/types/controllers/InsuranceController.d.ts +++ b/TypeScript/18CustomItemService/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/18CustomItemService/types/controllers/MatchController.d.ts b/TypeScript/18CustomItemService/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/18CustomItemService/types/controllers/MatchController.d.ts +++ b/TypeScript/18CustomItemService/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/18CustomItemService/types/controllers/RepeatableQuestController.d.ts b/TypeScript/18CustomItemService/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/18CustomItemService/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/18CustomItemService/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/18CustomItemService/types/di/Serializer.d.ts b/TypeScript/18CustomItemService/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/18CustomItemService/types/di/Serializer.d.ts +++ b/TypeScript/18CustomItemService/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/18CustomItemService/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/18CustomItemService/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/18CustomItemService/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/18CustomItemService/types/helpers/InRaidHelper.d.ts b/TypeScript/18CustomItemService/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/18CustomItemService/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/18CustomItemService/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/18CustomItemService/types/helpers/ItemHelper.d.ts b/TypeScript/18CustomItemService/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/18CustomItemService/types/helpers/ItemHelper.d.ts +++ b/TypeScript/18CustomItemService/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/18CustomItemService/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/18CustomItemService/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/18CustomItemService/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/18CustomItemService/types/loaders/PreAkiModLoader.d.ts b/TypeScript/18CustomItemService/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/18CustomItemService/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/18CustomItemService/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/18CustomItemService/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/18CustomItemService/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/18CustomItemService/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/18CustomItemService/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/18CustomItemService/types/models/external/HttpFramework.d.ts b/TypeScript/18CustomItemService/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/18CustomItemService/types/models/external/HttpFramework.d.ts +++ b/TypeScript/18CustomItemService/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/18CustomItemService/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/18CustomItemService/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/18CustomItemService/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/18CustomItemService/types/models/spt/config/IItemConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/18CustomItemService/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/18CustomItemService/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/18CustomItemService/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/18CustomItemService/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/18CustomItemService/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/18CustomItemService/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/18CustomItemService/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/18CustomItemService/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/18CustomItemService/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/18CustomItemService/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/18CustomItemService/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/18CustomItemService/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/18CustomItemService/types/models/spt/services/LootRequest.d.ts b/TypeScript/18CustomItemService/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/18CustomItemService/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/18CustomItemService/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/18CustomItemService/types/routers/EventOutputHolder.d.ts b/TypeScript/18CustomItemService/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/18CustomItemService/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/18CustomItemService/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/18CustomItemService/types/routers/HttpRouter.d.ts b/TypeScript/18CustomItemService/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/18CustomItemService/types/routers/HttpRouter.d.ts +++ b/TypeScript/18CustomItemService/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/18CustomItemService/types/routers/ImageRouter.d.ts b/TypeScript/18CustomItemService/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/18CustomItemService/types/routers/ImageRouter.d.ts +++ b/TypeScript/18CustomItemService/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/18CustomItemService/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/18CustomItemService/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/18CustomItemService/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/18CustomItemService/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/18CustomItemService/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/18CustomItemService/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/18CustomItemService/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/18CustomItemService/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/18CustomItemService/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/18CustomItemService/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/18CustomItemService/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/18CustomItemService/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/18CustomItemService/types/servers/HttpServer.d.ts b/TypeScript/18CustomItemService/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/18CustomItemService/types/servers/HttpServer.d.ts +++ b/TypeScript/18CustomItemService/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/18CustomItemService/types/servers/WebSocketServer.d.ts b/TypeScript/18CustomItemService/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/18CustomItemService/types/servers/WebSocketServer.d.ts +++ b/TypeScript/18CustomItemService/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/18CustomItemService/types/servers/http/AkiHttpListener.d.ts b/TypeScript/18CustomItemService/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/18CustomItemService/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/18CustomItemService/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/18CustomItemService/types/servers/http/IHttpListener.d.ts b/TypeScript/18CustomItemService/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/18CustomItemService/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/18CustomItemService/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/18CustomItemService/types/services/ItemFilterService.d.ts b/TypeScript/18CustomItemService/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/18CustomItemService/types/services/ItemFilterService.d.ts +++ b/TypeScript/18CustomItemService/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/18CustomItemService/types/services/ProfileFixerService.d.ts b/TypeScript/18CustomItemService/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/18CustomItemService/types/services/ProfileFixerService.d.ts +++ b/TypeScript/18CustomItemService/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/18CustomItemService/types/services/SeasonalEventService.d.ts b/TypeScript/18CustomItemService/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/18CustomItemService/types/services/SeasonalEventService.d.ts +++ b/TypeScript/18CustomItemService/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/18CustomItemService/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/18CustomItemService/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/18CustomItemService/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/18CustomItemService/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/18CustomItemService/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/18CustomItemService/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/18CustomItemService/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/18CustomItemService/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/18CustomItemService/types/utils/App.d.ts b/TypeScript/18CustomItemService/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/18CustomItemService/types/utils/App.d.ts +++ b/TypeScript/18CustomItemService/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/18CustomItemService/types/utils/HashUtil.d.ts b/TypeScript/18CustomItemService/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/18CustomItemService/types/utils/HashUtil.d.ts +++ b/TypeScript/18CustomItemService/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/18CustomItemService/types/utils/HttpFileUtil.d.ts b/TypeScript/18CustomItemService/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/18CustomItemService/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/18CustomItemService/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/18CustomItemService/types/utils/VFS.d.ts b/TypeScript/18CustomItemService/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/18CustomItemService/types/utils/VFS.d.ts +++ b/TypeScript/18CustomItemService/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/18CustomItemService/types/utils/Watermark.d.ts b/TypeScript/18CustomItemService/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/18CustomItemService/types/utils/Watermark.d.ts +++ b/TypeScript/18CustomItemService/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/18CustomItemService/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/18CustomItemService/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/18CustomItemService/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/18CustomItemService/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/19UseExternalLibraries/README.md b/TypeScript/19UseExternalLibraries/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/19UseExternalLibraries/README.md +++ b/TypeScript/19UseExternalLibraries/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/19UseExternalLibraries/types/controllers/GameController.d.ts b/TypeScript/19UseExternalLibraries/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/19UseExternalLibraries/types/controllers/GameController.d.ts +++ b/TypeScript/19UseExternalLibraries/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/19UseExternalLibraries/types/controllers/InraidController.d.ts b/TypeScript/19UseExternalLibraries/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/19UseExternalLibraries/types/controllers/InraidController.d.ts +++ b/TypeScript/19UseExternalLibraries/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/19UseExternalLibraries/types/controllers/InsuranceController.d.ts b/TypeScript/19UseExternalLibraries/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/19UseExternalLibraries/types/controllers/InsuranceController.d.ts +++ b/TypeScript/19UseExternalLibraries/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/19UseExternalLibraries/types/controllers/MatchController.d.ts b/TypeScript/19UseExternalLibraries/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/19UseExternalLibraries/types/controllers/MatchController.d.ts +++ b/TypeScript/19UseExternalLibraries/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/19UseExternalLibraries/types/controllers/RepeatableQuestController.d.ts b/TypeScript/19UseExternalLibraries/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/19UseExternalLibraries/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/19UseExternalLibraries/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/19UseExternalLibraries/types/di/Serializer.d.ts b/TypeScript/19UseExternalLibraries/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/19UseExternalLibraries/types/di/Serializer.d.ts +++ b/TypeScript/19UseExternalLibraries/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/19UseExternalLibraries/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/19UseExternalLibraries/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/19UseExternalLibraries/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/19UseExternalLibraries/types/helpers/InRaidHelper.d.ts b/TypeScript/19UseExternalLibraries/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/19UseExternalLibraries/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/19UseExternalLibraries/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/19UseExternalLibraries/types/helpers/ItemHelper.d.ts b/TypeScript/19UseExternalLibraries/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/19UseExternalLibraries/types/helpers/ItemHelper.d.ts +++ b/TypeScript/19UseExternalLibraries/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/19UseExternalLibraries/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/19UseExternalLibraries/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/19UseExternalLibraries/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/19UseExternalLibraries/types/loaders/PreAkiModLoader.d.ts b/TypeScript/19UseExternalLibraries/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/19UseExternalLibraries/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/19UseExternalLibraries/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/19UseExternalLibraries/types/models/external/HttpFramework.d.ts b/TypeScript/19UseExternalLibraries/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/19UseExternalLibraries/types/models/external/HttpFramework.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/IItemConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/19UseExternalLibraries/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/19UseExternalLibraries/types/models/spt/services/LootRequest.d.ts b/TypeScript/19UseExternalLibraries/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/19UseExternalLibraries/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/19UseExternalLibraries/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/19UseExternalLibraries/types/routers/EventOutputHolder.d.ts b/TypeScript/19UseExternalLibraries/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/19UseExternalLibraries/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/19UseExternalLibraries/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/19UseExternalLibraries/types/routers/HttpRouter.d.ts b/TypeScript/19UseExternalLibraries/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/19UseExternalLibraries/types/routers/HttpRouter.d.ts +++ b/TypeScript/19UseExternalLibraries/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/19UseExternalLibraries/types/routers/ImageRouter.d.ts b/TypeScript/19UseExternalLibraries/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/19UseExternalLibraries/types/routers/ImageRouter.d.ts +++ b/TypeScript/19UseExternalLibraries/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/19UseExternalLibraries/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/19UseExternalLibraries/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/19UseExternalLibraries/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/19UseExternalLibraries/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/19UseExternalLibraries/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/19UseExternalLibraries/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/19UseExternalLibraries/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/19UseExternalLibraries/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/19UseExternalLibraries/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/19UseExternalLibraries/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/19UseExternalLibraries/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/19UseExternalLibraries/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/19UseExternalLibraries/types/servers/HttpServer.d.ts b/TypeScript/19UseExternalLibraries/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/19UseExternalLibraries/types/servers/HttpServer.d.ts +++ b/TypeScript/19UseExternalLibraries/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/19UseExternalLibraries/types/servers/WebSocketServer.d.ts b/TypeScript/19UseExternalLibraries/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/19UseExternalLibraries/types/servers/WebSocketServer.d.ts +++ b/TypeScript/19UseExternalLibraries/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/19UseExternalLibraries/types/servers/http/AkiHttpListener.d.ts b/TypeScript/19UseExternalLibraries/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/19UseExternalLibraries/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/19UseExternalLibraries/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/19UseExternalLibraries/types/servers/http/IHttpListener.d.ts b/TypeScript/19UseExternalLibraries/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/19UseExternalLibraries/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/19UseExternalLibraries/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/19UseExternalLibraries/types/services/ItemFilterService.d.ts b/TypeScript/19UseExternalLibraries/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/19UseExternalLibraries/types/services/ItemFilterService.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/19UseExternalLibraries/types/services/ProfileFixerService.d.ts b/TypeScript/19UseExternalLibraries/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/19UseExternalLibraries/types/services/ProfileFixerService.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/19UseExternalLibraries/types/services/SeasonalEventService.d.ts b/TypeScript/19UseExternalLibraries/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/19UseExternalLibraries/types/services/SeasonalEventService.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/19UseExternalLibraries/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/19UseExternalLibraries/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/19UseExternalLibraries/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/19UseExternalLibraries/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/19UseExternalLibraries/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/19UseExternalLibraries/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/19UseExternalLibraries/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/19UseExternalLibraries/types/utils/App.d.ts b/TypeScript/19UseExternalLibraries/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/19UseExternalLibraries/types/utils/App.d.ts +++ b/TypeScript/19UseExternalLibraries/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/19UseExternalLibraries/types/utils/HashUtil.d.ts b/TypeScript/19UseExternalLibraries/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/19UseExternalLibraries/types/utils/HashUtil.d.ts +++ b/TypeScript/19UseExternalLibraries/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/19UseExternalLibraries/types/utils/HttpFileUtil.d.ts b/TypeScript/19UseExternalLibraries/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/19UseExternalLibraries/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/19UseExternalLibraries/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/19UseExternalLibraries/types/utils/VFS.d.ts b/TypeScript/19UseExternalLibraries/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/19UseExternalLibraries/types/utils/VFS.d.ts +++ b/TypeScript/19UseExternalLibraries/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/19UseExternalLibraries/types/utils/Watermark.d.ts b/TypeScript/19UseExternalLibraries/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/19UseExternalLibraries/types/utils/Watermark.d.ts +++ b/TypeScript/19UseExternalLibraries/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/19UseExternalLibraries/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/19UseExternalLibraries/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/19UseExternalLibraries/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/19UseExternalLibraries/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/1LogToConsole/README.md b/TypeScript/1LogToConsole/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/1LogToConsole/README.md +++ b/TypeScript/1LogToConsole/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/1LogToConsole/types/controllers/GameController.d.ts b/TypeScript/1LogToConsole/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/1LogToConsole/types/controllers/GameController.d.ts +++ b/TypeScript/1LogToConsole/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/1LogToConsole/types/controllers/InraidController.d.ts b/TypeScript/1LogToConsole/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/1LogToConsole/types/controllers/InraidController.d.ts +++ b/TypeScript/1LogToConsole/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/1LogToConsole/types/controllers/InsuranceController.d.ts b/TypeScript/1LogToConsole/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/1LogToConsole/types/controllers/InsuranceController.d.ts +++ b/TypeScript/1LogToConsole/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/1LogToConsole/types/controllers/MatchController.d.ts b/TypeScript/1LogToConsole/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/1LogToConsole/types/controllers/MatchController.d.ts +++ b/TypeScript/1LogToConsole/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/1LogToConsole/types/controllers/RepeatableQuestController.d.ts b/TypeScript/1LogToConsole/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/1LogToConsole/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/1LogToConsole/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/1LogToConsole/types/di/Serializer.d.ts b/TypeScript/1LogToConsole/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/1LogToConsole/types/di/Serializer.d.ts +++ b/TypeScript/1LogToConsole/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/1LogToConsole/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/1LogToConsole/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/1LogToConsole/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/1LogToConsole/types/helpers/InRaidHelper.d.ts b/TypeScript/1LogToConsole/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/1LogToConsole/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/1LogToConsole/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/1LogToConsole/types/helpers/ItemHelper.d.ts b/TypeScript/1LogToConsole/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/1LogToConsole/types/helpers/ItemHelper.d.ts +++ b/TypeScript/1LogToConsole/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/1LogToConsole/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/1LogToConsole/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/1LogToConsole/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/1LogToConsole/types/loaders/PreAkiModLoader.d.ts b/TypeScript/1LogToConsole/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/1LogToConsole/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/1LogToConsole/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/1LogToConsole/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/1LogToConsole/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/1LogToConsole/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/1LogToConsole/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/1LogToConsole/types/models/external/HttpFramework.d.ts b/TypeScript/1LogToConsole/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/1LogToConsole/types/models/external/HttpFramework.d.ts +++ b/TypeScript/1LogToConsole/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/1LogToConsole/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/1LogToConsole/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/1LogToConsole/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/1LogToConsole/types/models/spt/config/IItemConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/1LogToConsole/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/1LogToConsole/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/1LogToConsole/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/1LogToConsole/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/1LogToConsole/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/1LogToConsole/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/1LogToConsole/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/1LogToConsole/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/1LogToConsole/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/1LogToConsole/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/1LogToConsole/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/1LogToConsole/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/1LogToConsole/types/models/spt/services/LootRequest.d.ts b/TypeScript/1LogToConsole/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/1LogToConsole/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/1LogToConsole/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/1LogToConsole/types/routers/EventOutputHolder.d.ts b/TypeScript/1LogToConsole/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/1LogToConsole/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/1LogToConsole/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/1LogToConsole/types/routers/HttpRouter.d.ts b/TypeScript/1LogToConsole/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/1LogToConsole/types/routers/HttpRouter.d.ts +++ b/TypeScript/1LogToConsole/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/1LogToConsole/types/routers/ImageRouter.d.ts b/TypeScript/1LogToConsole/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/1LogToConsole/types/routers/ImageRouter.d.ts +++ b/TypeScript/1LogToConsole/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/1LogToConsole/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/1LogToConsole/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/1LogToConsole/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/1LogToConsole/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/1LogToConsole/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/1LogToConsole/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/1LogToConsole/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/1LogToConsole/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/1LogToConsole/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/1LogToConsole/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/1LogToConsole/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/1LogToConsole/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/1LogToConsole/types/servers/HttpServer.d.ts b/TypeScript/1LogToConsole/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/1LogToConsole/types/servers/HttpServer.d.ts +++ b/TypeScript/1LogToConsole/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/1LogToConsole/types/servers/WebSocketServer.d.ts b/TypeScript/1LogToConsole/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/1LogToConsole/types/servers/WebSocketServer.d.ts +++ b/TypeScript/1LogToConsole/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/1LogToConsole/types/servers/http/AkiHttpListener.d.ts b/TypeScript/1LogToConsole/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/1LogToConsole/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/1LogToConsole/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/1LogToConsole/types/servers/http/IHttpListener.d.ts b/TypeScript/1LogToConsole/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/1LogToConsole/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/1LogToConsole/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/1LogToConsole/types/services/ItemFilterService.d.ts b/TypeScript/1LogToConsole/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/1LogToConsole/types/services/ItemFilterService.d.ts +++ b/TypeScript/1LogToConsole/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/1LogToConsole/types/services/ProfileFixerService.d.ts b/TypeScript/1LogToConsole/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/1LogToConsole/types/services/ProfileFixerService.d.ts +++ b/TypeScript/1LogToConsole/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/1LogToConsole/types/services/SeasonalEventService.d.ts b/TypeScript/1LogToConsole/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/1LogToConsole/types/services/SeasonalEventService.d.ts +++ b/TypeScript/1LogToConsole/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/1LogToConsole/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/1LogToConsole/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/1LogToConsole/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/1LogToConsole/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/1LogToConsole/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/1LogToConsole/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/1LogToConsole/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/1LogToConsole/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/1LogToConsole/types/utils/App.d.ts b/TypeScript/1LogToConsole/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/1LogToConsole/types/utils/App.d.ts +++ b/TypeScript/1LogToConsole/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/1LogToConsole/types/utils/HashUtil.d.ts b/TypeScript/1LogToConsole/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/1LogToConsole/types/utils/HashUtil.d.ts +++ b/TypeScript/1LogToConsole/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/1LogToConsole/types/utils/HttpFileUtil.d.ts b/TypeScript/1LogToConsole/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/1LogToConsole/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/1LogToConsole/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/1LogToConsole/types/utils/VFS.d.ts b/TypeScript/1LogToConsole/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/1LogToConsole/types/utils/VFS.d.ts +++ b/TypeScript/1LogToConsole/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/1LogToConsole/types/utils/Watermark.d.ts b/TypeScript/1LogToConsole/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/1LogToConsole/types/utils/Watermark.d.ts +++ b/TypeScript/1LogToConsole/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/1LogToConsole/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/1LogToConsole/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/1LogToConsole/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/1LogToConsole/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/2EditDatabase/README.md b/TypeScript/2EditDatabase/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/2EditDatabase/README.md +++ b/TypeScript/2EditDatabase/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/2EditDatabase/types/controllers/GameController.d.ts b/TypeScript/2EditDatabase/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/2EditDatabase/types/controllers/GameController.d.ts +++ b/TypeScript/2EditDatabase/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/2EditDatabase/types/controllers/InraidController.d.ts b/TypeScript/2EditDatabase/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/2EditDatabase/types/controllers/InraidController.d.ts +++ b/TypeScript/2EditDatabase/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/2EditDatabase/types/controllers/InsuranceController.d.ts b/TypeScript/2EditDatabase/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/2EditDatabase/types/controllers/InsuranceController.d.ts +++ b/TypeScript/2EditDatabase/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/2EditDatabase/types/controllers/MatchController.d.ts b/TypeScript/2EditDatabase/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/2EditDatabase/types/controllers/MatchController.d.ts +++ b/TypeScript/2EditDatabase/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/2EditDatabase/types/controllers/RepeatableQuestController.d.ts b/TypeScript/2EditDatabase/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/2EditDatabase/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/2EditDatabase/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/2EditDatabase/types/di/Serializer.d.ts b/TypeScript/2EditDatabase/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/2EditDatabase/types/di/Serializer.d.ts +++ b/TypeScript/2EditDatabase/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/2EditDatabase/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/2EditDatabase/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/2EditDatabase/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/2EditDatabase/types/helpers/InRaidHelper.d.ts b/TypeScript/2EditDatabase/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/2EditDatabase/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/2EditDatabase/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/2EditDatabase/types/helpers/ItemHelper.d.ts b/TypeScript/2EditDatabase/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/2EditDatabase/types/helpers/ItemHelper.d.ts +++ b/TypeScript/2EditDatabase/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/2EditDatabase/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/2EditDatabase/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/2EditDatabase/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/2EditDatabase/types/loaders/PreAkiModLoader.d.ts b/TypeScript/2EditDatabase/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/2EditDatabase/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/2EditDatabase/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/2EditDatabase/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/2EditDatabase/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/2EditDatabase/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/2EditDatabase/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/2EditDatabase/types/models/external/HttpFramework.d.ts b/TypeScript/2EditDatabase/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/2EditDatabase/types/models/external/HttpFramework.d.ts +++ b/TypeScript/2EditDatabase/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/2EditDatabase/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/2EditDatabase/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/2EditDatabase/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/2EditDatabase/types/models/spt/config/IItemConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/2EditDatabase/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/2EditDatabase/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/2EditDatabase/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/2EditDatabase/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/2EditDatabase/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/2EditDatabase/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/2EditDatabase/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/2EditDatabase/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/2EditDatabase/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/2EditDatabase/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/2EditDatabase/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/2EditDatabase/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/2EditDatabase/types/models/spt/services/LootRequest.d.ts b/TypeScript/2EditDatabase/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/2EditDatabase/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/2EditDatabase/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/2EditDatabase/types/routers/EventOutputHolder.d.ts b/TypeScript/2EditDatabase/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/2EditDatabase/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/2EditDatabase/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/2EditDatabase/types/routers/HttpRouter.d.ts b/TypeScript/2EditDatabase/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/2EditDatabase/types/routers/HttpRouter.d.ts +++ b/TypeScript/2EditDatabase/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/2EditDatabase/types/routers/ImageRouter.d.ts b/TypeScript/2EditDatabase/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/2EditDatabase/types/routers/ImageRouter.d.ts +++ b/TypeScript/2EditDatabase/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/2EditDatabase/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/2EditDatabase/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/2EditDatabase/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/2EditDatabase/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/2EditDatabase/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/2EditDatabase/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/2EditDatabase/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/2EditDatabase/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/2EditDatabase/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/2EditDatabase/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/2EditDatabase/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/2EditDatabase/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/2EditDatabase/types/servers/HttpServer.d.ts b/TypeScript/2EditDatabase/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/2EditDatabase/types/servers/HttpServer.d.ts +++ b/TypeScript/2EditDatabase/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/2EditDatabase/types/servers/WebSocketServer.d.ts b/TypeScript/2EditDatabase/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/2EditDatabase/types/servers/WebSocketServer.d.ts +++ b/TypeScript/2EditDatabase/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/2EditDatabase/types/servers/http/AkiHttpListener.d.ts b/TypeScript/2EditDatabase/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/2EditDatabase/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/2EditDatabase/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/2EditDatabase/types/servers/http/IHttpListener.d.ts b/TypeScript/2EditDatabase/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/2EditDatabase/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/2EditDatabase/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/2EditDatabase/types/services/ItemFilterService.d.ts b/TypeScript/2EditDatabase/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/2EditDatabase/types/services/ItemFilterService.d.ts +++ b/TypeScript/2EditDatabase/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/2EditDatabase/types/services/ProfileFixerService.d.ts b/TypeScript/2EditDatabase/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/2EditDatabase/types/services/ProfileFixerService.d.ts +++ b/TypeScript/2EditDatabase/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/2EditDatabase/types/services/SeasonalEventService.d.ts b/TypeScript/2EditDatabase/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/2EditDatabase/types/services/SeasonalEventService.d.ts +++ b/TypeScript/2EditDatabase/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/2EditDatabase/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/2EditDatabase/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/2EditDatabase/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/2EditDatabase/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/2EditDatabase/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/2EditDatabase/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/2EditDatabase/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/2EditDatabase/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/2EditDatabase/types/utils/App.d.ts b/TypeScript/2EditDatabase/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/2EditDatabase/types/utils/App.d.ts +++ b/TypeScript/2EditDatabase/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/2EditDatabase/types/utils/HashUtil.d.ts b/TypeScript/2EditDatabase/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/2EditDatabase/types/utils/HashUtil.d.ts +++ b/TypeScript/2EditDatabase/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/2EditDatabase/types/utils/HttpFileUtil.d.ts b/TypeScript/2EditDatabase/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/2EditDatabase/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/2EditDatabase/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/2EditDatabase/types/utils/VFS.d.ts b/TypeScript/2EditDatabase/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/2EditDatabase/types/utils/VFS.d.ts +++ b/TypeScript/2EditDatabase/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/2EditDatabase/types/utils/Watermark.d.ts b/TypeScript/2EditDatabase/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/2EditDatabase/types/utils/Watermark.d.ts +++ b/TypeScript/2EditDatabase/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/2EditDatabase/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/2EditDatabase/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/2EditDatabase/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/2EditDatabase/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/3GetSptConfigFile/README.md b/TypeScript/3GetSptConfigFile/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/3GetSptConfigFile/README.md +++ b/TypeScript/3GetSptConfigFile/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/3GetSptConfigFile/types/controllers/GameController.d.ts b/TypeScript/3GetSptConfigFile/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/3GetSptConfigFile/types/controllers/GameController.d.ts +++ b/TypeScript/3GetSptConfigFile/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/3GetSptConfigFile/types/controllers/InraidController.d.ts b/TypeScript/3GetSptConfigFile/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/3GetSptConfigFile/types/controllers/InraidController.d.ts +++ b/TypeScript/3GetSptConfigFile/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/3GetSptConfigFile/types/controllers/InsuranceController.d.ts b/TypeScript/3GetSptConfigFile/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/3GetSptConfigFile/types/controllers/InsuranceController.d.ts +++ b/TypeScript/3GetSptConfigFile/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/3GetSptConfigFile/types/controllers/MatchController.d.ts b/TypeScript/3GetSptConfigFile/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/3GetSptConfigFile/types/controllers/MatchController.d.ts +++ b/TypeScript/3GetSptConfigFile/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/3GetSptConfigFile/types/controllers/RepeatableQuestController.d.ts b/TypeScript/3GetSptConfigFile/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/3GetSptConfigFile/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/3GetSptConfigFile/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/3GetSptConfigFile/types/di/Serializer.d.ts b/TypeScript/3GetSptConfigFile/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/3GetSptConfigFile/types/di/Serializer.d.ts +++ b/TypeScript/3GetSptConfigFile/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/3GetSptConfigFile/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/3GetSptConfigFile/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/3GetSptConfigFile/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/3GetSptConfigFile/types/helpers/InRaidHelper.d.ts b/TypeScript/3GetSptConfigFile/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/3GetSptConfigFile/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/3GetSptConfigFile/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/3GetSptConfigFile/types/helpers/ItemHelper.d.ts b/TypeScript/3GetSptConfigFile/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/3GetSptConfigFile/types/helpers/ItemHelper.d.ts +++ b/TypeScript/3GetSptConfigFile/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/3GetSptConfigFile/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/3GetSptConfigFile/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/3GetSptConfigFile/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/3GetSptConfigFile/types/loaders/PreAkiModLoader.d.ts b/TypeScript/3GetSptConfigFile/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/3GetSptConfigFile/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/3GetSptConfigFile/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/3GetSptConfigFile/types/models/external/HttpFramework.d.ts b/TypeScript/3GetSptConfigFile/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/3GetSptConfigFile/types/models/external/HttpFramework.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/IItemConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/3GetSptConfigFile/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/3GetSptConfigFile/types/models/spt/services/LootRequest.d.ts b/TypeScript/3GetSptConfigFile/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/3GetSptConfigFile/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/3GetSptConfigFile/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/3GetSptConfigFile/types/routers/EventOutputHolder.d.ts b/TypeScript/3GetSptConfigFile/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/3GetSptConfigFile/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/3GetSptConfigFile/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/3GetSptConfigFile/types/routers/HttpRouter.d.ts b/TypeScript/3GetSptConfigFile/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/3GetSptConfigFile/types/routers/HttpRouter.d.ts +++ b/TypeScript/3GetSptConfigFile/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/3GetSptConfigFile/types/routers/ImageRouter.d.ts b/TypeScript/3GetSptConfigFile/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/3GetSptConfigFile/types/routers/ImageRouter.d.ts +++ b/TypeScript/3GetSptConfigFile/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/3GetSptConfigFile/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/3GetSptConfigFile/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/3GetSptConfigFile/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/3GetSptConfigFile/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/3GetSptConfigFile/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/3GetSptConfigFile/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/3GetSptConfigFile/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/3GetSptConfigFile/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/3GetSptConfigFile/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/3GetSptConfigFile/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/3GetSptConfigFile/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/3GetSptConfigFile/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/3GetSptConfigFile/types/servers/HttpServer.d.ts b/TypeScript/3GetSptConfigFile/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/3GetSptConfigFile/types/servers/HttpServer.d.ts +++ b/TypeScript/3GetSptConfigFile/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/3GetSptConfigFile/types/servers/WebSocketServer.d.ts b/TypeScript/3GetSptConfigFile/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/3GetSptConfigFile/types/servers/WebSocketServer.d.ts +++ b/TypeScript/3GetSptConfigFile/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/3GetSptConfigFile/types/servers/http/AkiHttpListener.d.ts b/TypeScript/3GetSptConfigFile/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/3GetSptConfigFile/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/3GetSptConfigFile/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/3GetSptConfigFile/types/servers/http/IHttpListener.d.ts b/TypeScript/3GetSptConfigFile/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/3GetSptConfigFile/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/3GetSptConfigFile/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/3GetSptConfigFile/types/services/ItemFilterService.d.ts b/TypeScript/3GetSptConfigFile/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/3GetSptConfigFile/types/services/ItemFilterService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/3GetSptConfigFile/types/services/ProfileFixerService.d.ts b/TypeScript/3GetSptConfigFile/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/3GetSptConfigFile/types/services/ProfileFixerService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/3GetSptConfigFile/types/services/SeasonalEventService.d.ts b/TypeScript/3GetSptConfigFile/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/3GetSptConfigFile/types/services/SeasonalEventService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/3GetSptConfigFile/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/3GetSptConfigFile/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/3GetSptConfigFile/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/3GetSptConfigFile/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/3GetSptConfigFile/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/3GetSptConfigFile/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/3GetSptConfigFile/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/3GetSptConfigFile/types/utils/App.d.ts b/TypeScript/3GetSptConfigFile/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/3GetSptConfigFile/types/utils/App.d.ts +++ b/TypeScript/3GetSptConfigFile/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/3GetSptConfigFile/types/utils/HashUtil.d.ts b/TypeScript/3GetSptConfigFile/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/3GetSptConfigFile/types/utils/HashUtil.d.ts +++ b/TypeScript/3GetSptConfigFile/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/3GetSptConfigFile/types/utils/HttpFileUtil.d.ts b/TypeScript/3GetSptConfigFile/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/3GetSptConfigFile/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/3GetSptConfigFile/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/3GetSptConfigFile/types/utils/VFS.d.ts b/TypeScript/3GetSptConfigFile/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/3GetSptConfigFile/types/utils/VFS.d.ts +++ b/TypeScript/3GetSptConfigFile/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/3GetSptConfigFile/types/utils/Watermark.d.ts b/TypeScript/3GetSptConfigFile/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/3GetSptConfigFile/types/utils/Watermark.d.ts +++ b/TypeScript/3GetSptConfigFile/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/3GetSptConfigFile/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/3GetSptConfigFile/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/3GetSptConfigFile/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/3GetSptConfigFile/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/README.md b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/README.md +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/GameController.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/GameController.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/InraidController.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/InraidController.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/InsuranceController.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/InsuranceController.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/MatchController.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/MatchController.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/RepeatableQuestController.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/di/Serializer.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/di/Serializer.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/InRaidHelper.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/ItemHelper.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/ItemHelper.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/loaders/PreAkiModLoader.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/external/HttpFramework.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/external/HttpFramework.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IItemConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/services/LootRequest.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/EventOutputHolder.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/HttpRouter.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/HttpRouter.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/ImageRouter.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/ImageRouter.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/HttpServer.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/HttpServer.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/WebSocketServer.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/WebSocketServer.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/http/AkiHttpListener.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/http/IHttpListener.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ItemFilterService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ItemFilterService.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ProfileFixerService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ProfileFixerService.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/SeasonalEventService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/SeasonalEventService.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/App.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/App.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/HashUtil.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/HashUtil.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/HttpFileUtil.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/VFS.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/VFS.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/Watermark.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/Watermark.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/4.1UseACustomJson5OrJsonCConfigFile/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/4UseACustomConfigFile/README.md b/TypeScript/4UseACustomConfigFile/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/4UseACustomConfigFile/README.md +++ b/TypeScript/4UseACustomConfigFile/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/4UseACustomConfigFile/types/controllers/GameController.d.ts b/TypeScript/4UseACustomConfigFile/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/4UseACustomConfigFile/types/controllers/GameController.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/4UseACustomConfigFile/types/controllers/InraidController.d.ts b/TypeScript/4UseACustomConfigFile/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/4UseACustomConfigFile/types/controllers/InraidController.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/4UseACustomConfigFile/types/controllers/InsuranceController.d.ts b/TypeScript/4UseACustomConfigFile/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/4UseACustomConfigFile/types/controllers/InsuranceController.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/4UseACustomConfigFile/types/controllers/MatchController.d.ts b/TypeScript/4UseACustomConfigFile/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/4UseACustomConfigFile/types/controllers/MatchController.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/4UseACustomConfigFile/types/controllers/RepeatableQuestController.d.ts b/TypeScript/4UseACustomConfigFile/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/4UseACustomConfigFile/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/4UseACustomConfigFile/types/di/Serializer.d.ts b/TypeScript/4UseACustomConfigFile/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/4UseACustomConfigFile/types/di/Serializer.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/4UseACustomConfigFile/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/4UseACustomConfigFile/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/4UseACustomConfigFile/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/4UseACustomConfigFile/types/helpers/InRaidHelper.d.ts b/TypeScript/4UseACustomConfigFile/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/4UseACustomConfigFile/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/4UseACustomConfigFile/types/helpers/ItemHelper.d.ts b/TypeScript/4UseACustomConfigFile/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/4UseACustomConfigFile/types/helpers/ItemHelper.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/4UseACustomConfigFile/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/4UseACustomConfigFile/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/4UseACustomConfigFile/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/4UseACustomConfigFile/types/loaders/PreAkiModLoader.d.ts b/TypeScript/4UseACustomConfigFile/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/4UseACustomConfigFile/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/4UseACustomConfigFile/types/models/external/HttpFramework.d.ts b/TypeScript/4UseACustomConfigFile/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/external/HttpFramework.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IItemConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/4UseACustomConfigFile/types/models/spt/services/LootRequest.d.ts b/TypeScript/4UseACustomConfigFile/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/4UseACustomConfigFile/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/4UseACustomConfigFile/types/routers/EventOutputHolder.d.ts b/TypeScript/4UseACustomConfigFile/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/4UseACustomConfigFile/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/4UseACustomConfigFile/types/routers/HttpRouter.d.ts b/TypeScript/4UseACustomConfigFile/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/4UseACustomConfigFile/types/routers/HttpRouter.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/4UseACustomConfigFile/types/routers/ImageRouter.d.ts b/TypeScript/4UseACustomConfigFile/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/4UseACustomConfigFile/types/routers/ImageRouter.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/4UseACustomConfigFile/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/4UseACustomConfigFile/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/4UseACustomConfigFile/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/4UseACustomConfigFile/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/4UseACustomConfigFile/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/4UseACustomConfigFile/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/4UseACustomConfigFile/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/4UseACustomConfigFile/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/4UseACustomConfigFile/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/4UseACustomConfigFile/types/servers/HttpServer.d.ts b/TypeScript/4UseACustomConfigFile/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/4UseACustomConfigFile/types/servers/HttpServer.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/4UseACustomConfigFile/types/servers/WebSocketServer.d.ts b/TypeScript/4UseACustomConfigFile/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/4UseACustomConfigFile/types/servers/WebSocketServer.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/4UseACustomConfigFile/types/servers/http/AkiHttpListener.d.ts b/TypeScript/4UseACustomConfigFile/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/4UseACustomConfigFile/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/4UseACustomConfigFile/types/servers/http/IHttpListener.d.ts b/TypeScript/4UseACustomConfigFile/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/4UseACustomConfigFile/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/4UseACustomConfigFile/types/services/ItemFilterService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/ItemFilterService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/4UseACustomConfigFile/types/services/ProfileFixerService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/ProfileFixerService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/4UseACustomConfigFile/types/services/SeasonalEventService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/SeasonalEventService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/4UseACustomConfigFile/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/4UseACustomConfigFile/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/4UseACustomConfigFile/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/4UseACustomConfigFile/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/4UseACustomConfigFile/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/4UseACustomConfigFile/types/utils/App.d.ts b/TypeScript/4UseACustomConfigFile/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/4UseACustomConfigFile/types/utils/App.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/4UseACustomConfigFile/types/utils/HashUtil.d.ts b/TypeScript/4UseACustomConfigFile/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/4UseACustomConfigFile/types/utils/HashUtil.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/4UseACustomConfigFile/types/utils/HttpFileUtil.d.ts b/TypeScript/4UseACustomConfigFile/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/4UseACustomConfigFile/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/4UseACustomConfigFile/types/utils/VFS.d.ts b/TypeScript/4UseACustomConfigFile/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/4UseACustomConfigFile/types/utils/VFS.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/4UseACustomConfigFile/types/utils/Watermark.d.ts b/TypeScript/4UseACustomConfigFile/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/4UseACustomConfigFile/types/utils/Watermark.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/4UseACustomConfigFile/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/4UseACustomConfigFile/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/4UseACustomConfigFile/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/4UseACustomConfigFile/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/5ReplaceMethod/README.md b/TypeScript/5ReplaceMethod/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/5ReplaceMethod/README.md +++ b/TypeScript/5ReplaceMethod/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/5ReplaceMethod/types/controllers/GameController.d.ts b/TypeScript/5ReplaceMethod/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/5ReplaceMethod/types/controllers/GameController.d.ts +++ b/TypeScript/5ReplaceMethod/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/5ReplaceMethod/types/controllers/InraidController.d.ts b/TypeScript/5ReplaceMethod/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/5ReplaceMethod/types/controllers/InraidController.d.ts +++ b/TypeScript/5ReplaceMethod/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/5ReplaceMethod/types/controllers/InsuranceController.d.ts b/TypeScript/5ReplaceMethod/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/5ReplaceMethod/types/controllers/InsuranceController.d.ts +++ b/TypeScript/5ReplaceMethod/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/5ReplaceMethod/types/controllers/MatchController.d.ts b/TypeScript/5ReplaceMethod/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/5ReplaceMethod/types/controllers/MatchController.d.ts +++ b/TypeScript/5ReplaceMethod/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/5ReplaceMethod/types/controllers/RepeatableQuestController.d.ts b/TypeScript/5ReplaceMethod/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/5ReplaceMethod/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/5ReplaceMethod/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/5ReplaceMethod/types/di/Serializer.d.ts b/TypeScript/5ReplaceMethod/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/5ReplaceMethod/types/di/Serializer.d.ts +++ b/TypeScript/5ReplaceMethod/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/5ReplaceMethod/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/5ReplaceMethod/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/5ReplaceMethod/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/5ReplaceMethod/types/helpers/InRaidHelper.d.ts b/TypeScript/5ReplaceMethod/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/5ReplaceMethod/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/5ReplaceMethod/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/5ReplaceMethod/types/helpers/ItemHelper.d.ts b/TypeScript/5ReplaceMethod/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/5ReplaceMethod/types/helpers/ItemHelper.d.ts +++ b/TypeScript/5ReplaceMethod/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/5ReplaceMethod/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/5ReplaceMethod/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/5ReplaceMethod/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/5ReplaceMethod/types/loaders/PreAkiModLoader.d.ts b/TypeScript/5ReplaceMethod/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/5ReplaceMethod/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/5ReplaceMethod/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/5ReplaceMethod/types/models/external/HttpFramework.d.ts b/TypeScript/5ReplaceMethod/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/5ReplaceMethod/types/models/external/HttpFramework.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/IItemConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/5ReplaceMethod/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/5ReplaceMethod/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/5ReplaceMethod/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/5ReplaceMethod/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/5ReplaceMethod/types/models/spt/services/LootRequest.d.ts b/TypeScript/5ReplaceMethod/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/5ReplaceMethod/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/5ReplaceMethod/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/5ReplaceMethod/types/routers/EventOutputHolder.d.ts b/TypeScript/5ReplaceMethod/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/5ReplaceMethod/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/5ReplaceMethod/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/5ReplaceMethod/types/routers/HttpRouter.d.ts b/TypeScript/5ReplaceMethod/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/5ReplaceMethod/types/routers/HttpRouter.d.ts +++ b/TypeScript/5ReplaceMethod/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/5ReplaceMethod/types/routers/ImageRouter.d.ts b/TypeScript/5ReplaceMethod/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/5ReplaceMethod/types/routers/ImageRouter.d.ts +++ b/TypeScript/5ReplaceMethod/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/5ReplaceMethod/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/5ReplaceMethod/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/5ReplaceMethod/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/5ReplaceMethod/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/5ReplaceMethod/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/5ReplaceMethod/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/5ReplaceMethod/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/5ReplaceMethod/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/5ReplaceMethod/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/5ReplaceMethod/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/5ReplaceMethod/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/5ReplaceMethod/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/5ReplaceMethod/types/servers/HttpServer.d.ts b/TypeScript/5ReplaceMethod/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/5ReplaceMethod/types/servers/HttpServer.d.ts +++ b/TypeScript/5ReplaceMethod/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/5ReplaceMethod/types/servers/WebSocketServer.d.ts b/TypeScript/5ReplaceMethod/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/5ReplaceMethod/types/servers/WebSocketServer.d.ts +++ b/TypeScript/5ReplaceMethod/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/5ReplaceMethod/types/servers/http/AkiHttpListener.d.ts b/TypeScript/5ReplaceMethod/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/5ReplaceMethod/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/5ReplaceMethod/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/5ReplaceMethod/types/servers/http/IHttpListener.d.ts b/TypeScript/5ReplaceMethod/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/5ReplaceMethod/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/5ReplaceMethod/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/5ReplaceMethod/types/services/ItemFilterService.d.ts b/TypeScript/5ReplaceMethod/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/5ReplaceMethod/types/services/ItemFilterService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/5ReplaceMethod/types/services/ProfileFixerService.d.ts b/TypeScript/5ReplaceMethod/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/5ReplaceMethod/types/services/ProfileFixerService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/5ReplaceMethod/types/services/SeasonalEventService.d.ts b/TypeScript/5ReplaceMethod/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/5ReplaceMethod/types/services/SeasonalEventService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/5ReplaceMethod/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/5ReplaceMethod/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/5ReplaceMethod/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/5ReplaceMethod/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/5ReplaceMethod/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/5ReplaceMethod/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/5ReplaceMethod/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/5ReplaceMethod/types/utils/App.d.ts b/TypeScript/5ReplaceMethod/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/5ReplaceMethod/types/utils/App.d.ts +++ b/TypeScript/5ReplaceMethod/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/5ReplaceMethod/types/utils/HashUtil.d.ts b/TypeScript/5ReplaceMethod/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/5ReplaceMethod/types/utils/HashUtil.d.ts +++ b/TypeScript/5ReplaceMethod/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/5ReplaceMethod/types/utils/HttpFileUtil.d.ts b/TypeScript/5ReplaceMethod/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/5ReplaceMethod/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/5ReplaceMethod/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/5ReplaceMethod/types/utils/VFS.d.ts b/TypeScript/5ReplaceMethod/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/5ReplaceMethod/types/utils/VFS.d.ts +++ b/TypeScript/5ReplaceMethod/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/5ReplaceMethod/types/utils/Watermark.d.ts b/TypeScript/5ReplaceMethod/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/5ReplaceMethod/types/utils/Watermark.d.ts +++ b/TypeScript/5ReplaceMethod/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/5ReplaceMethod/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/5ReplaceMethod/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/5ReplaceMethod/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/5ReplaceMethod/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/6ReferenceAnotherClass/README.md b/TypeScript/6ReferenceAnotherClass/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/6ReferenceAnotherClass/README.md +++ b/TypeScript/6ReferenceAnotherClass/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/6ReferenceAnotherClass/types/controllers/GameController.d.ts b/TypeScript/6ReferenceAnotherClass/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/6ReferenceAnotherClass/types/controllers/GameController.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/6ReferenceAnotherClass/types/controllers/InraidController.d.ts b/TypeScript/6ReferenceAnotherClass/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/6ReferenceAnotherClass/types/controllers/InraidController.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/6ReferenceAnotherClass/types/controllers/InsuranceController.d.ts b/TypeScript/6ReferenceAnotherClass/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/6ReferenceAnotherClass/types/controllers/InsuranceController.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/6ReferenceAnotherClass/types/controllers/MatchController.d.ts b/TypeScript/6ReferenceAnotherClass/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/6ReferenceAnotherClass/types/controllers/MatchController.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/6ReferenceAnotherClass/types/controllers/RepeatableQuestController.d.ts b/TypeScript/6ReferenceAnotherClass/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/6ReferenceAnotherClass/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/6ReferenceAnotherClass/types/di/Serializer.d.ts b/TypeScript/6ReferenceAnotherClass/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/6ReferenceAnotherClass/types/di/Serializer.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/6ReferenceAnotherClass/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/6ReferenceAnotherClass/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/6ReferenceAnotherClass/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/6ReferenceAnotherClass/types/helpers/InRaidHelper.d.ts b/TypeScript/6ReferenceAnotherClass/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/6ReferenceAnotherClass/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/6ReferenceAnotherClass/types/helpers/ItemHelper.d.ts b/TypeScript/6ReferenceAnotherClass/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/6ReferenceAnotherClass/types/helpers/ItemHelper.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/6ReferenceAnotherClass/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/6ReferenceAnotherClass/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/6ReferenceAnotherClass/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/6ReferenceAnotherClass/types/loaders/PreAkiModLoader.d.ts b/TypeScript/6ReferenceAnotherClass/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/6ReferenceAnotherClass/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/6ReferenceAnotherClass/types/models/external/HttpFramework.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/external/HttpFramework.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IItemConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/6ReferenceAnotherClass/types/models/spt/services/LootRequest.d.ts b/TypeScript/6ReferenceAnotherClass/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/6ReferenceAnotherClass/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/6ReferenceAnotherClass/types/routers/EventOutputHolder.d.ts b/TypeScript/6ReferenceAnotherClass/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/6ReferenceAnotherClass/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/6ReferenceAnotherClass/types/routers/HttpRouter.d.ts b/TypeScript/6ReferenceAnotherClass/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/6ReferenceAnotherClass/types/routers/HttpRouter.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/6ReferenceAnotherClass/types/routers/ImageRouter.d.ts b/TypeScript/6ReferenceAnotherClass/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/6ReferenceAnotherClass/types/routers/ImageRouter.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/6ReferenceAnotherClass/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/6ReferenceAnotherClass/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/6ReferenceAnotherClass/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/6ReferenceAnotherClass/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/6ReferenceAnotherClass/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/6ReferenceAnotherClass/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/6ReferenceAnotherClass/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/6ReferenceAnotherClass/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/6ReferenceAnotherClass/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/6ReferenceAnotherClass/types/servers/HttpServer.d.ts b/TypeScript/6ReferenceAnotherClass/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/6ReferenceAnotherClass/types/servers/HttpServer.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/6ReferenceAnotherClass/types/servers/WebSocketServer.d.ts b/TypeScript/6ReferenceAnotherClass/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/6ReferenceAnotherClass/types/servers/WebSocketServer.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/6ReferenceAnotherClass/types/servers/http/AkiHttpListener.d.ts b/TypeScript/6ReferenceAnotherClass/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/6ReferenceAnotherClass/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/6ReferenceAnotherClass/types/servers/http/IHttpListener.d.ts b/TypeScript/6ReferenceAnotherClass/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/6ReferenceAnotherClass/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/6ReferenceAnotherClass/types/services/ItemFilterService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/ItemFilterService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/6ReferenceAnotherClass/types/services/ProfileFixerService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/ProfileFixerService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/6ReferenceAnotherClass/types/services/SeasonalEventService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/SeasonalEventService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/6ReferenceAnotherClass/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/6ReferenceAnotherClass/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/6ReferenceAnotherClass/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/6ReferenceAnotherClass/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/6ReferenceAnotherClass/types/utils/App.d.ts b/TypeScript/6ReferenceAnotherClass/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/6ReferenceAnotherClass/types/utils/App.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/6ReferenceAnotherClass/types/utils/HashUtil.d.ts b/TypeScript/6ReferenceAnotherClass/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/6ReferenceAnotherClass/types/utils/HashUtil.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/6ReferenceAnotherClass/types/utils/HttpFileUtil.d.ts b/TypeScript/6ReferenceAnotherClass/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/6ReferenceAnotherClass/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/6ReferenceAnotherClass/types/utils/VFS.d.ts b/TypeScript/6ReferenceAnotherClass/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/6ReferenceAnotherClass/types/utils/VFS.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/6ReferenceAnotherClass/types/utils/Watermark.d.ts b/TypeScript/6ReferenceAnotherClass/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/6ReferenceAnotherClass/types/utils/Watermark.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/6ReferenceAnotherClass/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/6ReferenceAnotherClass/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/6ReferenceAnotherClass/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/6ReferenceAnotherClass/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/7OnLoadHook/README.md b/TypeScript/7OnLoadHook/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/7OnLoadHook/README.md +++ b/TypeScript/7OnLoadHook/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/7OnLoadHook/types/controllers/GameController.d.ts b/TypeScript/7OnLoadHook/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/7OnLoadHook/types/controllers/GameController.d.ts +++ b/TypeScript/7OnLoadHook/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/7OnLoadHook/types/controllers/InraidController.d.ts b/TypeScript/7OnLoadHook/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/7OnLoadHook/types/controllers/InraidController.d.ts +++ b/TypeScript/7OnLoadHook/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/7OnLoadHook/types/controllers/InsuranceController.d.ts b/TypeScript/7OnLoadHook/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/7OnLoadHook/types/controllers/InsuranceController.d.ts +++ b/TypeScript/7OnLoadHook/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/7OnLoadHook/types/controllers/MatchController.d.ts b/TypeScript/7OnLoadHook/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/7OnLoadHook/types/controllers/MatchController.d.ts +++ b/TypeScript/7OnLoadHook/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/7OnLoadHook/types/controllers/RepeatableQuestController.d.ts b/TypeScript/7OnLoadHook/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/7OnLoadHook/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/7OnLoadHook/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/7OnLoadHook/types/di/Serializer.d.ts b/TypeScript/7OnLoadHook/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/7OnLoadHook/types/di/Serializer.d.ts +++ b/TypeScript/7OnLoadHook/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/7OnLoadHook/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/7OnLoadHook/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/7OnLoadHook/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/7OnLoadHook/types/helpers/InRaidHelper.d.ts b/TypeScript/7OnLoadHook/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/7OnLoadHook/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/7OnLoadHook/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/7OnLoadHook/types/helpers/ItemHelper.d.ts b/TypeScript/7OnLoadHook/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/7OnLoadHook/types/helpers/ItemHelper.d.ts +++ b/TypeScript/7OnLoadHook/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/7OnLoadHook/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/7OnLoadHook/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/7OnLoadHook/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/7OnLoadHook/types/loaders/PreAkiModLoader.d.ts b/TypeScript/7OnLoadHook/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/7OnLoadHook/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/7OnLoadHook/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/7OnLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/7OnLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/7OnLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/7OnLoadHook/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/7OnLoadHook/types/models/external/HttpFramework.d.ts b/TypeScript/7OnLoadHook/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/7OnLoadHook/types/models/external/HttpFramework.d.ts +++ b/TypeScript/7OnLoadHook/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/IItemConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/7OnLoadHook/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/7OnLoadHook/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/7OnLoadHook/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/7OnLoadHook/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/7OnLoadHook/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/7OnLoadHook/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/7OnLoadHook/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/7OnLoadHook/types/models/spt/services/LootRequest.d.ts b/TypeScript/7OnLoadHook/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/7OnLoadHook/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/7OnLoadHook/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/7OnLoadHook/types/routers/EventOutputHolder.d.ts b/TypeScript/7OnLoadHook/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/7OnLoadHook/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/7OnLoadHook/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/7OnLoadHook/types/routers/HttpRouter.d.ts b/TypeScript/7OnLoadHook/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/7OnLoadHook/types/routers/HttpRouter.d.ts +++ b/TypeScript/7OnLoadHook/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/7OnLoadHook/types/routers/ImageRouter.d.ts b/TypeScript/7OnLoadHook/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/7OnLoadHook/types/routers/ImageRouter.d.ts +++ b/TypeScript/7OnLoadHook/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/7OnLoadHook/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/7OnLoadHook/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/7OnLoadHook/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/7OnLoadHook/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/7OnLoadHook/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/7OnLoadHook/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/7OnLoadHook/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/7OnLoadHook/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/7OnLoadHook/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/7OnLoadHook/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/7OnLoadHook/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/7OnLoadHook/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/7OnLoadHook/types/servers/HttpServer.d.ts b/TypeScript/7OnLoadHook/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/7OnLoadHook/types/servers/HttpServer.d.ts +++ b/TypeScript/7OnLoadHook/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/7OnLoadHook/types/servers/WebSocketServer.d.ts b/TypeScript/7OnLoadHook/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/7OnLoadHook/types/servers/WebSocketServer.d.ts +++ b/TypeScript/7OnLoadHook/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/7OnLoadHook/types/servers/http/AkiHttpListener.d.ts b/TypeScript/7OnLoadHook/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/7OnLoadHook/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/7OnLoadHook/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/7OnLoadHook/types/servers/http/IHttpListener.d.ts b/TypeScript/7OnLoadHook/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/7OnLoadHook/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/7OnLoadHook/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/7OnLoadHook/types/services/ItemFilterService.d.ts b/TypeScript/7OnLoadHook/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/7OnLoadHook/types/services/ItemFilterService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/7OnLoadHook/types/services/ProfileFixerService.d.ts b/TypeScript/7OnLoadHook/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/7OnLoadHook/types/services/ProfileFixerService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/7OnLoadHook/types/services/SeasonalEventService.d.ts b/TypeScript/7OnLoadHook/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/7OnLoadHook/types/services/SeasonalEventService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/7OnLoadHook/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/7OnLoadHook/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/7OnLoadHook/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/7OnLoadHook/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/7OnLoadHook/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/7OnLoadHook/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/7OnLoadHook/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/7OnLoadHook/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/7OnLoadHook/types/utils/App.d.ts b/TypeScript/7OnLoadHook/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/7OnLoadHook/types/utils/App.d.ts +++ b/TypeScript/7OnLoadHook/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/7OnLoadHook/types/utils/HashUtil.d.ts b/TypeScript/7OnLoadHook/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/7OnLoadHook/types/utils/HashUtil.d.ts +++ b/TypeScript/7OnLoadHook/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/7OnLoadHook/types/utils/HttpFileUtil.d.ts b/TypeScript/7OnLoadHook/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/7OnLoadHook/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/7OnLoadHook/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/7OnLoadHook/types/utils/VFS.d.ts b/TypeScript/7OnLoadHook/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/7OnLoadHook/types/utils/VFS.d.ts +++ b/TypeScript/7OnLoadHook/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/7OnLoadHook/types/utils/Watermark.d.ts b/TypeScript/7OnLoadHook/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/7OnLoadHook/types/utils/Watermark.d.ts +++ b/TypeScript/7OnLoadHook/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/7OnLoadHook/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/7OnLoadHook/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/7OnLoadHook/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/7OnLoadHook/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/8OnUpdateHook/README.md b/TypeScript/8OnUpdateHook/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/8OnUpdateHook/README.md +++ b/TypeScript/8OnUpdateHook/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/8OnUpdateHook/types/controllers/GameController.d.ts b/TypeScript/8OnUpdateHook/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/8OnUpdateHook/types/controllers/GameController.d.ts +++ b/TypeScript/8OnUpdateHook/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/8OnUpdateHook/types/controllers/InraidController.d.ts b/TypeScript/8OnUpdateHook/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/8OnUpdateHook/types/controllers/InraidController.d.ts +++ b/TypeScript/8OnUpdateHook/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/8OnUpdateHook/types/controllers/InsuranceController.d.ts b/TypeScript/8OnUpdateHook/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/8OnUpdateHook/types/controllers/InsuranceController.d.ts +++ b/TypeScript/8OnUpdateHook/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/8OnUpdateHook/types/controllers/MatchController.d.ts b/TypeScript/8OnUpdateHook/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/8OnUpdateHook/types/controllers/MatchController.d.ts +++ b/TypeScript/8OnUpdateHook/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/8OnUpdateHook/types/controllers/RepeatableQuestController.d.ts b/TypeScript/8OnUpdateHook/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/8OnUpdateHook/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/8OnUpdateHook/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/8OnUpdateHook/types/di/Serializer.d.ts b/TypeScript/8OnUpdateHook/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/8OnUpdateHook/types/di/Serializer.d.ts +++ b/TypeScript/8OnUpdateHook/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/8OnUpdateHook/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/8OnUpdateHook/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/8OnUpdateHook/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/8OnUpdateHook/types/helpers/InRaidHelper.d.ts b/TypeScript/8OnUpdateHook/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/8OnUpdateHook/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/8OnUpdateHook/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/8OnUpdateHook/types/helpers/ItemHelper.d.ts b/TypeScript/8OnUpdateHook/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/8OnUpdateHook/types/helpers/ItemHelper.d.ts +++ b/TypeScript/8OnUpdateHook/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/8OnUpdateHook/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/8OnUpdateHook/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/8OnUpdateHook/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/8OnUpdateHook/types/loaders/PreAkiModLoader.d.ts b/TypeScript/8OnUpdateHook/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/8OnUpdateHook/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/8OnUpdateHook/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/8OnUpdateHook/types/models/external/HttpFramework.d.ts b/TypeScript/8OnUpdateHook/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/8OnUpdateHook/types/models/external/HttpFramework.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/IItemConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/8OnUpdateHook/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/8OnUpdateHook/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/8OnUpdateHook/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/8OnUpdateHook/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/8OnUpdateHook/types/models/spt/services/LootRequest.d.ts b/TypeScript/8OnUpdateHook/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/8OnUpdateHook/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/8OnUpdateHook/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/8OnUpdateHook/types/routers/EventOutputHolder.d.ts b/TypeScript/8OnUpdateHook/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/8OnUpdateHook/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/8OnUpdateHook/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/8OnUpdateHook/types/routers/HttpRouter.d.ts b/TypeScript/8OnUpdateHook/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/8OnUpdateHook/types/routers/HttpRouter.d.ts +++ b/TypeScript/8OnUpdateHook/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/8OnUpdateHook/types/routers/ImageRouter.d.ts b/TypeScript/8OnUpdateHook/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/8OnUpdateHook/types/routers/ImageRouter.d.ts +++ b/TypeScript/8OnUpdateHook/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/8OnUpdateHook/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/8OnUpdateHook/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/8OnUpdateHook/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/8OnUpdateHook/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/8OnUpdateHook/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/8OnUpdateHook/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/8OnUpdateHook/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/8OnUpdateHook/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/8OnUpdateHook/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/8OnUpdateHook/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/8OnUpdateHook/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/8OnUpdateHook/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/8OnUpdateHook/types/servers/HttpServer.d.ts b/TypeScript/8OnUpdateHook/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/8OnUpdateHook/types/servers/HttpServer.d.ts +++ b/TypeScript/8OnUpdateHook/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/8OnUpdateHook/types/servers/WebSocketServer.d.ts b/TypeScript/8OnUpdateHook/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/8OnUpdateHook/types/servers/WebSocketServer.d.ts +++ b/TypeScript/8OnUpdateHook/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/8OnUpdateHook/types/servers/http/AkiHttpListener.d.ts b/TypeScript/8OnUpdateHook/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/8OnUpdateHook/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/8OnUpdateHook/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/8OnUpdateHook/types/servers/http/IHttpListener.d.ts b/TypeScript/8OnUpdateHook/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/8OnUpdateHook/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/8OnUpdateHook/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/8OnUpdateHook/types/services/ItemFilterService.d.ts b/TypeScript/8OnUpdateHook/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/8OnUpdateHook/types/services/ItemFilterService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/8OnUpdateHook/types/services/ProfileFixerService.d.ts b/TypeScript/8OnUpdateHook/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/8OnUpdateHook/types/services/ProfileFixerService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/8OnUpdateHook/types/services/SeasonalEventService.d.ts b/TypeScript/8OnUpdateHook/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/8OnUpdateHook/types/services/SeasonalEventService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/8OnUpdateHook/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/8OnUpdateHook/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/8OnUpdateHook/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/8OnUpdateHook/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/8OnUpdateHook/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/8OnUpdateHook/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/8OnUpdateHook/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/8OnUpdateHook/types/utils/App.d.ts b/TypeScript/8OnUpdateHook/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/8OnUpdateHook/types/utils/App.d.ts +++ b/TypeScript/8OnUpdateHook/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/8OnUpdateHook/types/utils/HashUtil.d.ts b/TypeScript/8OnUpdateHook/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/8OnUpdateHook/types/utils/HashUtil.d.ts +++ b/TypeScript/8OnUpdateHook/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/8OnUpdateHook/types/utils/HttpFileUtil.d.ts b/TypeScript/8OnUpdateHook/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/8OnUpdateHook/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/8OnUpdateHook/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/8OnUpdateHook/types/utils/VFS.d.ts b/TypeScript/8OnUpdateHook/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/8OnUpdateHook/types/utils/VFS.d.ts +++ b/TypeScript/8OnUpdateHook/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/8OnUpdateHook/types/utils/Watermark.d.ts b/TypeScript/8OnUpdateHook/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/8OnUpdateHook/types/utils/Watermark.d.ts +++ b/TypeScript/8OnUpdateHook/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/8OnUpdateHook/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/8OnUpdateHook/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/8OnUpdateHook/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/8OnUpdateHook/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor"; diff --git a/TypeScript/9RouterHooks/README.md b/TypeScript/9RouterHooks/README.md index 8cba28e..48c742b 100644 --- a/TypeScript/9RouterHooks/README.md +++ b/TypeScript/9RouterHooks/README.md @@ -13,7 +13,7 @@ This project is designed to streamline the initial setup process for building an ## **NodeJS Setup** -Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). +Before you begin, ensure to install NodeJS version `v18.15.0`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/). After installation, it's advised to reboot your system. diff --git a/TypeScript/9RouterHooks/types/controllers/GameController.d.ts b/TypeScript/9RouterHooks/types/controllers/GameController.d.ts index b6903b7..74123b2 100644 --- a/TypeScript/9RouterHooks/types/controllers/GameController.d.ts +++ b/TypeScript/9RouterHooks/types/controllers/GameController.d.ts @@ -27,7 +27,6 @@ import { LocalisationService } from "../services/LocalisationService"; import { OpenZoneService } from "../services/OpenZoneService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { SeasonalEventService } from "../services/SeasonalEventService"; -import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; @@ -36,7 +35,6 @@ export declare class GameController { protected databaseServer: DatabaseServer; protected jsonUtil: JsonUtil; protected timeUtil: TimeUtil; - protected hashUtil: HashUtil; protected preAkiModLoader: PreAkiModLoader; protected httpServerHelper: HttpServerHelper; protected randomUtil: RandomUtil; @@ -51,14 +49,13 @@ export declare class GameController { protected giftService: GiftService; protected applicationContext: ApplicationContext; protected configServer: ConfigServer; - protected os: any; protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; protected ragfairConfig: IRagfairConfig; protected pmcConfig: IPmcConfig; protected lootConfig: ILootConfig; - constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); + constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer); load(): void; /** * Handle client/game/start @@ -67,12 +64,6 @@ export declare class GameController { protected addCustomLooseLootPositions(): void; protected adjustLooseLootSpawnProbabilities(): void; protected setHideoutAreasAndCraftsTo40Secs(): void; - /** - * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated - * We store the old AID value in new field `sessionId` - * @param fullProfile Profile to update - */ - protected fixIncorrectAidValue(fullProfile: IAkiProfile): void; /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ protected adjustMapBotLimits(): void; /** diff --git a/TypeScript/9RouterHooks/types/controllers/InraidController.d.ts b/TypeScript/9RouterHooks/types/controllers/InraidController.d.ts index 6e86c63..e4a8d64 100644 --- a/TypeScript/9RouterHooks/types/controllers/InraidController.d.ts +++ b/TypeScript/9RouterHooks/types/controllers/InraidController.d.ts @@ -62,10 +62,10 @@ export declare class InraidController { savePostRaidProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; /** * Handle updating player profile post-pmc raid - * @param sessionID session id - * @param offraidData post-raid data + * @param sessionID Session id + * @param postRaidRequest Post-raid data */ - protected savePmcProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Make changes to pmc profile after they've died in raid, * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items @@ -91,10 +91,10 @@ export declare class InraidController { protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void; /** * Handle updating the profile post-pscav raid - * @param sessionID session id - * @param offraidData post-raid data of raid + * @param sessionID Session id + * @param postRaidRequest Post-raid data of raid */ - protected savePlayerScavProgress(sessionID: string, offraidData: ISaveProgressRequestData): void; + protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void; /** * Is the player dead after a raid - dead is anything other than "survived" / "runner" * @param statusOnExit exit value from offraidData object diff --git a/TypeScript/9RouterHooks/types/controllers/InsuranceController.d.ts b/TypeScript/9RouterHooks/types/controllers/InsuranceController.d.ts index 061d0c9..fc3229b 100644 --- a/TypeScript/9RouterHooks/types/controllers/InsuranceController.d.ts +++ b/TypeScript/9RouterHooks/types/controllers/InsuranceController.d.ts @@ -4,12 +4,11 @@ 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"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; -import { Insurance } from "../models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "../models/eft/profile/IAkiProfile"; import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; @@ -67,67 +66,100 @@ export declare class InsuranceController { */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void; /** - * Build an array of items to delete from the insured items. + * Remove an insurance package from a profile using the package's system data information. * - * 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. + * @param sessionID The session ID of the profile to remove the package from. + * @param index The array index of the insurance package to remove. * @returns void */ - protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map): void; + protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): 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. + * Finds the items that should be deleted based on the given Insurance object. * - * @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 insured The insurance object containing the items to evaluate for deletion. + * @returns A Set containing the IDs of items that should be deleted. + */ + protected findItemsToDelete(insured: Insurance): Set; + /** + * Populate a Map object of items for quick lookup by their ID. + * + * @param insured The insurance object containing the items to populate the map with. + * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. + */ + protected populateItemsMap(insured: Insurance): Map; + /** + * Initialize a Map object that holds main-parents to all of their attachments. Note that "main-parent" in this + * context refers to the parent item that an attachment is attached to. For example, a suppressor attached to a gun, + * not the backpack that the gun is located in (the gun's parent). + * + * @param insured - The insurance object containing the items to evaluate. + * @param itemsMap - A Map object for quick item look-up by item ID. + * @returns A Map object containing parent item IDs to arrays of their attachment items. + */ + protected populateParentAttachmentsMap(insured: Insurance, itemsMap: Map): Map; + /** + * Process "regular" insurance items. Any insured item that is not an attached, attachment is considered a "regular" + * item. This method iterates over them, preforming item deletion rolls to see if they should be deleted. If so, + * they (and their attached, attachments, if any) are marked for deletion in the toDelete Set. + * + * @param insured The insurance object containing the items to evaluate. + * @param toDelete A Set to keep track of items marked for deletion. + * @returns void + */ + protected processRegularItems(insured: Insurance, toDelete: Set): void; + /** + * Process parent items and their attachments, updating the toDelete Set accordingly. + * + * This method iterates over a map of parent items to their attachments and performs evaluations on each. + * It marks items for deletion based on certain conditions and updates the toDelete Set accordingly. + * + * @param mainParentToAttachmentsMap A Map object containing parent item IDs to arrays of their attachment items. + * @param itemsMap A Map object for quick item look-up by item ID. + * @param traderId The trader ID from the Insurance object. + * @param toDelete A Set object to keep track of items marked for deletion. + */ + protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void; + /** + * Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by + * their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the + * number of deletions has been counted, the attachments are added to the toDelete Set, starting with the most + * valuable attachments first. + * + * @param attachments The array of attachment items to sort, filter, and roll. + * @param traderId The ID of the trader to that has ensured these items. * @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; + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void; + /** + * Sorts the attachment items by their max price in descending order. + * + * @param attachments The array of attachments items. + * @returns An array of items enriched with their max price and common locale-name. + */ + protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[]; + /** + * Logs the details of each attachment item. + * + * @param attachments The array of attachment items. + */ + protected logAttachmentsDetails(attachments: EnrichedItem[]): void; + /** + * Counts the number of successful rolls for the attachment items. + * + * @param attachments The array of attachment items. + * @param traderId The ID of the trader that has insured these attachments. + * @returns The number of successful rolls. + */ + protected countSuccessfulRolls(attachments: Item[], traderId: string): number; + /** + * Marks the most valuable attachments for deletion based on the number of successful rolls made. + * + * @param attachments The array of attachment items. + * @param successfulRolls The number of successful rolls. + * @param toDelete The array that accumulates the IDs of the items to be deleted. + */ + protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void; /** * Remove items from the insured items that should not be returned to the player. * @@ -135,7 +167,23 @@ export declare class InsuranceController { * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void; + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void; + /** + * Adopts orphaned items by resetting them as base-level items. Helpful in situations where a parent has been + * deleted from insurance, but any insured items within the parent should remain. This method will remove the + * reference from the children to the parent and set item properties to main-level values. + * + * @param insured Insurance object containing items. + */ + protected adoptOrphanedItems(insured: Insurance): void; + /** + * Fetches the parentId property of an item with a slotId "hideout". Not sure if this is actually dynamic, but this + * method should be a reliable way to fetch it, if it ever does change. + * + * @param items Array of items to search through. + * @returns The parentId of an item with slotId 'hideout'. Empty string if not found. + */ + protected fetchHideoutItemParent(items: Item[]): string; /** * Handle sending the insurance message to the user that potentially contains the valid insurance items. * @@ -146,15 +194,14 @@ export declare class InsuranceController { */ 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 + * Determines whether a 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. + * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise. */ - protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean; + protected rollForDelete(traderId: string, insuredItem?: Item): boolean; /** * Handle Insure event * Add insurance to an item @@ -175,3 +222,8 @@ export declare class InsuranceController { */ cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; } +interface EnrichedItem extends Item { + name: string; + maxPrice: number; +} +export {}; diff --git a/TypeScript/9RouterHooks/types/controllers/MatchController.d.ts b/TypeScript/9RouterHooks/types/controllers/MatchController.d.ts index ce9bc7f..23b65bf 100644 --- a/TypeScript/9RouterHooks/types/controllers/MatchController.d.ts +++ b/TypeScript/9RouterHooks/types/controllers/MatchController.d.ts @@ -1,4 +1,5 @@ import { ApplicationContext } from "../context/ApplicationContext"; +import { LootGenerator } from "../generators/LootGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { TraderHelper } from "../helpers/TraderHelper"; import { IPmcData } from "../models/eft/common/IPmcData"; @@ -12,16 +13,24 @@ import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult"; import { IInRaidConfig } from "../models/spt/config/IInRaidConfig"; import { IMatchConfig } from "../models/spt/config/IMatchConfig"; import { IPmcConfig } from "../models/spt/config/IPmcConfig"; +import { ITraderConfig } from "../models/spt/config/ITraderConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { SaveServer } from "../servers/SaveServer"; import { BotGenerationCacheService } from "../services/BotGenerationCacheService"; import { BotLootCacheService } from "../services/BotLootCacheService"; +import { MailSendService } from "../services/MailSendService"; import { MatchLocationService } from "../services/MatchLocationService"; import { ProfileSnapshotService } from "../services/ProfileSnapshotService"; +import { HashUtil } from "../utils/HashUtil"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class MatchController { protected logger: ILogger; protected saveServer: SaveServer; + protected timeUtil: TimeUtil; + protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected profileHelper: ProfileHelper; protected matchLocationService: MatchLocationService; protected traderHelper: TraderHelper; @@ -29,11 +38,14 @@ export declare class MatchController { protected configServer: ConfigServer; protected profileSnapshotService: ProfileSnapshotService; protected botGenerationCacheService: BotGenerationCacheService; + protected mailSendService: MailSendService; + protected lootGenerator: LootGenerator; protected applicationContext: ApplicationContext; protected matchConfig: IMatchConfig; protected inraidConfig: IInRaidConfig; + protected traderConfig: ITraderConfig; protected pmcConfig: IPmcConfig; - constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, randomUtil: RandomUtil, hashUtil: HashUtil, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, mailSendService: MailSendService, lootGenerator: LootGenerator, applicationContext: ApplicationContext); getEnabled(): boolean; /** Handle raid/profile/list */ getProfile(info: IGetProfileRequestData): IPmcData[]; @@ -59,6 +71,13 @@ export declare class MatchController { protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string; /** Handle client/match/offline/end */ endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void; + /** + * Did player take a COOP extract + * @param extractName Name of extract player took + * @returns True if coop extract + */ + protected extractWasViaCoop(extractName: string): boolean; + protected sendCoopTakenFenceMessage(sessionId: string): void; /** * Was extract by car * @param extractName name of extract diff --git a/TypeScript/9RouterHooks/types/controllers/RepeatableQuestController.d.ts b/TypeScript/9RouterHooks/types/controllers/RepeatableQuestController.d.ts index e9d2e56..024d85d 100644 --- a/TypeScript/9RouterHooks/types/controllers/RepeatableQuestController.d.ts +++ b/TypeScript/9RouterHooks/types/controllers/RepeatableQuestController.d.ts @@ -1,81 +1,41 @@ -import { HandbookHelper } from "../helpers/HandbookHelper"; -import { ItemHelper } from "../helpers/ItemHelper"; -import { PresetHelper } from "../helpers/PresetHelper"; +import { RepeatableQuestGenerator } from "../generators/RepeatableQuestGenerator"; import { ProfileHelper } from "../helpers/ProfileHelper"; import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData"; -import { Exit } from "../models/eft/common/ILocationBase"; import { IPmcData } from "../models/eft/common/IPmcData"; -import { TraderInfo } from "../models/eft/common/tables/IBotBase"; -import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IPmcDataRepeatableQuest, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; -import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IPmcDataRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "../models/eft/quests/IRepeatableQuestChangeRequest"; -import { ELocationName } from "../models/enums/ELocationName"; -import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; import { ILogger } from "../models/spt/utils/ILogger"; import { EventOutputHolder } from "../routers/EventOutputHolder"; import { ConfigServer } from "../servers/ConfigServer"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { ItemFilterService } from "../services/ItemFilterService"; -import { LocalisationService } from "../services/LocalisationService"; import { PaymentService } from "../services/PaymentService"; import { ProfileFixerService } from "../services/ProfileFixerService"; import { HttpResponseUtil } from "../utils/HttpResponseUtil"; import { JsonUtil } from "../utils/JsonUtil"; -import { MathUtil } from "../utils/MathUtil"; import { ObjectId } from "../utils/ObjectId"; -import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "../utils/RandomUtil"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; -export interface IQuestTypePool { - types: string[]; - pool: IQuestPool; -} -export interface IQuestPool { - Exploration: IExplorationPool; - Elimination: IEliminationPool; -} -export interface IExplorationPool { - locations: Partial>; -} -export interface IEliminationPool { - targets: IEliminationTargetPool; -} -export interface IEliminationTargetPool { - Savage?: ITargetLocation; - AnyPmc?: ITargetLocation; - bossBully?: ITargetLocation; - bossGluhar?: ITargetLocation; - bossKilla?: ITargetLocation; - bossSanitar?: ITargetLocation; - bossTagilla?: ITargetLocation; - bossKojaniy?: ITargetLocation; -} -export interface ITargetLocation { - locations: string[]; -} export declare class RepeatableQuestController { protected timeUtil: TimeUtil; protected logger: ILogger; protected randomUtil: RandomUtil; protected httpResponse: HttpResponseUtil; - protected mathUtil: MathUtil; protected jsonUtil: JsonUtil; - protected databaseServer: DatabaseServer; - protected itemHelper: ItemHelper; - protected presetHelper: PresetHelper; protected profileHelper: ProfileHelper; protected profileFixerService: ProfileFixerService; - protected handbookHelper: HandbookHelper; protected ragfairServerHelper: RagfairServerHelper; protected eventOutputHolder: EventOutputHolder; - protected localisationService: LocalisationService; protected paymentService: PaymentService; protected objectId: ObjectId; - protected itemFilterService: ItemFilterService; + protected repeatableQuestGenerator: RepeatableQuestGenerator; + protected repeatableQuestHelper: RepeatableQuestHelper; protected configServer: ConfigServer; protected questConfig: IQuestConfig; - constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, configServer: ConfigServer); + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, paymentService: PaymentService, objectId: ObjectId, repeatableQuestGenerator: RepeatableQuestGenerator, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -109,103 +69,10 @@ export declare class RepeatableQuestController { * @returns IPmcDataRepeatableQuest */ protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest; - /** - * This method is called by GetClientRepeatableQuests and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). - * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest - */ - protected generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ generateDebugDailies(dailiesPool: any, factory: any, number: number): any; - /** - * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json - * The templates include Elimination, Completion and Extraction quest types - * - * @param {string} type quest type: "Elimination", "Completion" or "Extraction" - * @param {string} traderId trader from which the quest will be provided - * @param {string} side scav daily or pmc daily/weekly quest - * @returns {object} a object which contains the base elements for repeatable quests of the requests type - * (needs to be filled with reward and conditions by called to make a valid quest) - */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; - /** - * Generates a valid Exploration quest - * - * @param {integer} pmcLevel player's level for reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) - */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; - /** - * Generates a valid Completion quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) - */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; - /** - * Generates a valid Elimination quest - * - * @param {integer} pmcLevel player's level for requested items and reward generation - * @param {string} traderId trader from which the quest will be provided - * @param {object} questTypePool Pools for quests (used to avoid redundant quests) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) - */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; - /** - * Get the relevant elimination config based on the current players PMC level - * @param pmcLevel Level of PMC character - * @param repeatableConfig Main repeatable config - * @returns IEliminationConfig - */ - protected getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; - /** - * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) - * @param locationKey e.g factory4_day - * @returns guid - */ - protected getQuestLocationByMapId(locationKey: string): string; - /** - * Exploration repeatable quests can specify a required extraction point. - * This method creates the according object which will be appended to the conditions array - * - * @param {string} exit The exit name to generate the condition for - * @returns {object} Exit condition - */ - protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) - * - * @param {string} targetItemId id of the item to request - * @param {integer} value amount of items of this specific type to request - * @returns {object} object of "Completion"-condition - */ - protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a location condition. - * - * @param {string} location the location on which to fulfill the elimination quest - * @returns {object} object of "Elimination"-location-subcondition - */ - protected generateEliminationLocation(location: string[]): IEliminationCondition; - /** - * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) - * This is a helper method for GenerateEliminationQuest to create a kill condition. - * - * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" - * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] - * @param {number} distance distance from which to kill (currently only >= supported) - * @returns {object} object of "Elimination"-kill-subcondition - */ - protected generateEliminationCondition(target: string, bodyPart: string[], distance: number): IEliminationCondition; /** * Used to create a quest pool during each cycle of repeatable quest generation. The pool will be subsequently * narrowed down during quest generation to avoid duplicate quests. Like duplicate extractions or elimination quests @@ -215,53 +82,10 @@ export declare class RepeatableQuestController { * @returns IQuestTypePool */ protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool; - /** - * Generate the reward for a mission. A reward can consist of - * - Experience - * - Money - * - Items - * - Trader Reputation - * - * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to - * experience / money / items / trader reputation can be defined in QuestConfig.js - * - * There's also a random variation of the reward the spread of which can be also defined in the config. - * - * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used - * - * @param {integer} pmcLevel player's level - * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 - * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) - * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest - * @returns {object} object of "Reward"-type that can be given for a repeatable mission - */ - protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; - /** - * Helper to create a reward item structured as required by the client - * - * @param {string} tpl itemId of the rewarded item - * @param {integer} value amount of items to give - * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index - * @returns {object} object of "Reward"-item-type - */ - protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool; debugLogRepeatableQuestIds(pmcData: IPmcData): void; - protected probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; /** * Handle RepeatableQuestChange event */ - changeRepeatableQuest(pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; - /** - * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) - * @param repeatableQuestConfig config file - * @returns a list of rewardable items [[_tpl, itemTemplate],...] - */ - protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; - /** - * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward - * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. - * @param {string} tpl template id of item to check - * @returns boolean: true if item is valid reward - */ - protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/TypeScript/9RouterHooks/types/di/Serializer.d.ts b/TypeScript/9RouterHooks/types/di/Serializer.d.ts index 2617007..b760b8b 100644 --- a/TypeScript/9RouterHooks/types/di/Serializer.d.ts +++ b/TypeScript/9RouterHooks/types/di/Serializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export declare class Serializer { serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void; canHandle(something: string): boolean; diff --git a/TypeScript/9RouterHooks/types/generators/RepeatableQuestGenerator.d.ts b/TypeScript/9RouterHooks/types/generators/RepeatableQuestGenerator.d.ts new file mode 100644 index 0000000..7fa39ba --- /dev/null +++ b/TypeScript/9RouterHooks/types/generators/RepeatableQuestGenerator.d.ts @@ -0,0 +1,183 @@ +import { HandbookHelper } from "../helpers/HandbookHelper"; +import { ItemHelper } from "../helpers/ItemHelper"; +import { PresetHelper } from "../helpers/PresetHelper"; +import { ProfileHelper } from "../helpers/ProfileHelper"; +import { RagfairServerHelper } from "../helpers/RagfairServerHelper"; +import { RepeatableQuestHelper } from "../helpers/RepeatableQuestHelper"; +import { Exit } from "../models/eft/common/ILocationBase"; +import { TraderInfo } from "../models/eft/common/tables/IBotBase"; +import { ICompletion, ICompletionAvailableFor, IElimination, IEliminationCondition, IExploration, IExplorationCondition, IRepeatableQuest, IReward, IRewards } from "../models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { IQuestTypePool } from "../models/spt/repeatable/IQuestTypePool"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { EventOutputHolder } from "../routers/EventOutputHolder"; +import { ConfigServer } from "../servers/ConfigServer"; +import { DatabaseServer } from "../servers/DatabaseServer"; +import { ItemFilterService } from "../services/ItemFilterService"; +import { LocalisationService } from "../services/LocalisationService"; +import { PaymentService } from "../services/PaymentService"; +import { ProfileFixerService } from "../services/ProfileFixerService"; +import { HttpResponseUtil } from "../utils/HttpResponseUtil"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ObjectId } from "../utils/ObjectId"; +import { RandomUtil } from "../utils/RandomUtil"; +import { TimeUtil } from "../utils/TimeUtil"; +export declare class RepeatableQuestGenerator { + protected timeUtil: TimeUtil; + protected logger: ILogger; + protected randomUtil: RandomUtil; + protected httpResponse: HttpResponseUtil; + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected itemHelper: ItemHelper; + protected presetHelper: PresetHelper; + protected profileHelper: ProfileHelper; + protected profileFixerService: ProfileFixerService; + protected handbookHelper: HandbookHelper; + protected ragfairServerHelper: RagfairServerHelper; + protected eventOutputHolder: EventOutputHolder; + protected localisationService: LocalisationService; + protected paymentService: PaymentService; + protected objectId: ObjectId; + protected itemFilterService: ItemFilterService; + protected repeatableQuestHelper: RepeatableQuestHelper; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(timeUtil: TimeUtil, logger: ILogger, randomUtil: RandomUtil, httpResponse: HttpResponseUtil, mathUtil: MathUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, handbookHelper: HandbookHelper, ragfairServerHelper: RagfairServerHelper, eventOutputHolder: EventOutputHolder, localisationService: LocalisationService, paymentService: PaymentService, objectId: ObjectId, itemFilterService: ItemFilterService, repeatableQuestHelper: RepeatableQuestHelper, configServer: ConfigServer); + /** + * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). + * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param pmcLevel Player's level for requested items and reward generation + * @param pmcTraderInfo Players traper standing/rep levels + * @param questTypePool Possible quest types pool + * @param repeatableConfig Repeatable quest config + * @returns IRepeatableQuest + */ + generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + /** + * Generate a randomised Elimination quest + * @param pmcLevel Player's level for requested items and reward generation + * @param traderId Trader from which the quest will be provided + * @param questTypePool Pools for quests (used to avoid redundant quests) + * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) + */ + protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IElimination; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a location condition. + * + * @param {string} location the location on which to fulfill the elimination quest + * @returns {object} object of "Elimination"-location-subcondition + */ + protected generateEliminationLocation(location: string[], allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateEliminationQuest to create a kill condition. + * + * @param {string} target array of target npcs e.g. "AnyPmc", "Savage" + * @param {array} bodyParts array of body parts with which to kill e.g. ["stomach", "thorax"] + * @param {number} distance distance from which to kill (currently only >= supported) + * @returns {object} object of "Elimination"-kill-subcondition + */ + protected generateEliminationCondition(target: string, bodyPart: string[], distance: number, allowedWeapon: string, allowedWeaponCategory: string): IEliminationCondition; + /** + * Generates a valid Completion quest + * + * @param {integer} pmcLevel player's level for requested items and reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) + */ + protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): ICompletion; + /** + * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) + * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) + * + * @param {string} targetItemId id of the item to request + * @param {integer} value amount of items of this specific type to request + * @returns {object} object of "Completion"-condition + */ + protected generateCompletionAvailableForFinish(targetItemId: string, value: number): ICompletionAvailableFor; + /** + * Generates a valid Exploration quest + * + * @param {integer} pmcLevel player's level for reward generation + * @param {string} traderId trader from which the quest will be provided + * @param {object} questTypePool Pools for quests (used to avoid redundant quests) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) + */ + protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IExploration; + /** + * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) + * @param locationKey e.g factory4_day + * @returns guid + */ + protected getQuestLocationByMapId(locationKey: string): string; + /** + * Exploration repeatable quests can specify a required extraction point. + * This method creates the according object which will be appended to the conditions array + * + * @param {string} exit The exit name to generate the condition for + * @returns {object} Exit condition + */ + protected generateExplorationExitCondition(exit: Exit): IExplorationCondition; + /** + * Generate the reward for a mission. A reward can consist of + * - Experience + * - Money + * - Items + * - Trader Reputation + * + * The reward is dependent on the player level as given by the wiki. The exact mapping of pmcLevel to + * experience / money / items / trader reputation can be defined in QuestConfig.js + * + * There's also a random variation of the reward the spread of which can be also defined in the config. + * + * Additonaly, a scaling factor w.r.t. quest difficulty going from 0.2...1 can be used + * + * @param {integer} pmcLevel player's level + * @param {number} difficulty a reward scaling factor goint from 0.2 to 1 + * @param {string} traderId the trader for reputation gain (and possible in the future filtering of reward item type based on trader) + * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest + * @returns {object} object of "Reward"-type that can be given for a repeatable mission + */ + protected generateReward(pmcLevel: number, difficulty: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRewards; + /** + * Helper to create a reward item structured as required by the client + * + * @param {string} tpl itemId of the rewarded item + * @param {integer} value amount of items to give + * @param {integer} index all rewards will be appended to a list, for unkown reasons the client wants the index + * @returns {object} object of "Reward"-item-type + */ + protected generateRewardItem(tpl: string, value: number, index: number, preset?: any): IReward; + /** + * Picks rewardable items from items.json. This means they need to fit into the inventory and they shouldn't be keys (debatable) + * @param repeatableQuestConfig config file + * @returns a list of rewardable items [[_tpl, itemTemplate],...] + */ + protected getRewardableItems(repeatableQuestConfig: IRepeatableQuestConfig): [string, ITemplateItem][]; + /** + * Checks if an id is a valid item. Valid meaning that it's an item that may be a reward + * or content of bot loot. Items that are tested as valid may be in a player backpack or stash. + * @param {string} tpl template id of item to check + * @returns boolean: true if item is valid reward + */ + protected isValidRewardItem(tpl: string, repeatableQuestConfig: IRepeatableQuestConfig): boolean; + /** + * Generates the base object of quest type format given as templates in assets/database/templates/repeatableQuests.json + * The templates include Elimination, Completion and Extraction quest types + * + * @param {string} type quest type: "Elimination", "Completion" or "Extraction" + * @param {string} traderId trader from which the quest will be provided + * @param {string} side scav daily or pmc daily/weekly quest + * @returns {object} a object which contains the base elements for repeatable quests of the requests type + * (needs to be filled with reward and conditions by called to make a valid quest) + */ + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; +} diff --git a/TypeScript/9RouterHooks/types/helpers/InRaidHelper.d.ts b/TypeScript/9RouterHooks/types/helpers/InRaidHelper.d.ts index b4c0c1c..3550489 100644 --- a/TypeScript/9RouterHooks/types/helpers/InRaidHelper.d.ts +++ b/TypeScript/9RouterHooks/types/helpers/InRaidHelper.d.ts @@ -111,11 +111,11 @@ export declare class InRaidHelper { * Add new items found in raid to profile * Store insurance items in profile * @param sessionID Session id - * @param pmcData Profile to update + * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid * @returns Updated profile */ - setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; + setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt * Used post-raid to remove items after death diff --git a/TypeScript/9RouterHooks/types/helpers/ItemHelper.d.ts b/TypeScript/9RouterHooks/types/helpers/ItemHelper.d.ts index f58ca4d..5920d8a 100644 --- a/TypeScript/9RouterHooks/types/helpers/ItemHelper.d.ts +++ b/TypeScript/9RouterHooks/types/helpers/ItemHelper.d.ts @@ -225,6 +225,48 @@ declare class ItemHelper { * @returns true if item is flagged as quest item */ isQuestItem(tpl: string): boolean; + /** + * Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the + * parent items existence in the database, the existence (and value) of the items RaidModdable property, and that + * the parents slot-required property exists, matches that of the item, and it's value. + * + * Note: this function does not preform any checks to see if the item and parent are *actually* related. + * + * @param item The item to be checked + * @param parent The parent of the item to be checked + * @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. + */ + isRaidModdable(item: Item, parent: Item): boolean | null; + /** + * Retrieves the main parent item for a given attachment item. + * + * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent + * item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it + * will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately + * attached to, even if that gun is located within multiple containers. + * + * It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items + * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates + * some of the performance concerns, as it allows for quick lookups of items by ID. + * + * To generate the map: + * ``` + * const itemsMap = new Map(); + * items.forEach(item => itemsMap.set(item._id, item)); + * ``` + * + * @param itemId - The unique identifier of the item for which to find the main parent. + * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. + * @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. + */ + getAttachmentMainParent(itemId: string, itemsMap: Map): Item | null; + /** + * Determines if an item is an attachment that is currently attached to it's parent item. + * + * @param item The item to check. + * @returns true if the item is attached attachment, otherwise false. + */ + isAttachmentAttached(item: Item): boolean; /** * Get the inventory size of an item * @param items Item with children @@ -303,6 +345,7 @@ declare class ItemHelper { * @returns Name of item */ getItemName(itemTpl: string): string; + getItemTplsOfBaseType(desiredBaseType: string): string[]; } declare namespace ItemHelper { interface ItemSize { diff --git a/TypeScript/9RouterHooks/types/helpers/RepeatableQuestHelper.d.ts b/TypeScript/9RouterHooks/types/helpers/RepeatableQuestHelper.d.ts new file mode 100644 index 0000000..08ae8aa --- /dev/null +++ b/TypeScript/9RouterHooks/types/helpers/RepeatableQuestHelper.d.ts @@ -0,0 +1,20 @@ +import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "../models/spt/config/IQuestConfig"; +import { ConfigServer } from "../servers/ConfigServer"; +import { JsonUtil } from "../utils/JsonUtil"; +import { MathUtil } from "../utils/MathUtil"; +import { ProbabilityObject, ProbabilityObjectArray } from "../utils/RandomUtil"; +export declare class RepeatableQuestHelper { + protected mathUtil: MathUtil; + protected jsonUtil: JsonUtil; + protected configServer: ConfigServer; + protected questConfig: IQuestConfig; + constructor(mathUtil: MathUtil, jsonUtil: JsonUtil, configServer: ConfigServer); + /** + * Get the relevant elimination config based on the current players PMC level + * @param pmcLevel Level of PMC character + * @param repeatableConfig Main repeatable config + * @returns IEliminationConfig + */ + getEliminationConfigByPmcLevel(pmcLevel: number, repeatableConfig: IRepeatableQuestConfig): IEliminationConfig; + probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray; +} diff --git a/TypeScript/9RouterHooks/types/loaders/PreAkiModLoader.d.ts b/TypeScript/9RouterHooks/types/loaders/PreAkiModLoader.d.ts index a1664e1..c0868b7 100644 --- a/TypeScript/9RouterHooks/types/loaders/PreAkiModLoader.d.ts +++ b/TypeScript/9RouterHooks/types/loaders/PreAkiModLoader.d.ts @@ -1,4 +1,5 @@ import { DependencyContainer } from "tsyringe"; +import { ModDetails } from "../models/eft/profile/IAkiProfile"; import { ICoreConfig } from "../models/spt/config/ICoreConfig"; import { IModLoader } from "../models/spt/mod/IModLoader"; import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData"; @@ -35,6 +36,7 @@ export declare class PreAkiModLoader implements IModLoader { */ getImportedModsNames(): string[]; getImportedModDetails(): Record; + getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[]; getModPath(mod: string): string; protected importMods(): Promise; protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number; @@ -64,6 +66,10 @@ export declare class PreAkiModLoader implements IModLoader { protected isModCombatibleWithAki(mod: IPackageJsonData): boolean; protected executeMods(container: DependencyContainer): Promise; sortModsLoadOrder(): string[]; + /** + * Compile mod and add into class property "imported" + * @param mod Name of mod to compile/add + */ protected addMod(mod: string): Promise; protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void; protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record): boolean; diff --git a/TypeScript/9RouterHooks/types/models/eft/common/tables/IRepeatableQuests.d.ts b/TypeScript/9RouterHooks/types/models/eft/common/tables/IRepeatableQuests.d.ts index 3a33f2e..a65f025 100644 --- a/TypeScript/9RouterHooks/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/TypeScript/9RouterHooks/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -161,6 +161,8 @@ export interface ICompletionAvailableForProps extends IAvailableForProps { } export interface ILocationConditionProps extends IConditionProps { target: string[]; + weapon?: string[]; + weaponCategories?: string[]; } export interface IKillConditionProps extends IConditionProps { target: string; @@ -168,6 +170,8 @@ export interface IKillConditionProps extends IConditionProps { savageRole?: string[]; bodyPart?: string[]; distance?: IDistanceCheck; + weapon?: string[]; + weaponCategories?: string[]; } export interface IDistanceCheck { compareMethod: string; diff --git a/TypeScript/9RouterHooks/types/models/external/HttpFramework.d.ts b/TypeScript/9RouterHooks/types/models/external/HttpFramework.d.ts index 64a37d6..fda8732 100644 --- a/TypeScript/9RouterHooks/types/models/external/HttpFramework.d.ts +++ b/TypeScript/9RouterHooks/types/models/external/HttpFramework.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; /** * Associates handlers, HTTP methods and a base url to a listener using a proxy diff --git a/TypeScript/9RouterHooks/types/models/spt/config/IAirdropConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/IAirdropConfig.d.ts index 21bb32e..8c23ed8 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/IAirdropConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/IAirdropConfig.d.ts @@ -52,4 +52,6 @@ export interface AirdropLoot { itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ armorLevelWhitelist?: number[]; + /** Should boss items be added to airdrop crate */ + allowBossItems: boolean; } diff --git a/TypeScript/9RouterHooks/types/models/spt/config/IInRaidConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/IInRaidConfig.d.ts index 3d3b1a2..cf30967 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/IInRaidConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/IInRaidConfig.d.ts @@ -8,6 +8,8 @@ export interface IInRaidConfig extends IBaseConfig { save: Save; /** Names of car extracts */ carExtracts: string[]; + /** Names of coop extracts */ + coopExtracts: string[]; /** Fene rep gain from a single car extract */ carExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ diff --git a/TypeScript/9RouterHooks/types/models/spt/config/IInventoryConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/IInventoryConfig.d.ts index 6657a1a..e026923 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/IInventoryConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/IInventoryConfig.d.ts @@ -23,4 +23,5 @@ export interface ISealedAirdropContainerSettings { weaponModRewardLimits: Record; rewardTypeLimits: Record; ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/TypeScript/9RouterHooks/types/models/spt/config/IItemConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/IItemConfig.d.ts index 5ecccc2..e08108d 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/IItemConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/IItemConfig.d.ts @@ -1,5 +1,8 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IItemConfig extends IBaseConfig { kind: "aki-item"; + /** Items that should be globally blacklisted */ blacklist: string[]; + /** Items that can only be found on bosses */ + bossItems: string[]; } diff --git a/TypeScript/9RouterHooks/types/models/spt/config/IQuestConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/IQuestConfig.d.ts index 8ce461b..0e793ad 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/IQuestConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/IQuestConfig.d.ts @@ -92,6 +92,12 @@ export interface IEliminationConfig { minDist: number; maxKills: number; minKills: number; + minBossKills: number; + maxBossKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } export interface ITarget extends IProbabilityObject { data: IBossInfo; @@ -102,6 +108,9 @@ export interface IBossInfo { export interface IBodyPart extends IProbabilityObject { data: string[]; } +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; +} export interface IProbabilityObject { key: string; relativeProbability: number; diff --git a/TypeScript/9RouterHooks/types/models/spt/config/IRepairConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/IRepairConfig.d.ts index b6db332..e95afa3 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/IRepairConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/IRepairConfig.d.ts @@ -6,8 +6,19 @@ export interface IRepairConfig extends IBaseConfig { applyRandomizeDurabilityLoss: boolean; weaponSkillRepairGain: number; armorKitSkillPointGainPerRepairPointMultiplier: number; + /** INT gain multiplier per repaired item type */ + repairKitIntellectGainMultiplier: IIntellectGainValues; + maxIntellectGainPerRepair: IMaxIntellectGainValues; repairKit: RepairKit; } +export interface IIntellectGainValues { + weapon: number; + armor: number; +} +export interface IMaxIntellectGainValues { + kit: number; + trader: number; +} export interface RepairKit { armor: BonusSettings; weapon: BonusSettings; diff --git a/TypeScript/9RouterHooks/types/models/spt/config/IScavCaseConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/IScavCaseConfig.d.ts index 86a8df3..84403d6 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/IScavCaseConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/IScavCaseConfig.d.ts @@ -9,6 +9,7 @@ export interface IScavCaseConfig extends IBaseConfig { rewardItemBlacklist: string[]; allowMultipleMoneyRewardsPerRarity: boolean; allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } export interface MoneyRewards { moneyRewardChancePercent: number; diff --git a/TypeScript/9RouterHooks/types/models/spt/config/ITraderConfig.d.ts b/TypeScript/9RouterHooks/types/models/spt/config/ITraderConfig.d.ts index 85adf73..e44d715 100644 --- a/TypeScript/9RouterHooks/types/models/spt/config/ITraderConfig.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/config/ITraderConfig.d.ts @@ -1,4 +1,5 @@ import { MinMax } from "../../../models/common/MinMax"; +import { LootRequest } from "../services/LootRequest"; import { IBaseConfig } from "./IBaseConfig"; export interface ITraderConfig extends IBaseConfig { kind: "aki-trader"; @@ -35,6 +36,12 @@ export interface FenceConfig { /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; blacklist: string[]; + coopExtractGift: CoopExtractReward; +} +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } export interface DiscountOptions { assortSize: number; diff --git a/TypeScript/9RouterHooks/types/models/spt/mod/IPackageJsonData.d.ts b/TypeScript/9RouterHooks/types/models/spt/mod/IPackageJsonData.d.ts index 06f7454..f58d7cc 100644 --- a/TypeScript/9RouterHooks/types/models/spt/mod/IPackageJsonData.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/mod/IPackageJsonData.d.ts @@ -6,6 +6,9 @@ export interface IPackageJsonData { author: string; version: string; akiVersion: string; + /** We deliberately purge this data */ + scripts: Record; + devDependencies: Record; licence: string; main: string; isBundleMod: boolean; diff --git a/TypeScript/9RouterHooks/types/models/spt/repeatable/IQuestTypePool.d.ts b/TypeScript/9RouterHooks/types/models/spt/repeatable/IQuestTypePool.d.ts new file mode 100644 index 0000000..24cf08b --- /dev/null +++ b/TypeScript/9RouterHooks/types/models/spt/repeatable/IQuestTypePool.d.ts @@ -0,0 +1,31 @@ +import { ELocationName } from "../../../models/enums/ELocationName"; +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; +} +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; +} +export interface IExplorationPool { + locations: Partial>; +} +export interface IEliminationPool { + targets: IEliminationTargetPool; +} +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; +} +export interface ITargetLocation { + locations: string[]; +} diff --git a/TypeScript/9RouterHooks/types/models/spt/services/LootRequest.d.ts b/TypeScript/9RouterHooks/types/models/spt/services/LootRequest.d.ts index 044935d..4dc3111 100644 --- a/TypeScript/9RouterHooks/types/models/spt/services/LootRequest.d.ts +++ b/TypeScript/9RouterHooks/types/models/spt/services/LootRequest.d.ts @@ -9,4 +9,5 @@ export interface LootRequest { itemLimits: Record; itemStackLimits: Record; armorLevelWhitelist: number[]; + allowBossItems: boolean; } diff --git a/TypeScript/9RouterHooks/types/routers/EventOutputHolder.d.ts b/TypeScript/9RouterHooks/types/routers/EventOutputHolder.d.ts index 1966741..ab780aa 100644 --- a/TypeScript/9RouterHooks/types/routers/EventOutputHolder.d.ts +++ b/TypeScript/9RouterHooks/types/routers/EventOutputHolder.d.ts @@ -29,7 +29,7 @@ export declare class EventOutputHolder { /** * Convert the internal trader data object into an object we can send to the client * @param traderData server data for traders - * @returns + * @returns dict of trader id + TraderData */ protected constructTraderRelations(traderData: Record): Record; /** diff --git a/TypeScript/9RouterHooks/types/routers/HttpRouter.d.ts b/TypeScript/9RouterHooks/types/routers/HttpRouter.d.ts index f75a47d..46f847a 100644 --- a/TypeScript/9RouterHooks/types/routers/HttpRouter.d.ts +++ b/TypeScript/9RouterHooks/types/routers/HttpRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage } from "http"; +import { IncomingMessage } from "node:http"; import { DynamicRouter, Router, StaticRouter } from "../di/Router"; export declare class HttpRouter { protected staticRouters: StaticRouter[]; diff --git a/TypeScript/9RouterHooks/types/routers/ImageRouter.d.ts b/TypeScript/9RouterHooks/types/routers/ImageRouter.d.ts index 675441c..fd03c59 100644 --- a/TypeScript/9RouterHooks/types/routers/ImageRouter.d.ts +++ b/TypeScript/9RouterHooks/types/routers/ImageRouter.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { ImageRouteService } from "../services/mod/image/ImageRouteService"; import { HttpFileUtil } from "../utils/HttpFileUtil"; import { VFS } from "../utils/VFS"; diff --git a/TypeScript/9RouterHooks/types/routers/serializers/BundleSerializer.d.ts b/TypeScript/9RouterHooks/types/routers/serializers/BundleSerializer.d.ts index ca4d8b6..db41142 100644 --- a/TypeScript/9RouterHooks/types/routers/serializers/BundleSerializer.d.ts +++ b/TypeScript/9RouterHooks/types/routers/serializers/BundleSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { BundleLoader } from "../../loaders/BundleLoader"; import { ILogger } from "../../models/spt/utils/ILogger"; diff --git a/TypeScript/9RouterHooks/types/routers/serializers/ImageSerializer.d.ts b/TypeScript/9RouterHooks/types/routers/serializers/ImageSerializer.d.ts index 5de48ff..62ce84d 100644 --- a/TypeScript/9RouterHooks/types/routers/serializers/ImageSerializer.d.ts +++ b/TypeScript/9RouterHooks/types/routers/serializers/ImageSerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ImageRouter } from "../ImageRouter"; export declare class ImageSerializer extends Serializer { diff --git a/TypeScript/9RouterHooks/types/routers/serializers/NotifySerializer.d.ts b/TypeScript/9RouterHooks/types/routers/serializers/NotifySerializer.d.ts index 1d179b2..e92d6e1 100644 --- a/TypeScript/9RouterHooks/types/routers/serializers/NotifySerializer.d.ts +++ b/TypeScript/9RouterHooks/types/routers/serializers/NotifySerializer.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { NotifierController } from "../../controllers/NotifierController"; import { Serializer } from "../../di/Serializer"; import { HttpServerHelper } from "../../helpers/HttpServerHelper"; diff --git a/TypeScript/9RouterHooks/types/servers/HttpServer.d.ts b/TypeScript/9RouterHooks/types/servers/HttpServer.d.ts index 97e0705..c73eb3c 100644 --- a/TypeScript/9RouterHooks/types/servers/HttpServer.d.ts +++ b/TypeScript/9RouterHooks/types/servers/HttpServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage, ServerResponse } from "http"; +import http, { IncomingMessage, ServerResponse } from "node:http"; import { ApplicationContext } from "../context/ApplicationContext"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { IHttpConfig } from "../models/spt/config/IHttpConfig"; diff --git a/TypeScript/9RouterHooks/types/servers/WebSocketServer.d.ts b/TypeScript/9RouterHooks/types/servers/WebSocketServer.d.ts index fffbea2..b4c6158 100644 --- a/TypeScript/9RouterHooks/types/servers/WebSocketServer.d.ts +++ b/TypeScript/9RouterHooks/types/servers/WebSocketServer.d.ts @@ -1,5 +1,5 @@ /// -import http, { IncomingMessage } from "http"; +import http, { IncomingMessage } from "node:http"; import WebSocket from "ws"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; import { INotification } from "../models/eft/notifier/INotifier"; diff --git a/TypeScript/9RouterHooks/types/servers/http/AkiHttpListener.d.ts b/TypeScript/9RouterHooks/types/servers/http/AkiHttpListener.d.ts index c72e18f..e4ac80c 100644 --- a/TypeScript/9RouterHooks/types/servers/http/AkiHttpListener.d.ts +++ b/TypeScript/9RouterHooks/types/servers/http/AkiHttpListener.d.ts @@ -1,6 +1,6 @@ /// /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { Serializer } from "../../di/Serializer"; import { ILogger } from "../../models/spt/utils/ILogger"; import { HttpRouter } from "../../routers/HttpRouter"; diff --git a/TypeScript/9RouterHooks/types/servers/http/IHttpListener.d.ts b/TypeScript/9RouterHooks/types/servers/http/IHttpListener.d.ts index 758bb5a..29d5fce 100644 --- a/TypeScript/9RouterHooks/types/servers/http/IHttpListener.d.ts +++ b/TypeScript/9RouterHooks/types/servers/http/IHttpListener.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; export interface IHttpListener { canHandle(sessionId: string, req: IncomingMessage): boolean; handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void; diff --git a/TypeScript/9RouterHooks/types/services/ItemFilterService.d.ts b/TypeScript/9RouterHooks/types/services/ItemFilterService.d.ts index b830d74..62f4f61 100644 --- a/TypeScript/9RouterHooks/types/services/ItemFilterService.d.ts +++ b/TypeScript/9RouterHooks/types/services/ItemFilterService.d.ts @@ -7,7 +7,6 @@ export declare class ItemFilterService { protected logger: ILogger; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; - protected blacklist: string[]; protected itemConfig: IItemConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, configServer: ConfigServer); /** @@ -21,4 +20,15 @@ export declare class ItemFilterService { * @returns string array of blacklisted tempalte ids */ getBlacklistedItems(): string[]; + /** + * Check if the provided template id is boss item in config/item.json + * @param tpl template id + * @returns true if boss item + */ + isBossItem(tpl: string): boolean; + /** + * Return boss items in config/item.json + * @returns string array of boss item tempalte ids + */ + getBossItems(): string[]; } diff --git a/TypeScript/9RouterHooks/types/services/ProfileFixerService.d.ts b/TypeScript/9RouterHooks/types/services/ProfileFixerService.d.ts index bc1e42e..cd6a87a 100644 --- a/TypeScript/9RouterHooks/types/services/ProfileFixerService.d.ts +++ b/TypeScript/9RouterHooks/types/services/ProfileFixerService.d.ts @@ -14,6 +14,7 @@ import { IRagfairConfig } from "../models/spt/config/IRagfairConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { Watermark } from "../utils/Watermark"; @@ -29,11 +30,12 @@ export declare class ProfileFixerService { protected localisationService: LocalisationService; protected timeUtil: TimeUtil; protected jsonUtil: JsonUtil; + protected hashUtil: HashUtil; protected databaseServer: DatabaseServer; protected configServer: ConfigServer; protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; - constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer, configServer: ConfigServer); + constructor(logger: ILogger, watermark: Watermark, hideoutHelper: HideoutHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, profileHelper: ProfileHelper, itemHelper: ItemHelper, localisationService: LocalisationService, timeUtil: TimeUtil, jsonUtil: JsonUtil, hashUtil: HashUtil, databaseServer: DatabaseServer, configServer: ConfigServer); /** * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix @@ -129,6 +131,17 @@ export declare class ProfileFixerService { * @param pmcProfile Profile to update */ removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void; + /** + * 3.7.0 moved AIDs to be numeric, old profiles need to be migrated + * We store the old AID value in new field `sessionId` + * @param fullProfile Profile to update + */ + fixIncorrectAidValue(fullProfile: IAkiProfile): void; + /** + * Bsg nested `stats` into a sub object called 'eft' + * @param fullProfile Profile to check for and migrate stats data + */ + migrateStatsToNewStructure(fullProfile: IAkiProfile): void; /** * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to @@ -136,7 +149,7 @@ export declare class ProfileFixerService { addMissingIdsToBonuses(pmcProfile: IPmcData): void; /** * At some point the property name was changed,migrate data across to new name - * @param pmcProfile + * @param pmcProfile Profile to migrate improvements in */ protected migrateImprovements(pmcProfile: IPmcData): void; } diff --git a/TypeScript/9RouterHooks/types/services/SeasonalEventService.d.ts b/TypeScript/9RouterHooks/types/services/SeasonalEventService.d.ts index 9fb3454..73d3b84 100644 --- a/TypeScript/9RouterHooks/types/services/SeasonalEventService.d.ts +++ b/TypeScript/9RouterHooks/types/services/SeasonalEventService.d.ts @@ -24,6 +24,8 @@ export declare class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; + protected halloweenEventActive: any; + protected christmasEventActive: any; constructor(logger: ILogger, databaseServer: DatabaseServer, databaseImporter: DatabaseImporter, giftService: GiftService, localisationService: LocalisationService, botHelper: BotHelper, profileHelper: ProfileHelper, configServer: ConfigServer); protected get christmasEventItems(): string[]; protected get halloweenEventItems(): string[]; @@ -51,23 +53,18 @@ export declare class SeasonalEventService { * @returns array of tpl strings */ getAllSeasonalEventItems(): string[]; - /** - * Get an array of seasonal items that should be blocked as season is not currently active - * @returns Array of tpl strings - */ - getSeasonalEventItemsToBlock(): string[]; /** * Is a seasonal event currently active * @returns true if event is active */ seasonalEventEnabled(): boolean; /** - * Is christmas event active (Globals eventtype array contains even name) + * Is christmas event active * @returns true if active */ christmasEventEnabled(): boolean; /** - * is halloween event active (Globals eventtype array contains even name) + * is halloween event active * @returns true if active */ halloweenEventEnabled(): boolean; @@ -95,10 +92,11 @@ export declare class SeasonalEventService { */ isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean; /** - * Check if current date falls inside any of the seasons events pased in, if so, handle them + * Handle seasonal events * @param sessionId Players id */ - checkForAndEnableSeasonalEvents(sessionId: string): void; + enableSeasonalEvents(sessionId: string): void; + protected cacheActiveEvents(): void; /** * Iterate through bots inventory and loot to find and remove christmas items (as defined in SeasonalEventService) * @param nodeInventory Bots inventory to iterate over diff --git a/TypeScript/9RouterHooks/types/services/mod/httpListener/HttpListenerMod.d.ts b/TypeScript/9RouterHooks/types/services/mod/httpListener/HttpListenerMod.d.ts index 2cdfbda..afe4574 100644 --- a/TypeScript/9RouterHooks/types/services/mod/httpListener/HttpListenerMod.d.ts +++ b/TypeScript/9RouterHooks/types/services/mod/httpListener/HttpListenerMod.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "../../../servers/http/IHttpListener"; export declare class HttpListenerMod implements IHttpListener { private canHandleOverride; diff --git a/TypeScript/9RouterHooks/types/services/mod/httpListener/HttpListenerModService.d.ts b/TypeScript/9RouterHooks/types/services/mod/httpListener/HttpListenerModService.d.ts index 9dd3473..23abfbe 100644 --- a/TypeScript/9RouterHooks/types/services/mod/httpListener/HttpListenerModService.d.ts +++ b/TypeScript/9RouterHooks/types/services/mod/httpListener/HttpListenerModService.d.ts @@ -1,5 +1,5 @@ /// -import { IncomingMessage, ServerResponse } from "http"; +import { IncomingMessage, ServerResponse } from "node:http"; import { DependencyContainer } from "tsyringe"; export declare class HttpListenerModService { protected container: DependencyContainer; diff --git a/TypeScript/9RouterHooks/types/utils/App.d.ts b/TypeScript/9RouterHooks/types/utils/App.d.ts index dd8f24c..5e759ad 100644 --- a/TypeScript/9RouterHooks/types/utils/App.d.ts +++ b/TypeScript/9RouterHooks/types/utils/App.d.ts @@ -12,7 +12,6 @@ export declare class App { protected onLoadComponents: OnLoad[]; protected onUpdateComponents: OnUpdate[]; protected onUpdateLastRun: {}; - protected os: any; constructor(logger: ILogger, timeUtil: TimeUtil, localisationService: LocalisationService, encodingUtil: EncodingUtil, onLoadComponents: OnLoad[], onUpdateComponents: OnUpdate[]); load(): Promise; protected update(onUpdateComponents: OnUpdate[]): Promise; diff --git a/TypeScript/9RouterHooks/types/utils/HashUtil.d.ts b/TypeScript/9RouterHooks/types/utils/HashUtil.d.ts index c017ca8..27204cb 100644 --- a/TypeScript/9RouterHooks/types/utils/HashUtil.d.ts +++ b/TypeScript/9RouterHooks/types/utils/HashUtil.d.ts @@ -1,5 +1,5 @@ /// -import crypto from "crypto"; +import crypto from "node:crypto"; import { TimeUtil } from "./TimeUtil"; export declare class HashUtil { protected timeUtil: TimeUtil; diff --git a/TypeScript/9RouterHooks/types/utils/HttpFileUtil.d.ts b/TypeScript/9RouterHooks/types/utils/HttpFileUtil.d.ts index afc8409..6a386ce 100644 --- a/TypeScript/9RouterHooks/types/utils/HttpFileUtil.d.ts +++ b/TypeScript/9RouterHooks/types/utils/HttpFileUtil.d.ts @@ -1,5 +1,5 @@ /// -import { ServerResponse } from "http"; +import { ServerResponse } from "node:http"; import { HttpServerHelper } from "../helpers/HttpServerHelper"; export declare class HttpFileUtil { protected httpServerHelper: HttpServerHelper; diff --git a/TypeScript/9RouterHooks/types/utils/VFS.d.ts b/TypeScript/9RouterHooks/types/utils/VFS.d.ts index 2cb09fa..3911c4b 100644 --- a/TypeScript/9RouterHooks/types/utils/VFS.d.ts +++ b/TypeScript/9RouterHooks/types/utils/VFS.d.ts @@ -1,6 +1,6 @@ /// /// -import fs from "fs"; +import fs from "node:fs"; import "reflect-metadata"; import { IAsyncQueue } from "../models/spt/utils/IAsyncQueue"; import { IUUidGenerator } from "../models/spt/utils/IUuidGenerator"; diff --git a/TypeScript/9RouterHooks/types/utils/Watermark.d.ts b/TypeScript/9RouterHooks/types/utils/Watermark.d.ts index fa63205..864e9b6 100644 --- a/TypeScript/9RouterHooks/types/utils/Watermark.d.ts +++ b/TypeScript/9RouterHooks/types/utils/Watermark.d.ts @@ -4,12 +4,10 @@ import { ConfigServer } from "../servers/ConfigServer"; import { LocalisationService } from "../services/LocalisationService"; export declare class WatermarkLocale { protected localisationService: LocalisationService; + protected description: string[]; + protected warning: string[]; + protected modding: string[]; constructor(localisationService: LocalisationService); - protected watermark: { - description: string[]; - warning: string[]; - modding: string[]; - }; getDescription(): string[]; getWarning(): string[]; getModding(): string[]; diff --git a/TypeScript/9RouterHooks/types/utils/logging/AbstractWinstonLogger.d.ts b/TypeScript/9RouterHooks/types/utils/logging/AbstractWinstonLogger.d.ts index 1ae1100..74767a2 100644 --- a/TypeScript/9RouterHooks/types/utils/logging/AbstractWinstonLogger.d.ts +++ b/TypeScript/9RouterHooks/types/utils/logging/AbstractWinstonLogger.d.ts @@ -1,5 +1,5 @@ /// -import fs from "fs"; +import fs from "node:fs"; import winston from "winston"; import { Daum } from "../../models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "../../models/spt/logging/LogBackgroundColor";