Update to 3.9.0

This commit is contained in:
Dev 2024-07-06 21:46:01 +01:00
parent d187862220
commit 425cd38446
2845 changed files with 13579 additions and 37292 deletions

View File

@ -1,6 +1,6 @@
# Welcome to the SPT Modding Project
# Welcome to the SPT-AKI Modding Project
This project is designed to streamline the initial setup process for building and creating mods in the SPT environment. Follow this guide to set up your environment efficiently.
This project is designed to streamline the initial setup process for building and creating mods in the SPT-AKI environment. Follow this guide to set up your environment efficiently.
## **Table of Contents**
- [NodeJS Setup](#nodejs-setup)
@ -39,7 +39,7 @@ Note: Preserve the `node_modules` folder as it contains necessary dependencies f
## **Essential Concepts**
Prioritize understanding Dependency Injection and Inversion of Control, the architectural principles SPT adopts. Comprehensive guidelines will be available on the hub upon release.
Prioritize understanding Dependency Injection and Inversion of Control, the architectural principles SPT-AKI adopts. Comprehensive guidelines will be available on the hub upon release.
Some resources to get you started:
- [A quick intro to Dependency Injection](https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f/)
@ -47,13 +47,13 @@ Some resources to get you started:
## **Coding Guidelines**
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"sptVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"akiVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
## **Distribution Guidelines**
Automated tasks are set up to bundle all necessary files for your mod to function in SPT:
Automated tasks are set up to bundle all necessary files for your mod to function in SPT-AKI:
> Terminal -> Run Task... -> Show All Tasks... -> npm: build
@ -61,6 +61,6 @@ The ZIP output, located in the `dist` directory, contains all required files. En
## **Conclusion**
With this setup, you're ready to begin modding with SPT. If you run into any trouble be sure to check out the [modding documentation on the hub](https://hub.sp-tarkov.com/doc/lexicon/66-modding/). If you really get stuck feel free to join us in the [#mods-development](https://discord.com/channels/875684761291599922/875803116409323562) official Discord channel.
With this setup, you're ready to begin modding with SPT-AKI. If you run into any trouble be sure to check out the [modding documentation on the hub](https://hub.sp-tarkov.com/doc/lexicon/66-modding/). If you really get stuck feel free to join us in the [#mods-development](https://discord.com/channels/875684761291599922/875803116409323562) official Discord channel.
Build something awesome!

View File

@ -1,7 +1,7 @@
{
"name": "ScopesAndTypes",
"version": "1.0.0",
"sptVersion": "~3.9",
"akiVersion": "~3.9",
"loadBefore": [],
"loadAfter": [],
"incompatibilities": [],

View File

@ -1,6 +1,6 @@
import { inject, injectable } from "tsyringe";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { Processing } from "./Processing";
@injectable()

View File

@ -1,6 +1,6 @@
import { inject, injectable } from "tsyringe";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
@injectable()
export class Processing

View File

@ -1,15 +1,15 @@
import { DependencyContainer, Lifecycle } from "tsyringe";
import { IPreSptLoadMod } from "@spt/models/external/IPreSptLoadMod";
import { IPostSptLoadMod } from "@spt/models/external/IPostSptLoadMod";
import { IPreAkiLoadMod } from "@spt-aki/models/external/IPreAkiLoadMod";
import { IPostAkiLoadMod } from "@spt-aki/models/external/IPostAkiLoadMod";
import { MyMod } from "./MyMod";
import { Processing } from "./Processing";
class Mod implements IPreSptLoadMod, IPostSptLoadMod
class Mod implements IPreAkiLoadMod, IPostAkiLoadMod
{
// Perform these actions before server fully loads
public preSptLoad(container: DependencyContainer): void {
public preAkiLoad(container: DependencyContainer): void {
// This class is registered as a singleton. This means ONE and only ONE bean
// of this class will ever exist.
container.register<MyMod>("MyMod", MyMod, {lifecycle: Lifecycle.Singleton});
@ -19,7 +19,7 @@ class Mod implements IPreSptLoadMod, IPostSptLoadMod
container.register<Processing>("Processing", Processing);
}
public postSptLoad(container: DependencyContainer): void
public postAkiLoad(container: DependencyContainer): void
{
// We will run this in a quick 5 loop to show how singletons and transients work
for (let i = 0; i < 5; i++)

View File

@ -11,7 +11,7 @@
"resolveJsonModule": true,
"outDir": "tmp",
"paths": {
"@spt/*": ["./types/*"],
"@spt-aki/*": ["./types/*"],
},
},
"exclude": ["node_modules", "dist", "tmp"],

View File

@ -59,4 +59,5 @@ export declare class InraidCallbacks {
itemDelivery(url: string, request: IItemDeliveryRequestData, sessionId: string): INullResponseData;
getTraitorScavHostileChance(url: string, info: IEmptyRequestData, sessionId: string): string;
getSandboxMaxPatrolValue(url: string, info: IEmptyRequestData, sessionId: string): string;
getBossConvertSettings(url: string, info: IEmptyRequestData, sessionId: string): string;
}

View File

@ -3,6 +3,7 @@ import { BotGenerator } from "@spt/generators/BotGenerator";
import { BotDifficultyHelper } from "@spt/helpers/BotDifficultyHelper";
import { BotHelper } from "@spt/helpers/BotHelper";
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper";
import { MinMax } from "@spt/models/common/MinMax";
import { Condition, IGenerateBotsRequestData } from "@spt/models/eft/bot/IGenerateBotsRequestData";
import { IPmcData } from "@spt/models/eft/common/IPmcData";
@ -27,6 +28,7 @@ export declare class BotController {
protected botGenerator: BotGenerator;
protected botHelper: BotHelper;
protected botDifficultyHelper: BotDifficultyHelper;
protected weightedRandomHelper: WeightedRandomHelper;
protected botGenerationCacheService: BotGenerationCacheService;
protected matchBotDetailsCacheService: MatchBotDetailsCacheService;
protected localisationService: LocalisationService;
@ -38,7 +40,7 @@ export declare class BotController {
protected cloner: ICloner;
protected botConfig: IBotConfig;
protected pmcConfig: IPmcConfig;
constructor(logger: ILogger, databaseService: DatabaseService, botGenerator: BotGenerator, botHelper: BotHelper, botDifficultyHelper: BotDifficultyHelper, botGenerationCacheService: BotGenerationCacheService, matchBotDetailsCacheService: MatchBotDetailsCacheService, localisationService: LocalisationService, seasonalEventService: SeasonalEventService, profileHelper: ProfileHelper, configServer: ConfigServer, applicationContext: ApplicationContext, randomUtil: RandomUtil, cloner: ICloner);
constructor(logger: ILogger, databaseService: DatabaseService, botGenerator: BotGenerator, botHelper: BotHelper, botDifficultyHelper: BotDifficultyHelper, weightedRandomHelper: WeightedRandomHelper, botGenerationCacheService: BotGenerationCacheService, matchBotDetailsCacheService: MatchBotDetailsCacheService, localisationService: LocalisationService, seasonalEventService: SeasonalEventService, profileHelper: ProfileHelper, configServer: ConfigServer, applicationContext: ApplicationContext, randomUtil: RandomUtil, cloner: ICloner);
/**
* Return the number of bot load-out varieties to be generated
* @param type bot Type we want the load-out gen count for
@ -116,6 +118,7 @@ export declare class BotController {
* @returns Single IBotBase object
*/
protected returnSingleBotFromCache(sessionId: string, request: IGenerateBotsRequestData): Promise<IBotBase[]>;
protected updateBotGenerationDetailsToRandomBoss(botGenerationDetails: BotGenerationDetails, possibleBossTypeWeights: Record<string, number>): void;
/**
* Get the difficulty passed in, if its not "asonline", get selected difficulty from config
* @param requestedDifficulty

View File

@ -31,6 +31,7 @@ import { PmcChatResponseService } from "@spt/services/PmcChatResponseService";
import { TraderServicesService } from "@spt/services/TraderServicesService";
import { RandomUtil } from "@spt/utils/RandomUtil";
import { TimeUtil } from "@spt/utils/TimeUtil";
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
/**
* Logic for handling In Raid callbacks
*/
@ -62,6 +63,7 @@ export declare class InraidController {
protected locationConfig: ILocationConfig;
protected ragfairConfig: IRagfairConfig;
protected hideoutConfig: IHideoutConfig;
protected botConfig: IBotConfig;
constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, databaseService: DatabaseService, pmcChatResponseService: PmcChatResponseService, matchBotDetailsCacheService: MatchBotDetailsCacheService, questHelper: QuestHelper, itemHelper: ItemHelper, profileHelper: ProfileHelper, playerScavGenerator: PlayerScavGenerator, healthHelper: HealthHelper, traderHelper: TraderHelper, traderServicesService: TraderServicesService, localisationService: LocalisationService, insuranceService: InsuranceService, inRaidHelper: InRaidHelper, applicationContext: ApplicationContext, configServer: ConfigServer, mailSendService: MailSendService, randomUtil: RandomUtil);
/**
* Save locationId to active profiles inraid object AND app context
@ -189,4 +191,5 @@ export declare class InraidController {
itemDelivery(sessionId: string, traderId: string, items: Item[]): void;
getTraitorScavHostileChance(url: string, sessionID: string): number;
getSandboxMaxPatrolValue(url: string, sessionID: string): number;
getBossConvertSettings(url: string, sessionId: string): string[];
}

View File

@ -9,6 +9,7 @@ import { ISptProfile } from "@spt/models/eft/profile/ISptProfile";
import { IRepeatableQuestChangeRequest } from "@spt/models/eft/quests/IRepeatableQuestChangeRequest";
import { ELocationName } from "@spt/models/enums/ELocationName";
import { IQuestConfig, IRepeatableQuestConfig } from "@spt/models/spt/config/IQuestConfig";
import { IGetRepeatableByIdResult } from "@spt/models/spt/quests/IGetRepeatableByIdResult";
import { IQuestTypePool } from "@spt/models/spt/repeatable/IQuestTypePool";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { EventOutputHolder } from "@spt/routers/EventOutputHolder";
@ -146,13 +147,21 @@ export declare class RepeatableQuestController {
* @returns IItemEventRouterResponse
*/
changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse;
/**
* Find a repeatable (daily/weekly/scav) from a players profile by its id
* @param questId Id of quest to find
* @param pmcData Profile that contains quests to look through
* @returns IGetRepeatableByIdResult
*/
protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult;
protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest;
/**
* Some accounts have access to repeatable quest refreshes for free
* Some accounts have access to free repeatable quest refreshes
* Track the usage of them inside players profile
* @param fullProfile Profile of player
* @param repeatableSubType Can be daily/weekly/scav repeatables
* @param repeatableTypeName Subtype of repeatables: daily / weekly / scav
* @param fullProfile Player profile
* @param repeatableSubType Can be daily / weekly / scav repeatable
* @param repeatableTypeName Subtype of repeatable quest: daily / weekly / scav
* @returns Is the repeatable being replaced for free
*/
protected handleFreeRefreshUses(fullProfile: ISptProfile, repeatableSubType: IPmcDataRepeatableQuest, repeatableTypeName: string): void;
protected useFreeRefreshIfAvailable(fullProfile: ISptProfile, repeatableSubType: IPmcDataRepeatableQuest, repeatableTypeName: string): boolean;
}

View File

@ -12,6 +12,8 @@ import { Item } from "@spt/models/eft/common/tables/IItem";
import { ITemplateItem, Slot } from "@spt/models/eft/common/tables/ITemplateItem";
import { ModSpawn } from "@spt/models/enums/ModSpawn";
import { IChooseRandomCompatibleModResult } from "@spt/models/spt/bots/IChooseRandomCompatibleModResult";
import { IFilterPlateModsForSlotByLevelResult } from "@spt/models/spt/bots/IFilterPlateModsForSlotByLevelResult";
import { IGenerateEquipmentProperties } from "@spt/models/spt/bots/IGenerateEquipmentProperties";
import { IGenerateWeaponRequest } from "@spt/models/spt/bots/IGenerateWeaponRequest";
import { IModToSpawnRequest } from "@spt/models/spt/bots/IModToSpawnRequest";
import { EquipmentFilterDetails, EquipmentFilters, IBotConfig } from "@spt/models/spt/config/IBotConfig";
@ -26,8 +28,6 @@ import { LocalisationService } from "@spt/services/LocalisationService";
import { ICloner } from "@spt/utils/cloners/ICloner";
import { HashUtil } from "@spt/utils/HashUtil";
import { RandomUtil } from "@spt/utils/RandomUtil";
import { IFilterPlateModsForSlotByLevelResult } from "../models/spt/bots/IFilterPlateModsForSlotByLevelResult";
import { IGenerateEquipmentProperties } from "./BotInventoryGenerator";
export declare class BotEquipmentModGenerator {
protected logger: ILogger;
protected hashUtil: HashUtil;
@ -94,8 +94,19 @@ export declare class BotEquipmentModGenerator {
* @param modSpawnChances Chance dictionary to update
*/
protected adjustSlotSpawnChances(modSpawnChances: ModsChances, modSlotsToAdjust: string[], newChancePercent: number): void;
protected modSlotCanHoldMuzzleDevices(modSlot: string, modsParentId: string): boolean;
protected sortModKeys(unsortedKeys: string[]): string[];
/**
* Does the provided modSlot allow muzzle-related items
* @param modSlot Slot id to check
* @param modsParentId OPTIONAL: parent id of modslot being checked
* @returns True if modSlot can have muzzle-related items
*/
protected modSlotCanHoldMuzzleDevices(modSlot: string, modsParentId?: string): boolean;
/**
* Sort mod slots into an ordering that maximises chance of a successful weapon generation
* @param unsortedSlotKeys Array of mod slot strings to sort
* @returns Sorted array
*/
protected sortModKeys(unsortedSlotKeys: string[]): string[];
/**
* Get a Slot property for an item (chamber/cartridge/slot)
* @param modSlot e.g patron_in_weapon
@ -118,43 +129,53 @@ export declare class BotEquipmentModGenerator {
* @returns itemHelper.getItem() result
*/
protected chooseModToPutIntoSlot(request: IModToSpawnRequest): [boolean, ITemplateItem] | undefined;
protected pickWeaponModTplForSlotFromPool(modPool: string[], parentSlot: Slot, modSpawnResult: ModSpawn, weapon: Item[], modSlotname: string): IChooseRandomCompatibleModResult;
/**
*
* @param modPool Pool of mods that can be picked from
* @param parentSlot Slot the picked mod will have as a parent
* @param choiceTypeEnum How should chosen tpl be treated: DEFAULT_MOD/SPAWN/SKIP
* @param weapon Array of weapon items chosen item will be added to
* @param modSlotName Name of slot picked mod will be placed into
* @returns Chosen weapon details
*/
protected pickWeaponModTplForSlotFromPool(modPool: string[], parentSlot: Slot, choiceTypeEnum: ModSpawn, weapon: Item[], modSlotName: string): IChooseRandomCompatibleModResult;
/**
* Filter mod pool down based on various criteria:
* Is slot flagged as randomisable
* Is slot required
* Is slot flagged as default mod only
* @param itemModPool Existing pool of mods to choose
* @param modSpawnResult outcome of random roll to select if mod should be added
* @param itemSpawnCategory How should slot be handled
* @param parentTemplate Mods parent
* @param weaponTemplate Mods root parent (weapon/equipment)
* @param modSlot name of mod slot to choose for
* @param botEquipBlacklist
* @param isRandomisableSlot is flagged as a randomisable slot
* @returns
* @param botEquipBlacklist A blacklist of items not allowed to be picked
* @param isRandomisableSlot Slot is flagged as a randomisable slot
* @returns Array of mod tpls
*/
protected getModPoolForSlot(itemModPool: Record<string, string[]>, modSpawnResult: ModSpawn, parentTemplate: ITemplateItem, weaponTemplate: ITemplateItem, modSlot: string, botEquipBlacklist: EquipmentFilterDetails, isRandomisableSlot: boolean): string[];
protected getModPoolForSlot(itemModPool: Record<string, string[]>, itemSpawnCategory: ModSpawn, parentTemplate: ITemplateItem, weaponTemplate: ITemplateItem, modSlot: string, botEquipBlacklist: EquipmentFilterDetails, isRandomisableSlot: boolean): string[];
/**
* Get default preset for weapon, get specific weapon presets for edge cases (mp5/silenced dvl)
* @param weaponTemplate
* @param parentItemTpl
* Get default preset for weapon OR get specific weapon presets for edge cases (mp5/silenced dvl)
* @param weaponTemplate Weapons db template
* @param parentItemTpl Tpl of the parent item
* @returns Default preset found
*/
protected getMatchingPreset(weaponTemplate: ITemplateItem, parentItemTpl: string): IPreset | undefined;
/**
* Temp fix to prevent certain combinations of weapons with mods that are known to be incompatible
* @param weapon Weapon
* @param weapon Array of items that make up a weapon
* @param modTpl Mod to check compatibility with weapon
* @returns True if incompatible
*/
protected weaponModComboIsIncompatible(weapon: Item[], modTpl: string): boolean;
/**
* Create a mod item with parameters as properties
* Create a mod item with provided parameters as properties + add upd property
* @param modId _id
* @param modTpl _tpl
* @param parentId parentId
* @param modSlot slotId
* @param modTemplate Used to add additional properties in the upd object
* @param botRole The bots role mod is being created for
* @returns Item object
*/
protected createModItem(modId: string, modTpl: string, parentId: string, modSlot: string, modTemplate: ITemplateItem, botRole: string): Item;
@ -166,43 +187,44 @@ export declare class BotEquipmentModGenerator {
protected getAmmoContainers(): string[];
/**
* Get a random mod from an items compatible mods Filter array
* @param modTpl ???? default value to return if nothing found
* @param parentSlot item mod will go into, used to get compatible items
* @param fallbackModTpl Default value to return if parentSlot Filter is empty
* @param parentSlot Item mod will go into, used to get compatible items
* @param modSlot Slot to get mod to fill
* @param items items to ensure picked mod is compatible with
* @returns item tpl
* @param items Items to ensure picked mod is compatible with
* @returns Item tpl
*/
protected getRandomModTplFromItemDb(modTpl: string, parentSlot: Slot, modSlot: string, items: Item[]): string | undefined;
protected getRandomModTplFromItemDb(fallbackModTpl: string, parentSlot: Slot, modSlot: string, items: Item[]): string | undefined;
/**
* Check if mod exists in db + is for a required slot
* @param modToAdd Db template of mod to check
* @param slotAddedToTemplate Slot object the item will be placed as child into
* @param modSlot Slot the mod will fill
* @param parentTemplate Db template of the mods being added
* @param botRole Bots wildspawntype (assault/pmcBot etc)
* @returns true if valid
* @param botRole Bots wildspawntype (assault/pmcBot/exUsec etc)
* @returns True if valid for slot
*/
protected isModValidForSlot(modToAdd: [boolean, ITemplateItem], slotAddedToTemplate: Slot, modSlot: string, parentTemplate: ITemplateItem, botRole: string): boolean;
/**
* Find mod tpls of a provided type and add to modPool
* @param desiredSlotName slot to look up and add we are adding tpls for (e.g mod_scope)
* @param desiredSlotName Slot to look up and add we are adding tpls for (e.g mod_scope)
* @param modTemplate db object for modItem we get compatible mods from
* @param modPool Pool of mods we are adding to
* @param botEquipBlacklist A blacklist of items that cannot be picked
*/
protected addCompatibleModsForProvidedMod(desiredSlotName: string, modTemplate: ITemplateItem, modPool: Mods, botEquipBlacklist: EquipmentFilterDetails): void;
/**
* Get the possible items that fit a slot
* @param parentItemId item tpl to get compatible items for
* @param modSlot Slot item should fit in
* @param botEquipBlacklist equipment that should not be picked
* @returns array of compatible items for that slot
* @param botEquipBlacklist Equipment that should not be picked
* @returns Array of compatible items for that slot
*/
protected getDynamicModPool(parentItemId: string, modSlot: string, botEquipBlacklist: EquipmentFilterDetails): string[];
/**
* Take a list of tpls and filter out blacklisted values using itemFilterService + botEquipmentBlacklist
* @param allowedMods base mods to filter
* @param botEquipBlacklist equipment blacklist
* @param modSlot slot mods belong to
* @param allowedMods Base mods to filter
* @param botEquipBlacklist Equipment blacklist
* @param modSlot Slot mods belong to
* @returns Filtered array of mod tpls
*/
protected filterWeaponModsByBlacklist(allowedMods: string[], botEquipBlacklist: EquipmentFilterDetails, modSlot: string): string[];
@ -212,17 +234,17 @@ export declare class BotEquipmentModGenerator {
* Ammo is not put into the magazine directly but assigned to the magazine's slots: The "camora_xxx" slots.
* This function is a helper called by generateModsForItem for mods with parent type "CylinderMagazine"
* @param items The items where the CylinderMagazine's camora are appended to
* @param modPool modPool which should include available cartridges
* @param parentId The CylinderMagazine's UID
* @param parentTemplate The CylinderMagazine's template
* @param modPool ModPool which should include available cartridges
* @param cylinderMagParentId The CylinderMagazine's UID
* @param cylinderMagTemplate The CylinderMagazine's template
*/
protected fillCamora(items: Item[], modPool: Mods, parentId: string, parentTemplate: ITemplateItem): void;
protected fillCamora(items: Item[], modPool: Mods, cylinderMagParentId: string, cylinderMagTemplate: ITemplateItem): void;
/**
* Take a record of camoras and merge the compatible shells into one array
* @param camorasWithShells camoras we want to merge into one array
* @returns string array of shells for multiple camora sources
* @param camorasWithShells Dictionary of camoras we want to merge into one array
* @returns String array of shells for multiple camora sources
*/
protected mergeCamoraPoolsTogether(camorasWithShells: Record<string, string[]>): string[];
protected mergeCamoraPools(camorasWithShells: Record<string, string[]>): string[];
/**
* Filter out non-whitelisted weapon scopes
* Controlled by bot.json weaponSightWhitelist

View File

@ -6,9 +6,10 @@ import { BotHelper } from "@spt/helpers/BotHelper";
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper";
import { Inventory as PmcInventory } from "@spt/models/eft/common/tables/IBotBase";
import { Chances, Generation, IBotType, Inventory, Mods } from "@spt/models/eft/common/tables/IBotType";
import { Chances, Equipment, Generation, IBotType, Inventory } from "@spt/models/eft/common/tables/IBotType";
import { EquipmentSlots } from "@spt/models/enums/EquipmentSlots";
import { EquipmentFilterDetails, EquipmentFilters, IBotConfig, RandomisationDetails } from "@spt/models/spt/config/IBotConfig";
import { IGenerateEquipmentProperties } from "@spt/models/spt/bots/IGenerateEquipmentProperties";
import { EquipmentFilterDetails, IBotConfig } from "@spt/models/spt/config/IBotConfig";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
import { BotEquipmentModPoolService } from "@spt/services/BotEquipmentModPoolService";
@ -61,14 +62,14 @@ export declare class BotInventoryGenerator {
protected generateAndAddEquipmentToBot(templateInventory: Inventory, wornItemChances: Chances, botRole: string, botInventory: PmcInventory, botLevel: number, chosenGameVersion: string): void;
/**
* Remove non-armored rigs from parameter data
* @param templateInventory
* @param templateEquipment Equpiment to filter TacticalVest of
*/
protected filterRigsToThoseWithProtection(templateInventory: Inventory): void;
protected filterRigsToThoseWithProtection(templateEquipment: Equipment): void;
/**
* Remove armored rigs from parameter data
* @param templateInventory
* @param templateEquipment Equpiment to filter TacticalVest of
*/
protected filterRigsToThoseWithoutProtection(templateInventory: Inventory): void;
protected filterRigsToThoseWithoutProtection(templateEquipment: Equipment): void;
/**
* Add a piece of equipment with mods to inventory from the provided pools
* @param settings Values to adjust how item is chosen and added to bot
@ -90,8 +91,8 @@ export declare class BotInventoryGenerator {
* @param botInventory Inventory to add weapons to
* @param botRole assault/pmcBot/bossTagilla etc
* @param isPmc Is the bot being generated as a pmc
* @param botLevel level of bot having weapon generated
* @param itemGenerationLimitsMinMax Limits for items the bot can have
* @param botLevel level of bot having weapon generated
*/
protected generateAndAddWeaponsToBot(templateInventory: Inventory, equipmentChances: Chances, sessionId: string, botInventory: PmcInventory, botRole: string, isPmc: boolean, itemGenerationLimitsMinMax: Generation, botLevel: number): void;
/**
@ -119,22 +120,3 @@ export declare class BotInventoryGenerator {
shouldSpawn: boolean;
}, templateInventory: Inventory, botInventory: PmcInventory, equipmentChances: Chances, botRole: string, isPmc: boolean, itemGenerationWeights: Generation, botLevel: number): void;
}
export interface IGenerateEquipmentProperties {
/** Root Slot being generated */
rootEquipmentSlot: string;
/** Equipment pool for root slot being generated */
rootEquipmentPool: Record<string, number>;
modPool: Mods;
/** Dictionary of mod items and their chance to spawn for this bot type */
spawnChances: Chances;
/** Role being generated for */
botRole: string;
/** Level of bot being generated */
botLevel: number;
inventory: PmcInventory;
botEquipmentConfig: EquipmentFilters;
/** Settings from bot.json to adjust how item is generated */
randomisationDetails: RandomisationDetails;
/** OPTIONAL - Do not generate mods for tpls in this array */
generateModsBlacklist?: string[];
}

View File

@ -170,7 +170,7 @@ export declare class RagfairOfferGenerator {
* @param tpl Item to look for matching condition object
* @returns condition id
*/
protected getDynamicConditionIdForTpl(tpl: string): string;
protected getDynamicConditionIdForTpl(tpl: string): string | undefined;
/**
* Alter an items condition based on its item base type
* @param conditionSettingsId also the parentId of item being altered

View File

@ -118,12 +118,22 @@ export declare class RepeatableQuestRewardGenerator {
* 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} count Amount of items to give
* @param {integer} index All rewards will be appended to a list, for unknown reasons the client wants the index
* @param preset Optional array of preset items
* @returns {object} Object of "Reward"-item-type
*/
protected generateRewardItem(tpl: string, value: number, index: number, preset?: Item[]): IQuestReward;
protected generateItemReward(tpl: string, count: number, index: number): IQuestReward;
/**
* Helper to create a reward item structured as required by the client
*
* @param {string} tpl ItemId of the rewarded item
* @param {integer} count Amount of items to give
* @param {integer} index All rewards will be appended to a list, for unknown reasons the client wants the index
* @param preset Optional array of preset items
* @returns {object} Object of "Reward"-item-type
*/
protected generatePresetReward(tpl: string, count: number, index: number, preset?: Item[]): IQuestReward;
/**
* Picks rewardable items from items.json
* This means they must:

View File

@ -47,6 +47,11 @@ export declare class BotHelper {
*/
shouldBotBePmc(botRole: string): boolean;
rollChanceToBePmc(role: string, botConvertMinMax: MinMax): boolean;
/**
* is the provided role a PMC, case-agnostic
* @param botRole Role to check
* @returns True if role is PMC
*/
botRoleIsPmc(botRole: string): boolean;
/**
* Get randomization settings for bot from config/bot.json

View File

@ -22,12 +22,12 @@ export declare class HealthHelper {
*/
resetVitality(sessionID: string): ISptProfile;
/**
* Update player profile with changes from request object
* Update player profile vitality values with changes from client request object
* @param pmcData Player profile
* @param request Heal request
* @param sessionID Session id
* @param addEffects Should effects be added or removed (default - add)
* @param deleteExistingEffects Should all prior effects be removed before apply new ones
* @param addEffects Should effects be added to profile (default - true)
* @param deleteExistingEffects Should all prior effects be removed before apply new ones (default - true)
*/
saveVitality(pmcData: IPmcData, request: ISyncHealthRequestData, sessionID: string, addEffects?: boolean, deleteExistingEffects?: boolean): void;
/**

View File

@ -1,6 +1,7 @@
import { InventoryHelper } from "@spt/helpers/InventoryHelper";
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { PaymentHelper } from "@spt/helpers/PaymentHelper";
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
import { QuestHelper } from "@spt/helpers/QuestHelper";
import { IPmcData, IPostRaidPmcData } from "@spt/models/eft/common/IPmcData";
import { IQuestStatus, TraderInfo } from "@spt/models/eft/common/tables/IBotBase";
@ -17,7 +18,6 @@ import { ProfileFixerService } from "@spt/services/ProfileFixerService";
import { ICloner } from "@spt/utils/cloners/ICloner";
import { RandomUtil } from "@spt/utils/RandomUtil";
import { TimeUtil } from "@spt/utils/TimeUtil";
import { ProfileHelper } from "./ProfileHelper";
export declare class InRaidHelper {
protected logger: ILogger;
protected timeUtil: TimeUtil;

View File

@ -9,9 +9,7 @@ import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { Inventory } from "@spt/models/eft/common/tables/IBotBase";
import { Item, Upd } from "@spt/models/eft/common/tables/IItem";
import { IAddItemDirectRequest } from "@spt/models/eft/inventory/IAddItemDirectRequest";
import { AddItem } from "@spt/models/eft/inventory/IAddItemRequestData";
import { IAddItemsDirectRequest } from "@spt/models/eft/inventory/IAddItemsDirectRequest";
import { IAddItemTempObject } from "@spt/models/eft/inventory/IAddItemTempObject";
import { IInventoryMergeRequestData } from "@spt/models/eft/inventory/IInventoryMergeRequestData";
import { IInventoryMoveRequestData } from "@spt/models/eft/inventory/IInventoryMoveRequestData";
import { IInventoryRemoveRequestData } from "@spt/models/eft/inventory/IInventoryRemoveRequestData";
@ -106,19 +104,12 @@ export declare class InventoryHelper {
* Find a location to place an item into inventory and place it
* @param stashFS2D 2-dimensional representation of the container slots
* @param sortingTableFS2D 2-dimensional representation of the sorting table slots
* @param itemWithChildren Item to place
* @param playerInventory
* @param itemWithChildren Item to place with children
* @param playerInventory Players inventory
* @param useSortingTable Should sorting table to be used if main stash has no space
* @param output output to send back to client
*/
protected placeItemInInventory(stashFS2D: number[][], sortingTableFS2D: number[][], itemWithChildren: Item[], playerInventory: Inventory, useSortingTable: boolean, output: IItemEventRouterResponse): void;
/**
* Split an items stack size based on its StackMaxSize value
* @param assortItems Items to add to inventory
* @param requestItem Details of purchased item to add to inventory
* @param result Array split stacks are appended to
*/
protected splitStackIntoSmallerChildStacks(assortItems: Item[], requestItem: AddItem, result: IAddItemTempObject[]): void;
/**
* Handle Remove event
* Remove item from player inventory + insured items array
@ -154,6 +145,14 @@ export declare class InventoryHelper {
* @returns [width, height]
*/
getItemSize(itemTpl: string, itemID: string, inventoryItems: Item[]): number[];
/**
* Calculates the size of an item including attachements
* takes into account if item is folded
* @param itemTpl Items template id
* @param itemID Items id
* @param inventoryItemHash Hashmap of inventory items
* @returns An array representing the [width, height] of the item
*/
protected getSizeByInventoryItemHash(itemTpl: string, itemID: string, inventoryItemHash: InventoryHelper.InventoryItemHash): number[];
/**
* Get a blank two-dimentional representation of a container

View File

@ -182,15 +182,18 @@ export declare class ItemHelper {
/**
* Calcualte the average quality of an item and its children
* @param items An offers item to process
* @param skipArmorItemsWithoutDurability Skip over armor items without durability
* @returns % quality modifer between 0 and 1
*/
getItemQualityModifierForOfferItems(items: Item[]): number;
getItemQualityModifierForItems(items: Item[], skipArmorItemsWithoutDurability?: boolean): number;
/**
* get normalized value (0-1) based on item condition
* Will return -1 for base armor items with 0 durability
* @param item
* @returns number between 0 and 1
* @param skipArmorItemsWithoutDurability return -1 for armor items that have maxdurability of 0
* @returns Number between 0 and 1
*/
getItemQualityModifier(item: Item): number;
getItemQualityModifier(item: Item, skipArmorItemsWithoutDurability?: boolean): number;
/**
* Get a quality value based on a repairable items (weapon/armor) current state between current and max durability
* @param itemDetails Db details for item we want quality value for

View File

@ -1,8 +1,8 @@
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { IPreset } from "@spt/models/eft/common/IGlobals";
import { BaseClasses } from "@spt/models/enums/BaseClasses";
import { DatabaseService } from "@spt/services/DatabaseService";
import { ICloner } from "@spt/utils/cloners/ICloner";
import { ItemHelper } from "./ItemHelper";
export declare class PresetHelper {
protected databaseService: DatabaseService;
protected itemHelper: ItemHelper;

View File

@ -144,11 +144,11 @@ export declare class QuestHelper {
/**
* Adjust quest money rewards by passed in multiplier
* @param quest Quest to multiple money rewards
* @param multiplier Value to adjust money rewards by
* @param bonusPercent Value to adjust money rewards by
* @param questStatus Status of quest to apply money boost to rewards of
* @returns Updated quest
*/
applyMoneyBoost(quest: IQuest, multiplier: number, questStatus: QuestStatus): IQuest;
applyMoneyBoost(quest: IQuest, bonusPercent: number, questStatus: QuestStatus): IQuest;
/**
* Sets the item stack to new value, or delete the item if value <= 0
* // TODO maybe merge this function and the one from customization

View File

@ -3,6 +3,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper";
import { PaymentHelper } from "@spt/helpers/PaymentHelper";
import { PresetHelper } from "@spt/helpers/PresetHelper";
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
import { QuestHelper } from "@spt/helpers/QuestHelper";
import { RagfairHelper } from "@spt/helpers/RagfairHelper";
import { RagfairServerHelper } from "@spt/helpers/RagfairServerHelper";
import { RagfairSortHelper } from "@spt/helpers/RagfairSortHelper";
@ -28,7 +29,6 @@ import { RagfairOfferService } from "@spt/services/RagfairOfferService";
import { RagfairRequiredItemsService } from "@spt/services/RagfairRequiredItemsService";
import { HashUtil } from "@spt/utils/HashUtil";
import { TimeUtil } from "@spt/utils/TimeUtil";
import { QuestHelper } from "./QuestHelper";
export declare class RagfairOfferHelper {
protected logger: ILogger;
protected timeUtil: TimeUtil;

View File

@ -1,4 +1,4 @@
import { IMagazineTemplateAmmoItem } from "../profile/ISptProfile";
import { IMagazineTemplateAmmoItem } from "@spt/models/eft/profile/ISptProfile";
export interface ISetMagazineRequest {
Id: string;
Name: string;

View File

@ -1,7 +1,7 @@
import { Exit, ILocationBase } from "@spt/models/eft/common/ILocationBase";
import { ILooseLoot } from "@spt/models/eft/common/ILooseLoot";
import { Ixyz } from "./Ixyz";
import { Item } from "./tables/IItem";
import { Ixyz } from "@spt/models/eft/common/Ixyz";
import { Item } from "@spt/models/eft/common/tables/IItem";
export interface ILocation {
/** Map meta-data */
base: ILocationBase;

View File

@ -1,4 +1,4 @@
import { IQuestConditionTypes, IQuestRewards } from "./IQuest";
import { IQuestConditionTypes, IQuestRewards } from "@spt/models/eft/common/tables/IQuest";
export interface IAchievement {
id: string;
imageUrl: string;

View File

@ -1,4 +1,4 @@
import { IQuest, IQuestConditionTypes, IQuestRewards } from "./IQuest";
import { IQuest, IQuestConditionTypes, IQuestRewards } from "@spt/models/eft/common/tables/IQuest";
export interface IRepeatableQuest extends IQuest {
changeCost: IChangeCost[];
changeStandingCost: number;

View File

@ -1,4 +1,4 @@
import { Item } from "../common/tables/IItem";
import { Item } from "@spt/models/eft/common/tables/IItem";
export interface IItemDeliveryRequestData {
items: Item[];
traderId: string;

View File

@ -1,4 +1,4 @@
import { Item } from "../common/tables/IItem";
import { Item } from "@spt/models/eft/common/tables/IItem";
export interface IAddItemDirectRequest {
/** Item and child mods to add to player inventory */
itemWithModsToAdd: Item[];

View File

@ -1,4 +1,4 @@
import { Item } from "../common/tables/IItem";
import { Item } from "@spt/models/eft/common/tables/IItem";
export interface IAddItemsDirectRequest {
/** Item and child mods to add to player inventory */
itemsWithModsToAdd: Item[][];

View File

@ -1,4 +1,4 @@
import { IInventoryBaseActionRequestData } from "./IInventoryBaseActionRequestData";
import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData";
export interface IRedeemProfileRequestData extends IInventoryBaseActionRequestData {
Action: "RedeemProfileReward";
events: IRedeemProfileRequestEvent[];

View File

@ -1,4 +1,4 @@
import { IInventoryBaseActionRequestData } from "./IInventoryBaseActionRequestData";
import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData";
export interface ISetFavoriteItems extends IInventoryBaseActionRequestData {
Action: "SetFavoriteItems";
items: any[];

View File

@ -1,4 +1,4 @@
import { IAchievement } from "../common/tables/IAchievement";
import { IAchievement } from "@spt/models/eft/common/tables/IAchievement";
export interface IGetAchievementsResponse {
elements: IAchievement[];
}

View File

@ -1,6 +1,6 @@
import { IGroupCharacter } from "@spt/models/eft/match/IGroupCharacter";
import { Message } from "@spt/models/eft/profile/ISptProfile";
import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent";
import { IGroupCharacter } from "../match/IGroupCharacter";
export interface IWsChatMessageReceived extends IWsNotificationEvent {
dialogId: string;
message: Message;

View File

@ -1,4 +1,4 @@
import { IGroupCharacter } from "@spt/models/eft/match/IGroupCharacter";
import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent";
import { IGroupCharacter } from "../match/IGroupCharacter";
export interface IWsGroupMatchInviteAccept extends IWsNotificationEvent, IGroupCharacter {
}

View File

@ -1,5 +1,8 @@
export declare enum ModSpawn {
/** Chosen mod should be the tpl from the default weapon template */
DEFAULT_MOD = 0,
/** Normal behaviour */
SPAWN = 1,
/** Item should not be chosen */
SKIP = 2
}

View File

@ -1,9 +1,15 @@
export declare enum NotificationEventType {
ASSORTMENT_UNLOCK_RULE = "AssortmentUnlockRule",
EXAMINE_ITEMS = "ExamineItems",
EXAMINE_ALL_ITEMS = "ExamineAllItems",
FORCE_LOGOUT = "ForceLogout",
RAGFAIR_OFFER_SOLD = "RagfairOfferSold",
RAGFAIR_NEW_RATING = "RagfairNewRating",
RAGFAIR_RATING_CHANGE = "RagfairRatingChange",
CHAT_MESSAGE_RECEIVED = "new_message",
PING = "ping",
TRADER_SUPPLY = "TraderSupply",
TRADER_SALES_SUM = "TraderSalesSum",
TRADER_SUPPLY = "trader_supply",
TRADER_STANDING = "TraderStanding",
UNLOCK_TRADER = "UnlockTrader",
GROUP_MATCH_RAID_SETTINGS = "groupMatchRaidSettings",
@ -18,11 +24,17 @@ export declare enum NotificationEventType {
GROUP_MATCH_WAS_REMOVED = "groupMatchWasRemoved",
GROUP_MATCH_USER_BAD_VERSION = "groupMatchUserHasBadVersion",
USER_CONFIRMED = "userConfirmed",
USER_MATCHED = "UserMatched",
USER_MATCH_OVER = "userMatchOver",
CHANNEL_DELETED = "channel_deleted",
FRIEND_LIST_REQUEST_ACCEPTED = "friendListRequestAccept",
FRIEND_LIST_REQUEST_DECLINED = "friendListRequestDecline",
FRIEND_LIST_NEW_REQUEST = "friendListNewRequest",
FRIEND_LIST_REMOVED_FROM_FRIEND_LIST = "youAreRemovedFromFriendList",
YOU_ARE_ADDED_TO_IGNORE_LIST = "YouWereAddedToIgnoreList",
YOU_ARE_REMOVED_FROM_IGNORE_LIST = "youAreRemoveFromIgnoreList"
YOU_ARE_REMOVED_FROM_IGNORE_LIST = "youAreRemoveFromIgnoreList",
PROFILE_LOCK_TIMER = "ProfileLockTimer",
STASH_ROWS = "StashRows",
SKILL_POINTS = "SkillPoints",
TOURNAMENT_WARNING = "tournamentWarning"
}

View File

@ -52,5 +52,19 @@ export declare enum SkillTypes {
USEC_DEEP_WEAPON_MOD = "UsecDeepweaponmodding_Settings",
USEC_LONG_RANGE_OPTICS = "UsecLongrangeoptics_Settings",
USEC_NEGOTIATIONS = "UsecNegotiations",
USEC_TACTICS = "UsecTactics"
USEC_TACTICS = "UsecTactics",
PISTOL = "Pistol",
REVOLVER = "Revolver",
SMG = "SMG",
ASSAULT = "Assault",
SHOTGUN = "Shotgun",
SNIPER = "Sniper",
LMG = "LMG",
HMG = "HMG",
LAUNCHER = "Launcher",
ATTACHED_LAUNCHER = "AttachedLauncher",
MISC = "Misc",
DMR = "DMR",
DRAW_MASTER = "DrawMaster",
AIM_MASTER = "AimMaster"
}

View File

@ -0,0 +1,22 @@
import { Inventory as PmcInventory } from "@spt/models/eft/common/tables/IBotBase";
import { Chances, Mods } from "@spt/models/eft/common/tables/IBotType";
import { EquipmentFilters, RandomisationDetails } from "@spt/models/spt/config/IBotConfig";
export interface IGenerateEquipmentProperties {
/** Root Slot being generated */
rootEquipmentSlot: string;
/** Equipment pool for root slot being generated */
rootEquipmentPool: Record<string, number>;
modPool: Mods;
/** Dictionary of mod items and their chance to spawn for this bot type */
spawnChances: Chances;
/** Role being generated for */
botRole: string;
/** Level of bot being generated */
botLevel: number;
inventory: PmcInventory;
botEquipmentConfig: EquipmentFilters;
/** Settings from bot.json to adjust how item is generated */
randomisationDetails: RandomisationDetails;
/** OPTIONAL - Do not generate mods for tpls in this array */
generateModsBlacklist?: string[];
}

View File

@ -1,5 +1,5 @@
import { MinMax } from "@spt/models/common/MinMax";
import { IBaseConfig } from "./IBaseConfig";
import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig";
export interface IBTRConfig extends IBaseConfig {
kind: "spt-btr";
/** How fast the BTR moves */

View File

@ -43,6 +43,12 @@ export interface IBotConfig extends IBaseConfig {
lowProfileGasBlockTpls: string[];
/** What bottypes should be excluded from having loot generated on them (backpack/pocket/vest) does not disable food/drink/special/ */
disableLootOnBotTypes: string[];
assaultToBossConversion: IAssaultToBossConversion;
}
export interface IAssaultToBossConversion {
bossConvertEnabled: boolean;
bossesToConvertToWeights: Record<string, number>;
bossConvertMinMax: Record<string, MinMax>;
}
/** Number of bots to generate and store in cache on raid start per bot type */
export interface PresetBatch {

View File

@ -4,7 +4,7 @@ import { GiftSenderType } from "@spt/models/enums/GiftSenderType";
import { SeasonalEventType } from "@spt/models/enums/SeasonalEventType";
import { Traders } from "@spt/models/enums/Traders";
import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig";
import { IProfileChangeEvent } from "../dialog/ISendMessageDetails";
import { IProfileChangeEvent } from "@spt/models/spt/dialog/ISendMessageDetails";
export interface IGiftsConfig extends IBaseConfig {
kind: "spt-gifts";
gifts: Record<string, Gift>;

View File

@ -27,7 +27,8 @@ export interface FenceConfig {
presetPriceMult: number;
armorMaxDurabilityPercentMinMax: IItemDurabilityCurrentMax;
weaponDurabilityPercentMinMax: IItemDurabilityCurrentMax;
chancePlateExistsInArmorPercent: number;
/** Keyed to plate protection level */
chancePlateExistsInArmorPercent: Record<string, number>;
/** Key: item tpl */
itemStackSizeOverrideMinMax: Record<string, MinMax>;
itemTypeLimits: Record<string, number>;

View File

@ -0,0 +1,5 @@
import { IPmcDataRepeatableQuest, IRepeatableQuest } from "@spt/models/eft/common/tables/IRepeatableQuests";
export interface IGetRepeatableByIdResult {
quest: IRepeatableQuest;
repeatableType: IPmcDataRepeatableQuest;
}

View File

@ -11,4 +11,5 @@ export interface LootRequest {
itemStackLimits: Record<string, MinMax>;
armorLevelWhitelist: number[];
allowBossItems: boolean;
useRewarditemBlacklist?: boolean;
}

View File

@ -1,11 +1,11 @@
import { SaveLoadRouter } from "@spt/di/Router";
import { ISptProfile, Info } from "@spt/models/eft/profile/ISptProfile";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
import { LocalisationService } from "@spt/services/LocalisationService";
import { HashUtil } from "@spt/utils/HashUtil";
import { JsonUtil } from "@spt/utils/JsonUtil";
import { VFS } from "@spt/utils/VFS";
import { ConfigServer } from "./ConfigServer";
export declare class SaveServer {
protected vfs: VFS;
protected saveLoadRouters: SaveLoadRouter[];

View File

@ -3,10 +3,10 @@ import http, { IncomingMessage } from "node:http";
import { WebSocket, Server } from "ws";
import { HttpServerHelper } from "@spt/helpers/HttpServerHelper";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { IWebSocketConnectionHandler } from "@spt/servers/ws/IWebSocketConnectionHandler";
import { LocalisationService } from "@spt/services/LocalisationService";
import { JsonUtil } from "@spt/utils/JsonUtil";
import { RandomUtil } from "@spt/utils/RandomUtil";
import { IWebSocketConnectionHandler } from "./ws/IWebSocketConnectionHandler";
export declare class WebSocketServer {
protected logger: ILogger;
protected randomUtil: RandomUtil;

View File

@ -8,9 +8,9 @@ import { IHttpConfig } from "@spt/models/spt/config/IHttpConfig";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
import { IWebSocketConnectionHandler } from "@spt/servers/ws/IWebSocketConnectionHandler";
import { ISptWebSocketMessageHandler } from "@spt/servers/ws/message/ISptWebSocketMessageHandler";
import { LocalisationService } from "@spt/services/LocalisationService";
import { JsonUtil } from "@spt/utils/JsonUtil";
import { ISptWebSocketMessageHandler } from "./message/ISptWebSocketMessageHandler";
export declare class SptWebSocketConnectionHandler implements IWebSocketConnectionHandler {
protected logger: ILogger;
protected profileHelper: ProfileHelper;

View File

@ -19,7 +19,7 @@ import { ISettingsBase } from "@spt/models/spt/server/ISettingsBase";
import { ITemplates } from "@spt/models/spt/templates/ITemplates";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { DatabaseServer } from "@spt/servers/DatabaseServer";
import { LocalisationService } from "./LocalisationService";
import { LocalisationService } from "@spt/services/LocalisationService";
export declare class DatabaseService {
protected logger: ILogger;
protected databaseServer: DatabaseServer;
@ -52,7 +52,7 @@ export declare class DatabaseService {
getLocations(): ILocations;
/**
* Get specific location by its Id
* @param locationId Desired trader id
* @param locationId Desired location id
* @returns assets/database/locations/
*/
getLocation(locationId: string): ILocation;

View File

@ -4,7 +4,7 @@ import { PresetHelper } from "@spt/helpers/PresetHelper";
import { IFenceLevel } from "@spt/models/eft/common/IGlobals";
import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { Item, Repairable } from "@spt/models/eft/common/tables/IItem";
import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem";
import { ITemplateItem, Slot } from "@spt/models/eft/common/tables/ITemplateItem";
import { IBarterScheme, ITraderAssort } from "@spt/models/eft/common/tables/ITrader";
import { IItemDurabilityCurrentMax, ITraderConfig } from "@spt/models/spt/config/ITraderConfig";
import { ICreateFenceAssortsResult } from "@spt/models/spt/fence/ICreateFenceAssortsResult";
@ -254,6 +254,19 @@ export declare class FenceService {
* @param itemDbDetails Armor items db template
*/
protected randomiseArmorModDurability(armor: Item[], itemDbDetails: ITemplateItem): void;
/**
* Randomise the durability values of items on armor with a passed in slot
* @param softInsertSlots Slots of items to randomise
* @param armorItemAndMods Array of armor + inserts to get items from
*/
protected randomiseArmorSoftInsertDurabilities(softInsertSlots: Slot[], armorItemAndMods: Item[]): void;
/**
* Randomise the durability values of plate items in armor
* Has chance to remove plate
* @param plateSlots Slots of items to randomise
* @param armorItemAndMods Array of armor + inserts to get items from
*/
protected randomiseArmorInsertsDurabilities(plateSlots: Slot[], armorItemAndMods: Item[]): void;
/**
* Get stack size of a singular item (no mods)
* @param itemDbDetails item being added to fence

View File

@ -1,6 +1,6 @@
# Welcome to the SPT Modding Project
# Welcome to the SPT-AKI Modding Project
This project is designed to streamline the initial setup process for building and creating mods in the SPT environment. Follow this guide to set up your environment efficiently.
This project is designed to streamline the initial setup process for building and creating mods in the SPT-AKI environment. Follow this guide to set up your environment efficiently.
## **Table of Contents**
- [NodeJS Setup](#nodejs-setup)
@ -39,7 +39,7 @@ Note: Preserve the `node_modules` folder as it contains necessary dependencies f
## **Essential Concepts**
Prioritize understanding Dependency Injection and Inversion of Control, the architectural principles SPT adopts. Comprehensive guidelines will be available on the hub upon release.
Prioritize understanding Dependency Injection and Inversion of Control, the architectural principles SPT-AKI adopts. Comprehensive guidelines will be available on the hub upon release.
Some resources to get you started:
- [A quick intro to Dependency Injection](https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f/)
@ -47,13 +47,13 @@ Some resources to get you started:
## **Coding Guidelines**
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"sptVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"akiVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
## **Distribution Guidelines**
Automated tasks are set up to bundle all necessary files for your mod to function in SPT:
Automated tasks are set up to bundle all necessary files for your mod to function in SPT-AKI:
> Terminal -> Run Task... -> Show All Tasks... -> npm: build
@ -61,6 +61,6 @@ The ZIP output, located in the `dist` directory, contains all required files. En
## **Conclusion**
With this setup, you're ready to begin modding with SPT. If you run into any trouble be sure to check out the [modding documentation on the hub](https://hub.sp-tarkov.com/doc/lexicon/66-modding/). If you really get stuck feel free to join us in the [#mods-development](https://discord.com/channels/875684761291599922/875803116409323562) official Discord channel.
With this setup, you're ready to begin modding with SPT-AKI. If you run into any trouble be sure to check out the [modding documentation on the hub](https://hub.sp-tarkov.com/doc/lexicon/66-modding/). If you really get stuck feel free to join us in the [#mods-development](https://discord.com/channels/875684761291599922/875803116409323562) official Discord channel.
Build something awesome!

View File

@ -1,7 +1,7 @@
{
"name": "BundleLoading",
"version": "1.0.0",
"sptVersion": "~3.9",
"akiVersion": "~3.9",
"loadBefore": [],
"loadAfter": [],
"incompatibilities": [],

View File

@ -1,14 +1,14 @@
import { DependencyContainer } from "tsyringe";
import { IPostSptLoadMod } from "@spt/models/external/IPostSptLoadMod";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { IPostAkiLoadMod } from "@spt-aki/models/external/IPostAkiLoadMod";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
class Mod implements IPostSptLoadMod
class Mod implements IPostAkiLoadMod
{
public postSptLoad(container: DependencyContainer): void
public postAkiLoad(container: DependencyContainer): void
{
// get the logger from the server container
const logger = container.resolve<ILogger>("PrimaryLogger");
const logger = container.resolve<ILogger>("WinstonLogger");
logger.info("Loading: Bundle Loading Sample");
}

View File

@ -11,7 +11,7 @@
"resolveJsonModule": true,
"outDir": "tmp",
"paths": {
"@spt/*": ["./types/*"],
"@spt-aki/*": ["./types/*"],
},
},
"exclude": ["node_modules", "dist", "tmp"],

View File

@ -59,4 +59,5 @@ export declare class InraidCallbacks {
itemDelivery(url: string, request: IItemDeliveryRequestData, sessionId: string): INullResponseData;
getTraitorScavHostileChance(url: string, info: IEmptyRequestData, sessionId: string): string;
getSandboxMaxPatrolValue(url: string, info: IEmptyRequestData, sessionId: string): string;
getBossConvertSettings(url: string, info: IEmptyRequestData, sessionId: string): string;
}

View File

@ -3,6 +3,7 @@ import { BotGenerator } from "@spt/generators/BotGenerator";
import { BotDifficultyHelper } from "@spt/helpers/BotDifficultyHelper";
import { BotHelper } from "@spt/helpers/BotHelper";
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper";
import { MinMax } from "@spt/models/common/MinMax";
import { Condition, IGenerateBotsRequestData } from "@spt/models/eft/bot/IGenerateBotsRequestData";
import { IPmcData } from "@spt/models/eft/common/IPmcData";
@ -27,6 +28,7 @@ export declare class BotController {
protected botGenerator: BotGenerator;
protected botHelper: BotHelper;
protected botDifficultyHelper: BotDifficultyHelper;
protected weightedRandomHelper: WeightedRandomHelper;
protected botGenerationCacheService: BotGenerationCacheService;
protected matchBotDetailsCacheService: MatchBotDetailsCacheService;
protected localisationService: LocalisationService;
@ -38,7 +40,7 @@ export declare class BotController {
protected cloner: ICloner;
protected botConfig: IBotConfig;
protected pmcConfig: IPmcConfig;
constructor(logger: ILogger, databaseService: DatabaseService, botGenerator: BotGenerator, botHelper: BotHelper, botDifficultyHelper: BotDifficultyHelper, botGenerationCacheService: BotGenerationCacheService, matchBotDetailsCacheService: MatchBotDetailsCacheService, localisationService: LocalisationService, seasonalEventService: SeasonalEventService, profileHelper: ProfileHelper, configServer: ConfigServer, applicationContext: ApplicationContext, randomUtil: RandomUtil, cloner: ICloner);
constructor(logger: ILogger, databaseService: DatabaseService, botGenerator: BotGenerator, botHelper: BotHelper, botDifficultyHelper: BotDifficultyHelper, weightedRandomHelper: WeightedRandomHelper, botGenerationCacheService: BotGenerationCacheService, matchBotDetailsCacheService: MatchBotDetailsCacheService, localisationService: LocalisationService, seasonalEventService: SeasonalEventService, profileHelper: ProfileHelper, configServer: ConfigServer, applicationContext: ApplicationContext, randomUtil: RandomUtil, cloner: ICloner);
/**
* Return the number of bot load-out varieties to be generated
* @param type bot Type we want the load-out gen count for
@ -116,6 +118,7 @@ export declare class BotController {
* @returns Single IBotBase object
*/
protected returnSingleBotFromCache(sessionId: string, request: IGenerateBotsRequestData): Promise<IBotBase[]>;
protected updateBotGenerationDetailsToRandomBoss(botGenerationDetails: BotGenerationDetails, possibleBossTypeWeights: Record<string, number>): void;
/**
* Get the difficulty passed in, if its not "asonline", get selected difficulty from config
* @param requestedDifficulty

View File

@ -31,6 +31,7 @@ import { PmcChatResponseService } from "@spt/services/PmcChatResponseService";
import { TraderServicesService } from "@spt/services/TraderServicesService";
import { RandomUtil } from "@spt/utils/RandomUtil";
import { TimeUtil } from "@spt/utils/TimeUtil";
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
/**
* Logic for handling In Raid callbacks
*/
@ -62,6 +63,7 @@ export declare class InraidController {
protected locationConfig: ILocationConfig;
protected ragfairConfig: IRagfairConfig;
protected hideoutConfig: IHideoutConfig;
protected botConfig: IBotConfig;
constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, databaseService: DatabaseService, pmcChatResponseService: PmcChatResponseService, matchBotDetailsCacheService: MatchBotDetailsCacheService, questHelper: QuestHelper, itemHelper: ItemHelper, profileHelper: ProfileHelper, playerScavGenerator: PlayerScavGenerator, healthHelper: HealthHelper, traderHelper: TraderHelper, traderServicesService: TraderServicesService, localisationService: LocalisationService, insuranceService: InsuranceService, inRaidHelper: InRaidHelper, applicationContext: ApplicationContext, configServer: ConfigServer, mailSendService: MailSendService, randomUtil: RandomUtil);
/**
* Save locationId to active profiles inraid object AND app context
@ -189,4 +191,5 @@ export declare class InraidController {
itemDelivery(sessionId: string, traderId: string, items: Item[]): void;
getTraitorScavHostileChance(url: string, sessionID: string): number;
getSandboxMaxPatrolValue(url: string, sessionID: string): number;
getBossConvertSettings(url: string, sessionId: string): string[];
}

View File

@ -9,6 +9,7 @@ import { ISptProfile } from "@spt/models/eft/profile/ISptProfile";
import { IRepeatableQuestChangeRequest } from "@spt/models/eft/quests/IRepeatableQuestChangeRequest";
import { ELocationName } from "@spt/models/enums/ELocationName";
import { IQuestConfig, IRepeatableQuestConfig } from "@spt/models/spt/config/IQuestConfig";
import { IGetRepeatableByIdResult } from "@spt/models/spt/quests/IGetRepeatableByIdResult";
import { IQuestTypePool } from "@spt/models/spt/repeatable/IQuestTypePool";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { EventOutputHolder } from "@spt/routers/EventOutputHolder";
@ -146,13 +147,21 @@ export declare class RepeatableQuestController {
* @returns IItemEventRouterResponse
*/
changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse;
/**
* Find a repeatable (daily/weekly/scav) from a players profile by its id
* @param questId Id of quest to find
* @param pmcData Profile that contains quests to look through
* @returns IGetRepeatableByIdResult
*/
protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult;
protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest;
/**
* Some accounts have access to repeatable quest refreshes for free
* Some accounts have access to free repeatable quest refreshes
* Track the usage of them inside players profile
* @param fullProfile Profile of player
* @param repeatableSubType Can be daily/weekly/scav repeatables
* @param repeatableTypeName Subtype of repeatables: daily / weekly / scav
* @param fullProfile Player profile
* @param repeatableSubType Can be daily / weekly / scav repeatable
* @param repeatableTypeName Subtype of repeatable quest: daily / weekly / scav
* @returns Is the repeatable being replaced for free
*/
protected handleFreeRefreshUses(fullProfile: ISptProfile, repeatableSubType: IPmcDataRepeatableQuest, repeatableTypeName: string): void;
protected useFreeRefreshIfAvailable(fullProfile: ISptProfile, repeatableSubType: IPmcDataRepeatableQuest, repeatableTypeName: string): boolean;
}

View File

@ -12,6 +12,8 @@ import { Item } from "@spt/models/eft/common/tables/IItem";
import { ITemplateItem, Slot } from "@spt/models/eft/common/tables/ITemplateItem";
import { ModSpawn } from "@spt/models/enums/ModSpawn";
import { IChooseRandomCompatibleModResult } from "@spt/models/spt/bots/IChooseRandomCompatibleModResult";
import { IFilterPlateModsForSlotByLevelResult } from "@spt/models/spt/bots/IFilterPlateModsForSlotByLevelResult";
import { IGenerateEquipmentProperties } from "@spt/models/spt/bots/IGenerateEquipmentProperties";
import { IGenerateWeaponRequest } from "@spt/models/spt/bots/IGenerateWeaponRequest";
import { IModToSpawnRequest } from "@spt/models/spt/bots/IModToSpawnRequest";
import { EquipmentFilterDetails, EquipmentFilters, IBotConfig } from "@spt/models/spt/config/IBotConfig";
@ -26,8 +28,6 @@ import { LocalisationService } from "@spt/services/LocalisationService";
import { ICloner } from "@spt/utils/cloners/ICloner";
import { HashUtil } from "@spt/utils/HashUtil";
import { RandomUtil } from "@spt/utils/RandomUtil";
import { IFilterPlateModsForSlotByLevelResult } from "../models/spt/bots/IFilterPlateModsForSlotByLevelResult";
import { IGenerateEquipmentProperties } from "./BotInventoryGenerator";
export declare class BotEquipmentModGenerator {
protected logger: ILogger;
protected hashUtil: HashUtil;
@ -94,8 +94,19 @@ export declare class BotEquipmentModGenerator {
* @param modSpawnChances Chance dictionary to update
*/
protected adjustSlotSpawnChances(modSpawnChances: ModsChances, modSlotsToAdjust: string[], newChancePercent: number): void;
protected modSlotCanHoldMuzzleDevices(modSlot: string, modsParentId: string): boolean;
protected sortModKeys(unsortedKeys: string[]): string[];
/**
* Does the provided modSlot allow muzzle-related items
* @param modSlot Slot id to check
* @param modsParentId OPTIONAL: parent id of modslot being checked
* @returns True if modSlot can have muzzle-related items
*/
protected modSlotCanHoldMuzzleDevices(modSlot: string, modsParentId?: string): boolean;
/**
* Sort mod slots into an ordering that maximises chance of a successful weapon generation
* @param unsortedSlotKeys Array of mod slot strings to sort
* @returns Sorted array
*/
protected sortModKeys(unsortedSlotKeys: string[]): string[];
/**
* Get a Slot property for an item (chamber/cartridge/slot)
* @param modSlot e.g patron_in_weapon
@ -118,43 +129,53 @@ export declare class BotEquipmentModGenerator {
* @returns itemHelper.getItem() result
*/
protected chooseModToPutIntoSlot(request: IModToSpawnRequest): [boolean, ITemplateItem] | undefined;
protected pickWeaponModTplForSlotFromPool(modPool: string[], parentSlot: Slot, modSpawnResult: ModSpawn, weapon: Item[], modSlotname: string): IChooseRandomCompatibleModResult;
/**
*
* @param modPool Pool of mods that can be picked from
* @param parentSlot Slot the picked mod will have as a parent
* @param choiceTypeEnum How should chosen tpl be treated: DEFAULT_MOD/SPAWN/SKIP
* @param weapon Array of weapon items chosen item will be added to
* @param modSlotName Name of slot picked mod will be placed into
* @returns Chosen weapon details
*/
protected pickWeaponModTplForSlotFromPool(modPool: string[], parentSlot: Slot, choiceTypeEnum: ModSpawn, weapon: Item[], modSlotName: string): IChooseRandomCompatibleModResult;
/**
* Filter mod pool down based on various criteria:
* Is slot flagged as randomisable
* Is slot required
* Is slot flagged as default mod only
* @param itemModPool Existing pool of mods to choose
* @param modSpawnResult outcome of random roll to select if mod should be added
* @param itemSpawnCategory How should slot be handled
* @param parentTemplate Mods parent
* @param weaponTemplate Mods root parent (weapon/equipment)
* @param modSlot name of mod slot to choose for
* @param botEquipBlacklist
* @param isRandomisableSlot is flagged as a randomisable slot
* @returns
* @param botEquipBlacklist A blacklist of items not allowed to be picked
* @param isRandomisableSlot Slot is flagged as a randomisable slot
* @returns Array of mod tpls
*/
protected getModPoolForSlot(itemModPool: Record<string, string[]>, modSpawnResult: ModSpawn, parentTemplate: ITemplateItem, weaponTemplate: ITemplateItem, modSlot: string, botEquipBlacklist: EquipmentFilterDetails, isRandomisableSlot: boolean): string[];
protected getModPoolForSlot(itemModPool: Record<string, string[]>, itemSpawnCategory: ModSpawn, parentTemplate: ITemplateItem, weaponTemplate: ITemplateItem, modSlot: string, botEquipBlacklist: EquipmentFilterDetails, isRandomisableSlot: boolean): string[];
/**
* Get default preset for weapon, get specific weapon presets for edge cases (mp5/silenced dvl)
* @param weaponTemplate
* @param parentItemTpl
* Get default preset for weapon OR get specific weapon presets for edge cases (mp5/silenced dvl)
* @param weaponTemplate Weapons db template
* @param parentItemTpl Tpl of the parent item
* @returns Default preset found
*/
protected getMatchingPreset(weaponTemplate: ITemplateItem, parentItemTpl: string): IPreset | undefined;
/**
* Temp fix to prevent certain combinations of weapons with mods that are known to be incompatible
* @param weapon Weapon
* @param weapon Array of items that make up a weapon
* @param modTpl Mod to check compatibility with weapon
* @returns True if incompatible
*/
protected weaponModComboIsIncompatible(weapon: Item[], modTpl: string): boolean;
/**
* Create a mod item with parameters as properties
* Create a mod item with provided parameters as properties + add upd property
* @param modId _id
* @param modTpl _tpl
* @param parentId parentId
* @param modSlot slotId
* @param modTemplate Used to add additional properties in the upd object
* @param botRole The bots role mod is being created for
* @returns Item object
*/
protected createModItem(modId: string, modTpl: string, parentId: string, modSlot: string, modTemplate: ITemplateItem, botRole: string): Item;
@ -166,43 +187,44 @@ export declare class BotEquipmentModGenerator {
protected getAmmoContainers(): string[];
/**
* Get a random mod from an items compatible mods Filter array
* @param modTpl ???? default value to return if nothing found
* @param parentSlot item mod will go into, used to get compatible items
* @param fallbackModTpl Default value to return if parentSlot Filter is empty
* @param parentSlot Item mod will go into, used to get compatible items
* @param modSlot Slot to get mod to fill
* @param items items to ensure picked mod is compatible with
* @returns item tpl
* @param items Items to ensure picked mod is compatible with
* @returns Item tpl
*/
protected getRandomModTplFromItemDb(modTpl: string, parentSlot: Slot, modSlot: string, items: Item[]): string | undefined;
protected getRandomModTplFromItemDb(fallbackModTpl: string, parentSlot: Slot, modSlot: string, items: Item[]): string | undefined;
/**
* Check if mod exists in db + is for a required slot
* @param modToAdd Db template of mod to check
* @param slotAddedToTemplate Slot object the item will be placed as child into
* @param modSlot Slot the mod will fill
* @param parentTemplate Db template of the mods being added
* @param botRole Bots wildspawntype (assault/pmcBot etc)
* @returns true if valid
* @param botRole Bots wildspawntype (assault/pmcBot/exUsec etc)
* @returns True if valid for slot
*/
protected isModValidForSlot(modToAdd: [boolean, ITemplateItem], slotAddedToTemplate: Slot, modSlot: string, parentTemplate: ITemplateItem, botRole: string): boolean;
/**
* Find mod tpls of a provided type and add to modPool
* @param desiredSlotName slot to look up and add we are adding tpls for (e.g mod_scope)
* @param desiredSlotName Slot to look up and add we are adding tpls for (e.g mod_scope)
* @param modTemplate db object for modItem we get compatible mods from
* @param modPool Pool of mods we are adding to
* @param botEquipBlacklist A blacklist of items that cannot be picked
*/
protected addCompatibleModsForProvidedMod(desiredSlotName: string, modTemplate: ITemplateItem, modPool: Mods, botEquipBlacklist: EquipmentFilterDetails): void;
/**
* Get the possible items that fit a slot
* @param parentItemId item tpl to get compatible items for
* @param modSlot Slot item should fit in
* @param botEquipBlacklist equipment that should not be picked
* @returns array of compatible items for that slot
* @param botEquipBlacklist Equipment that should not be picked
* @returns Array of compatible items for that slot
*/
protected getDynamicModPool(parentItemId: string, modSlot: string, botEquipBlacklist: EquipmentFilterDetails): string[];
/**
* Take a list of tpls and filter out blacklisted values using itemFilterService + botEquipmentBlacklist
* @param allowedMods base mods to filter
* @param botEquipBlacklist equipment blacklist
* @param modSlot slot mods belong to
* @param allowedMods Base mods to filter
* @param botEquipBlacklist Equipment blacklist
* @param modSlot Slot mods belong to
* @returns Filtered array of mod tpls
*/
protected filterWeaponModsByBlacklist(allowedMods: string[], botEquipBlacklist: EquipmentFilterDetails, modSlot: string): string[];
@ -212,17 +234,17 @@ export declare class BotEquipmentModGenerator {
* Ammo is not put into the magazine directly but assigned to the magazine's slots: The "camora_xxx" slots.
* This function is a helper called by generateModsForItem for mods with parent type "CylinderMagazine"
* @param items The items where the CylinderMagazine's camora are appended to
* @param modPool modPool which should include available cartridges
* @param parentId The CylinderMagazine's UID
* @param parentTemplate The CylinderMagazine's template
* @param modPool ModPool which should include available cartridges
* @param cylinderMagParentId The CylinderMagazine's UID
* @param cylinderMagTemplate The CylinderMagazine's template
*/
protected fillCamora(items: Item[], modPool: Mods, parentId: string, parentTemplate: ITemplateItem): void;
protected fillCamora(items: Item[], modPool: Mods, cylinderMagParentId: string, cylinderMagTemplate: ITemplateItem): void;
/**
* Take a record of camoras and merge the compatible shells into one array
* @param camorasWithShells camoras we want to merge into one array
* @returns string array of shells for multiple camora sources
* @param camorasWithShells Dictionary of camoras we want to merge into one array
* @returns String array of shells for multiple camora sources
*/
protected mergeCamoraPoolsTogether(camorasWithShells: Record<string, string[]>): string[];
protected mergeCamoraPools(camorasWithShells: Record<string, string[]>): string[];
/**
* Filter out non-whitelisted weapon scopes
* Controlled by bot.json weaponSightWhitelist

View File

@ -6,9 +6,10 @@ import { BotHelper } from "@spt/helpers/BotHelper";
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper";
import { Inventory as PmcInventory } from "@spt/models/eft/common/tables/IBotBase";
import { Chances, Generation, IBotType, Inventory, Mods } from "@spt/models/eft/common/tables/IBotType";
import { Chances, Equipment, Generation, IBotType, Inventory } from "@spt/models/eft/common/tables/IBotType";
import { EquipmentSlots } from "@spt/models/enums/EquipmentSlots";
import { EquipmentFilterDetails, EquipmentFilters, IBotConfig, RandomisationDetails } from "@spt/models/spt/config/IBotConfig";
import { IGenerateEquipmentProperties } from "@spt/models/spt/bots/IGenerateEquipmentProperties";
import { EquipmentFilterDetails, IBotConfig } from "@spt/models/spt/config/IBotConfig";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
import { BotEquipmentModPoolService } from "@spt/services/BotEquipmentModPoolService";
@ -61,14 +62,14 @@ export declare class BotInventoryGenerator {
protected generateAndAddEquipmentToBot(templateInventory: Inventory, wornItemChances: Chances, botRole: string, botInventory: PmcInventory, botLevel: number, chosenGameVersion: string): void;
/**
* Remove non-armored rigs from parameter data
* @param templateInventory
* @param templateEquipment Equpiment to filter TacticalVest of
*/
protected filterRigsToThoseWithProtection(templateInventory: Inventory): void;
protected filterRigsToThoseWithProtection(templateEquipment: Equipment): void;
/**
* Remove armored rigs from parameter data
* @param templateInventory
* @param templateEquipment Equpiment to filter TacticalVest of
*/
protected filterRigsToThoseWithoutProtection(templateInventory: Inventory): void;
protected filterRigsToThoseWithoutProtection(templateEquipment: Equipment): void;
/**
* Add a piece of equipment with mods to inventory from the provided pools
* @param settings Values to adjust how item is chosen and added to bot
@ -90,8 +91,8 @@ export declare class BotInventoryGenerator {
* @param botInventory Inventory to add weapons to
* @param botRole assault/pmcBot/bossTagilla etc
* @param isPmc Is the bot being generated as a pmc
* @param botLevel level of bot having weapon generated
* @param itemGenerationLimitsMinMax Limits for items the bot can have
* @param botLevel level of bot having weapon generated
*/
protected generateAndAddWeaponsToBot(templateInventory: Inventory, equipmentChances: Chances, sessionId: string, botInventory: PmcInventory, botRole: string, isPmc: boolean, itemGenerationLimitsMinMax: Generation, botLevel: number): void;
/**
@ -119,22 +120,3 @@ export declare class BotInventoryGenerator {
shouldSpawn: boolean;
}, templateInventory: Inventory, botInventory: PmcInventory, equipmentChances: Chances, botRole: string, isPmc: boolean, itemGenerationWeights: Generation, botLevel: number): void;
}
export interface IGenerateEquipmentProperties {
/** Root Slot being generated */
rootEquipmentSlot: string;
/** Equipment pool for root slot being generated */
rootEquipmentPool: Record<string, number>;
modPool: Mods;
/** Dictionary of mod items and their chance to spawn for this bot type */
spawnChances: Chances;
/** Role being generated for */
botRole: string;
/** Level of bot being generated */
botLevel: number;
inventory: PmcInventory;
botEquipmentConfig: EquipmentFilters;
/** Settings from bot.json to adjust how item is generated */
randomisationDetails: RandomisationDetails;
/** OPTIONAL - Do not generate mods for tpls in this array */
generateModsBlacklist?: string[];
}

View File

@ -170,7 +170,7 @@ export declare class RagfairOfferGenerator {
* @param tpl Item to look for matching condition object
* @returns condition id
*/
protected getDynamicConditionIdForTpl(tpl: string): string;
protected getDynamicConditionIdForTpl(tpl: string): string | undefined;
/**
* Alter an items condition based on its item base type
* @param conditionSettingsId also the parentId of item being altered

View File

@ -118,12 +118,22 @@ export declare class RepeatableQuestRewardGenerator {
* 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} count Amount of items to give
* @param {integer} index All rewards will be appended to a list, for unknown reasons the client wants the index
* @param preset Optional array of preset items
* @returns {object} Object of "Reward"-item-type
*/
protected generateRewardItem(tpl: string, value: number, index: number, preset?: Item[]): IQuestReward;
protected generateItemReward(tpl: string, count: number, index: number): IQuestReward;
/**
* Helper to create a reward item structured as required by the client
*
* @param {string} tpl ItemId of the rewarded item
* @param {integer} count Amount of items to give
* @param {integer} index All rewards will be appended to a list, for unknown reasons the client wants the index
* @param preset Optional array of preset items
* @returns {object} Object of "Reward"-item-type
*/
protected generatePresetReward(tpl: string, count: number, index: number, preset?: Item[]): IQuestReward;
/**
* Picks rewardable items from items.json
* This means they must:

View File

@ -47,6 +47,11 @@ export declare class BotHelper {
*/
shouldBotBePmc(botRole: string): boolean;
rollChanceToBePmc(role: string, botConvertMinMax: MinMax): boolean;
/**
* is the provided role a PMC, case-agnostic
* @param botRole Role to check
* @returns True if role is PMC
*/
botRoleIsPmc(botRole: string): boolean;
/**
* Get randomization settings for bot from config/bot.json

View File

@ -22,12 +22,12 @@ export declare class HealthHelper {
*/
resetVitality(sessionID: string): ISptProfile;
/**
* Update player profile with changes from request object
* Update player profile vitality values with changes from client request object
* @param pmcData Player profile
* @param request Heal request
* @param sessionID Session id
* @param addEffects Should effects be added or removed (default - add)
* @param deleteExistingEffects Should all prior effects be removed before apply new ones
* @param addEffects Should effects be added to profile (default - true)
* @param deleteExistingEffects Should all prior effects be removed before apply new ones (default - true)
*/
saveVitality(pmcData: IPmcData, request: ISyncHealthRequestData, sessionID: string, addEffects?: boolean, deleteExistingEffects?: boolean): void;
/**

View File

@ -1,6 +1,7 @@
import { InventoryHelper } from "@spt/helpers/InventoryHelper";
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { PaymentHelper } from "@spt/helpers/PaymentHelper";
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
import { QuestHelper } from "@spt/helpers/QuestHelper";
import { IPmcData, IPostRaidPmcData } from "@spt/models/eft/common/IPmcData";
import { IQuestStatus, TraderInfo } from "@spt/models/eft/common/tables/IBotBase";
@ -17,7 +18,6 @@ import { ProfileFixerService } from "@spt/services/ProfileFixerService";
import { ICloner } from "@spt/utils/cloners/ICloner";
import { RandomUtil } from "@spt/utils/RandomUtil";
import { TimeUtil } from "@spt/utils/TimeUtil";
import { ProfileHelper } from "./ProfileHelper";
export declare class InRaidHelper {
protected logger: ILogger;
protected timeUtil: TimeUtil;

View File

@ -9,9 +9,7 @@ import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { Inventory } from "@spt/models/eft/common/tables/IBotBase";
import { Item, Upd } from "@spt/models/eft/common/tables/IItem";
import { IAddItemDirectRequest } from "@spt/models/eft/inventory/IAddItemDirectRequest";
import { AddItem } from "@spt/models/eft/inventory/IAddItemRequestData";
import { IAddItemsDirectRequest } from "@spt/models/eft/inventory/IAddItemsDirectRequest";
import { IAddItemTempObject } from "@spt/models/eft/inventory/IAddItemTempObject";
import { IInventoryMergeRequestData } from "@spt/models/eft/inventory/IInventoryMergeRequestData";
import { IInventoryMoveRequestData } from "@spt/models/eft/inventory/IInventoryMoveRequestData";
import { IInventoryRemoveRequestData } from "@spt/models/eft/inventory/IInventoryRemoveRequestData";
@ -106,19 +104,12 @@ export declare class InventoryHelper {
* Find a location to place an item into inventory and place it
* @param stashFS2D 2-dimensional representation of the container slots
* @param sortingTableFS2D 2-dimensional representation of the sorting table slots
* @param itemWithChildren Item to place
* @param playerInventory
* @param itemWithChildren Item to place with children
* @param playerInventory Players inventory
* @param useSortingTable Should sorting table to be used if main stash has no space
* @param output output to send back to client
*/
protected placeItemInInventory(stashFS2D: number[][], sortingTableFS2D: number[][], itemWithChildren: Item[], playerInventory: Inventory, useSortingTable: boolean, output: IItemEventRouterResponse): void;
/**
* Split an items stack size based on its StackMaxSize value
* @param assortItems Items to add to inventory
* @param requestItem Details of purchased item to add to inventory
* @param result Array split stacks are appended to
*/
protected splitStackIntoSmallerChildStacks(assortItems: Item[], requestItem: AddItem, result: IAddItemTempObject[]): void;
/**
* Handle Remove event
* Remove item from player inventory + insured items array
@ -154,6 +145,14 @@ export declare class InventoryHelper {
* @returns [width, height]
*/
getItemSize(itemTpl: string, itemID: string, inventoryItems: Item[]): number[];
/**
* Calculates the size of an item including attachements
* takes into account if item is folded
* @param itemTpl Items template id
* @param itemID Items id
* @param inventoryItemHash Hashmap of inventory items
* @returns An array representing the [width, height] of the item
*/
protected getSizeByInventoryItemHash(itemTpl: string, itemID: string, inventoryItemHash: InventoryHelper.InventoryItemHash): number[];
/**
* Get a blank two-dimentional representation of a container

View File

@ -182,15 +182,18 @@ export declare class ItemHelper {
/**
* Calcualte the average quality of an item and its children
* @param items An offers item to process
* @param skipArmorItemsWithoutDurability Skip over armor items without durability
* @returns % quality modifer between 0 and 1
*/
getItemQualityModifierForOfferItems(items: Item[]): number;
getItemQualityModifierForItems(items: Item[], skipArmorItemsWithoutDurability?: boolean): number;
/**
* get normalized value (0-1) based on item condition
* Will return -1 for base armor items with 0 durability
* @param item
* @returns number between 0 and 1
* @param skipArmorItemsWithoutDurability return -1 for armor items that have maxdurability of 0
* @returns Number between 0 and 1
*/
getItemQualityModifier(item: Item): number;
getItemQualityModifier(item: Item, skipArmorItemsWithoutDurability?: boolean): number;
/**
* Get a quality value based on a repairable items (weapon/armor) current state between current and max durability
* @param itemDetails Db details for item we want quality value for

View File

@ -1,8 +1,8 @@
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { IPreset } from "@spt/models/eft/common/IGlobals";
import { BaseClasses } from "@spt/models/enums/BaseClasses";
import { DatabaseService } from "@spt/services/DatabaseService";
import { ICloner } from "@spt/utils/cloners/ICloner";
import { ItemHelper } from "./ItemHelper";
export declare class PresetHelper {
protected databaseService: DatabaseService;
protected itemHelper: ItemHelper;

View File

@ -144,11 +144,11 @@ export declare class QuestHelper {
/**
* Adjust quest money rewards by passed in multiplier
* @param quest Quest to multiple money rewards
* @param multiplier Value to adjust money rewards by
* @param bonusPercent Value to adjust money rewards by
* @param questStatus Status of quest to apply money boost to rewards of
* @returns Updated quest
*/
applyMoneyBoost(quest: IQuest, multiplier: number, questStatus: QuestStatus): IQuest;
applyMoneyBoost(quest: IQuest, bonusPercent: number, questStatus: QuestStatus): IQuest;
/**
* Sets the item stack to new value, or delete the item if value <= 0
* // TODO maybe merge this function and the one from customization

View File

@ -3,6 +3,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper";
import { PaymentHelper } from "@spt/helpers/PaymentHelper";
import { PresetHelper } from "@spt/helpers/PresetHelper";
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
import { QuestHelper } from "@spt/helpers/QuestHelper";
import { RagfairHelper } from "@spt/helpers/RagfairHelper";
import { RagfairServerHelper } from "@spt/helpers/RagfairServerHelper";
import { RagfairSortHelper } from "@spt/helpers/RagfairSortHelper";
@ -28,7 +29,6 @@ import { RagfairOfferService } from "@spt/services/RagfairOfferService";
import { RagfairRequiredItemsService } from "@spt/services/RagfairRequiredItemsService";
import { HashUtil } from "@spt/utils/HashUtil";
import { TimeUtil } from "@spt/utils/TimeUtil";
import { QuestHelper } from "./QuestHelper";
export declare class RagfairOfferHelper {
protected logger: ILogger;
protected timeUtil: TimeUtil;

View File

@ -1,4 +1,4 @@
import { IMagazineTemplateAmmoItem } from "../profile/ISptProfile";
import { IMagazineTemplateAmmoItem } from "@spt/models/eft/profile/ISptProfile";
export interface ISetMagazineRequest {
Id: string;
Name: string;

View File

@ -1,7 +1,7 @@
import { Exit, ILocationBase } from "@spt/models/eft/common/ILocationBase";
import { ILooseLoot } from "@spt/models/eft/common/ILooseLoot";
import { Ixyz } from "./Ixyz";
import { Item } from "./tables/IItem";
import { Ixyz } from "@spt/models/eft/common/Ixyz";
import { Item } from "@spt/models/eft/common/tables/IItem";
export interface ILocation {
/** Map meta-data */
base: ILocationBase;

View File

@ -1,4 +1,4 @@
import { IQuestConditionTypes, IQuestRewards } from "./IQuest";
import { IQuestConditionTypes, IQuestRewards } from "@spt/models/eft/common/tables/IQuest";
export interface IAchievement {
id: string;
imageUrl: string;

View File

@ -1,4 +1,4 @@
import { IQuest, IQuestConditionTypes, IQuestRewards } from "./IQuest";
import { IQuest, IQuestConditionTypes, IQuestRewards } from "@spt/models/eft/common/tables/IQuest";
export interface IRepeatableQuest extends IQuest {
changeCost: IChangeCost[];
changeStandingCost: number;

View File

@ -1,4 +1,4 @@
import { Item } from "../common/tables/IItem";
import { Item } from "@spt/models/eft/common/tables/IItem";
export interface IItemDeliveryRequestData {
items: Item[];
traderId: string;

View File

@ -1,4 +1,4 @@
import { Item } from "../common/tables/IItem";
import { Item } from "@spt/models/eft/common/tables/IItem";
export interface IAddItemDirectRequest {
/** Item and child mods to add to player inventory */
itemWithModsToAdd: Item[];

View File

@ -1,4 +1,4 @@
import { Item } from "../common/tables/IItem";
import { Item } from "@spt/models/eft/common/tables/IItem";
export interface IAddItemsDirectRequest {
/** Item and child mods to add to player inventory */
itemsWithModsToAdd: Item[][];

View File

@ -1,4 +1,4 @@
import { IInventoryBaseActionRequestData } from "./IInventoryBaseActionRequestData";
import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData";
export interface IRedeemProfileRequestData extends IInventoryBaseActionRequestData {
Action: "RedeemProfileReward";
events: IRedeemProfileRequestEvent[];

View File

@ -1,4 +1,4 @@
import { IInventoryBaseActionRequestData } from "./IInventoryBaseActionRequestData";
import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData";
export interface ISetFavoriteItems extends IInventoryBaseActionRequestData {
Action: "SetFavoriteItems";
items: any[];

View File

@ -1,4 +1,4 @@
import { IAchievement } from "../common/tables/IAchievement";
import { IAchievement } from "@spt/models/eft/common/tables/IAchievement";
export interface IGetAchievementsResponse {
elements: IAchievement[];
}

View File

@ -1,6 +1,6 @@
import { IGroupCharacter } from "@spt/models/eft/match/IGroupCharacter";
import { Message } from "@spt/models/eft/profile/ISptProfile";
import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent";
import { IGroupCharacter } from "../match/IGroupCharacter";
export interface IWsChatMessageReceived extends IWsNotificationEvent {
dialogId: string;
message: Message;

View File

@ -1,4 +1,4 @@
import { IGroupCharacter } from "@spt/models/eft/match/IGroupCharacter";
import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent";
import { IGroupCharacter } from "../match/IGroupCharacter";
export interface IWsGroupMatchInviteAccept extends IWsNotificationEvent, IGroupCharacter {
}

View File

@ -1,5 +1,8 @@
export declare enum ModSpawn {
/** Chosen mod should be the tpl from the default weapon template */
DEFAULT_MOD = 0,
/** Normal behaviour */
SPAWN = 1,
/** Item should not be chosen */
SKIP = 2
}

View File

@ -1,9 +1,15 @@
export declare enum NotificationEventType {
ASSORTMENT_UNLOCK_RULE = "AssortmentUnlockRule",
EXAMINE_ITEMS = "ExamineItems",
EXAMINE_ALL_ITEMS = "ExamineAllItems",
FORCE_LOGOUT = "ForceLogout",
RAGFAIR_OFFER_SOLD = "RagfairOfferSold",
RAGFAIR_NEW_RATING = "RagfairNewRating",
RAGFAIR_RATING_CHANGE = "RagfairRatingChange",
CHAT_MESSAGE_RECEIVED = "new_message",
PING = "ping",
TRADER_SUPPLY = "TraderSupply",
TRADER_SALES_SUM = "TraderSalesSum",
TRADER_SUPPLY = "trader_supply",
TRADER_STANDING = "TraderStanding",
UNLOCK_TRADER = "UnlockTrader",
GROUP_MATCH_RAID_SETTINGS = "groupMatchRaidSettings",
@ -18,11 +24,17 @@ export declare enum NotificationEventType {
GROUP_MATCH_WAS_REMOVED = "groupMatchWasRemoved",
GROUP_MATCH_USER_BAD_VERSION = "groupMatchUserHasBadVersion",
USER_CONFIRMED = "userConfirmed",
USER_MATCHED = "UserMatched",
USER_MATCH_OVER = "userMatchOver",
CHANNEL_DELETED = "channel_deleted",
FRIEND_LIST_REQUEST_ACCEPTED = "friendListRequestAccept",
FRIEND_LIST_REQUEST_DECLINED = "friendListRequestDecline",
FRIEND_LIST_NEW_REQUEST = "friendListNewRequest",
FRIEND_LIST_REMOVED_FROM_FRIEND_LIST = "youAreRemovedFromFriendList",
YOU_ARE_ADDED_TO_IGNORE_LIST = "YouWereAddedToIgnoreList",
YOU_ARE_REMOVED_FROM_IGNORE_LIST = "youAreRemoveFromIgnoreList"
YOU_ARE_REMOVED_FROM_IGNORE_LIST = "youAreRemoveFromIgnoreList",
PROFILE_LOCK_TIMER = "ProfileLockTimer",
STASH_ROWS = "StashRows",
SKILL_POINTS = "SkillPoints",
TOURNAMENT_WARNING = "tournamentWarning"
}

View File

@ -52,5 +52,19 @@ export declare enum SkillTypes {
USEC_DEEP_WEAPON_MOD = "UsecDeepweaponmodding_Settings",
USEC_LONG_RANGE_OPTICS = "UsecLongrangeoptics_Settings",
USEC_NEGOTIATIONS = "UsecNegotiations",
USEC_TACTICS = "UsecTactics"
USEC_TACTICS = "UsecTactics",
PISTOL = "Pistol",
REVOLVER = "Revolver",
SMG = "SMG",
ASSAULT = "Assault",
SHOTGUN = "Shotgun",
SNIPER = "Sniper",
LMG = "LMG",
HMG = "HMG",
LAUNCHER = "Launcher",
ATTACHED_LAUNCHER = "AttachedLauncher",
MISC = "Misc",
DMR = "DMR",
DRAW_MASTER = "DrawMaster",
AIM_MASTER = "AimMaster"
}

View File

@ -0,0 +1,22 @@
import { Inventory as PmcInventory } from "@spt/models/eft/common/tables/IBotBase";
import { Chances, Mods } from "@spt/models/eft/common/tables/IBotType";
import { EquipmentFilters, RandomisationDetails } from "@spt/models/spt/config/IBotConfig";
export interface IGenerateEquipmentProperties {
/** Root Slot being generated */
rootEquipmentSlot: string;
/** Equipment pool for root slot being generated */
rootEquipmentPool: Record<string, number>;
modPool: Mods;
/** Dictionary of mod items and their chance to spawn for this bot type */
spawnChances: Chances;
/** Role being generated for */
botRole: string;
/** Level of bot being generated */
botLevel: number;
inventory: PmcInventory;
botEquipmentConfig: EquipmentFilters;
/** Settings from bot.json to adjust how item is generated */
randomisationDetails: RandomisationDetails;
/** OPTIONAL - Do not generate mods for tpls in this array */
generateModsBlacklist?: string[];
}

View File

@ -1,5 +1,5 @@
import { MinMax } from "@spt/models/common/MinMax";
import { IBaseConfig } from "./IBaseConfig";
import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig";
export interface IBTRConfig extends IBaseConfig {
kind: "spt-btr";
/** How fast the BTR moves */

View File

@ -43,6 +43,12 @@ export interface IBotConfig extends IBaseConfig {
lowProfileGasBlockTpls: string[];
/** What bottypes should be excluded from having loot generated on them (backpack/pocket/vest) does not disable food/drink/special/ */
disableLootOnBotTypes: string[];
assaultToBossConversion: IAssaultToBossConversion;
}
export interface IAssaultToBossConversion {
bossConvertEnabled: boolean;
bossesToConvertToWeights: Record<string, number>;
bossConvertMinMax: Record<string, MinMax>;
}
/** Number of bots to generate and store in cache on raid start per bot type */
export interface PresetBatch {

View File

@ -4,7 +4,7 @@ import { GiftSenderType } from "@spt/models/enums/GiftSenderType";
import { SeasonalEventType } from "@spt/models/enums/SeasonalEventType";
import { Traders } from "@spt/models/enums/Traders";
import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig";
import { IProfileChangeEvent } from "../dialog/ISendMessageDetails";
import { IProfileChangeEvent } from "@spt/models/spt/dialog/ISendMessageDetails";
export interface IGiftsConfig extends IBaseConfig {
kind: "spt-gifts";
gifts: Record<string, Gift>;

View File

@ -27,7 +27,8 @@ export interface FenceConfig {
presetPriceMult: number;
armorMaxDurabilityPercentMinMax: IItemDurabilityCurrentMax;
weaponDurabilityPercentMinMax: IItemDurabilityCurrentMax;
chancePlateExistsInArmorPercent: number;
/** Keyed to plate protection level */
chancePlateExistsInArmorPercent: Record<string, number>;
/** Key: item tpl */
itemStackSizeOverrideMinMax: Record<string, MinMax>;
itemTypeLimits: Record<string, number>;

View File

@ -0,0 +1,5 @@
import { IPmcDataRepeatableQuest, IRepeatableQuest } from "@spt/models/eft/common/tables/IRepeatableQuests";
export interface IGetRepeatableByIdResult {
quest: IRepeatableQuest;
repeatableType: IPmcDataRepeatableQuest;
}

View File

@ -11,4 +11,5 @@ export interface LootRequest {
itemStackLimits: Record<string, MinMax>;
armorLevelWhitelist: number[];
allowBossItems: boolean;
useRewarditemBlacklist?: boolean;
}

View File

@ -1,11 +1,11 @@
import { SaveLoadRouter } from "@spt/di/Router";
import { ISptProfile, Info } from "@spt/models/eft/profile/ISptProfile";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
import { LocalisationService } from "@spt/services/LocalisationService";
import { HashUtil } from "@spt/utils/HashUtil";
import { JsonUtil } from "@spt/utils/JsonUtil";
import { VFS } from "@spt/utils/VFS";
import { ConfigServer } from "./ConfigServer";
export declare class SaveServer {
protected vfs: VFS;
protected saveLoadRouters: SaveLoadRouter[];

View File

@ -3,10 +3,10 @@ import http, { IncomingMessage } from "node:http";
import { WebSocket, Server } from "ws";
import { HttpServerHelper } from "@spt/helpers/HttpServerHelper";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { IWebSocketConnectionHandler } from "@spt/servers/ws/IWebSocketConnectionHandler";
import { LocalisationService } from "@spt/services/LocalisationService";
import { JsonUtil } from "@spt/utils/JsonUtil";
import { RandomUtil } from "@spt/utils/RandomUtil";
import { IWebSocketConnectionHandler } from "./ws/IWebSocketConnectionHandler";
export declare class WebSocketServer {
protected logger: ILogger;
protected randomUtil: RandomUtil;

View File

@ -8,9 +8,9 @@ import { IHttpConfig } from "@spt/models/spt/config/IHttpConfig";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
import { IWebSocketConnectionHandler } from "@spt/servers/ws/IWebSocketConnectionHandler";
import { ISptWebSocketMessageHandler } from "@spt/servers/ws/message/ISptWebSocketMessageHandler";
import { LocalisationService } from "@spt/services/LocalisationService";
import { JsonUtil } from "@spt/utils/JsonUtil";
import { ISptWebSocketMessageHandler } from "./message/ISptWebSocketMessageHandler";
export declare class SptWebSocketConnectionHandler implements IWebSocketConnectionHandler {
protected logger: ILogger;
protected profileHelper: ProfileHelper;

View File

@ -19,7 +19,7 @@ import { ISettingsBase } from "@spt/models/spt/server/ISettingsBase";
import { ITemplates } from "@spt/models/spt/templates/ITemplates";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { DatabaseServer } from "@spt/servers/DatabaseServer";
import { LocalisationService } from "./LocalisationService";
import { LocalisationService } from "@spt/services/LocalisationService";
export declare class DatabaseService {
protected logger: ILogger;
protected databaseServer: DatabaseServer;
@ -52,7 +52,7 @@ export declare class DatabaseService {
getLocations(): ILocations;
/**
* Get specific location by its Id
* @param locationId Desired trader id
* @param locationId Desired location id
* @returns assets/database/locations/
*/
getLocation(locationId: string): ILocation;

View File

@ -4,7 +4,7 @@ import { PresetHelper } from "@spt/helpers/PresetHelper";
import { IFenceLevel } from "@spt/models/eft/common/IGlobals";
import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { Item, Repairable } from "@spt/models/eft/common/tables/IItem";
import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem";
import { ITemplateItem, Slot } from "@spt/models/eft/common/tables/ITemplateItem";
import { IBarterScheme, ITraderAssort } from "@spt/models/eft/common/tables/ITrader";
import { IItemDurabilityCurrentMax, ITraderConfig } from "@spt/models/spt/config/ITraderConfig";
import { ICreateFenceAssortsResult } from "@spt/models/spt/fence/ICreateFenceAssortsResult";
@ -254,6 +254,19 @@ export declare class FenceService {
* @param itemDbDetails Armor items db template
*/
protected randomiseArmorModDurability(armor: Item[], itemDbDetails: ITemplateItem): void;
/**
* Randomise the durability values of items on armor with a passed in slot
* @param softInsertSlots Slots of items to randomise
* @param armorItemAndMods Array of armor + inserts to get items from
*/
protected randomiseArmorSoftInsertDurabilities(softInsertSlots: Slot[], armorItemAndMods: Item[]): void;
/**
* Randomise the durability values of plate items in armor
* Has chance to remove plate
* @param plateSlots Slots of items to randomise
* @param armorItemAndMods Array of armor + inserts to get items from
*/
protected randomiseArmorInsertsDurabilities(plateSlots: Slot[], armorItemAndMods: Item[]): void;
/**
* Get stack size of a singular item (no mods)
* @param itemDbDetails item being added to fence

View File

@ -1,6 +1,6 @@
# Welcome to the SPT Modding Project
# Welcome to the SPT-AKI Modding Project
This project is designed to streamline the initial setup process for building and creating mods in the SPT environment. Follow this guide to set up your environment efficiently.
This project is designed to streamline the initial setup process for building and creating mods in the SPT-AKI environment. Follow this guide to set up your environment efficiently.
## **Table of Contents**
- [NodeJS Setup](#nodejs-setup)
@ -39,7 +39,7 @@ Note: Preserve the `node_modules` folder as it contains necessary dependencies f
## **Essential Concepts**
Prioritize understanding Dependency Injection and Inversion of Control, the architectural principles SPT adopts. Comprehensive guidelines will be available on the hub upon release.
Prioritize understanding Dependency Injection and Inversion of Control, the architectural principles SPT-AKI adopts. Comprehensive guidelines will be available on the hub upon release.
Some resources to get you started:
- [A quick intro to Dependency Injection](https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f/)
@ -47,13 +47,13 @@ Some resources to get you started:
## **Coding Guidelines**
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"sptVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"akiVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
## **Distribution Guidelines**
Automated tasks are set up to bundle all necessary files for your mod to function in SPT:
Automated tasks are set up to bundle all necessary files for your mod to function in SPT-AKI:
> Terminal -> Run Task... -> Show All Tasks... -> npm: build
@ -61,6 +61,6 @@ The ZIP output, located in the `dist` directory, contains all required files. En
## **Conclusion**
With this setup, you're ready to begin modding with SPT. If you run into any trouble be sure to check out the [modding documentation on the hub](https://hub.sp-tarkov.com/doc/lexicon/66-modding/). If you really get stuck feel free to join us in the [#mods-development](https://discord.com/channels/875684761291599922/875803116409323562) official Discord channel.
With this setup, you're ready to begin modding with SPT-AKI. If you run into any trouble be sure to check out the [modding documentation on the hub](https://hub.sp-tarkov.com/doc/lexicon/66-modding/). If you really get stuck feel free to join us in the [#mods-development](https://discord.com/channels/875684761291599922/875803116409323562) official Discord channel.
Build something awesome!

View File

@ -1,7 +1,7 @@
{
"name": "ClassExtensionOverride",
"version": "1.0.0",
"sptVersion": "~3.9",
"akiVersion": "~3.9",
"loadBefore": [],
"loadAfter": [],
"incompatibilities": [],

View File

@ -1,12 +1,12 @@
import { inject, injectable } from "tsyringe";
import { LauncherCallbacks } from "@spt/callbacks/LauncherCallbacks";
import { LauncherController } from "@spt/controllers/LauncherController";
import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { SaveServer } from "@spt/servers/SaveServer";
import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil";
import { Watermark } from "@spt/utils/Watermark";
import { LauncherCallbacks } from "@spt-aki/callbacks/LauncherCallbacks";
import { LauncherController } from "@spt-aki/controllers/LauncherController";
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { SaveServer } from "@spt-aki/servers/SaveServer";
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
import { Watermark } from "@spt-aki/utils/Watermark";
// We need to declare this class as injectable, this will add the container
// metadata

View File

@ -1,22 +1,22 @@
import { DependencyContainer } from "tsyringe";
import { IPreSptLoadMod } from "@spt/models/external/IPreSptLoadMod"
import { IPreAkiLoadMod } from "@spt-aki/models/external/IPreAkiLoadMod"
import { MyCustomLauncherCallbacks } from "./MyCustomLauncherCallbacks";
class Mod implements IPreSptLoadMod
class Mod implements IPreAkiLoadMod
{
// This example will show you how to override and register your own components and use them
// The container will by default register all SPT dependencies, but you can inject into it
// The container will by default register all AKI dependencies, but you can inject into it
// you own custom implementations the server will then use.
// In this example we will take the LauncherCallbacks class and override the ping() method
// for our own custom method that will return "Lets dance" instead of "pong!"
// Perform these actions before server fully loads
public preSptLoad(container: DependencyContainer): void {
public preAkiLoad(container: DependencyContainer): void {
// Here we register our override for the component and we NEED to use the same
// token the server is using to register it.
// You can find this tokens here:
// https://dev.sp-tarkov.com/SPT/Server/src/branch/development/project/src/di/Container.ts
// https://dev.sp-tarkov.com/SPT-AKI/Server/src/branch/development/project/src/di/Container.ts
// In this scenario we want to override LauncherCallbacks, so we find the proper registry:
//
// depContainer.register<LauncherCallbacks>("LauncherCallbacks", { useClass: LauncherCallbacks });

Some files were not shown because too many files have changed in this diff Show More