Updated types and readme to 3.10.2

This commit is contained in:
Chomp 2024-12-07 15:02:59 +00:00
parent facdd2b687
commit e532454053
505 changed files with 8597 additions and 3837 deletions

View File

@ -1,4 +1,4 @@
# Mod examples for v3.10.1
# Mod examples for v3.10.2
A collection of example mods that perform typical actions in SPT

View File

@ -118,6 +118,9 @@ export declare class ProfileController {
* Handle client/profile/status
*/
getProfileStatus(sessionId: string): IGetProfileStatusResponseData;
/**
* Handle client/profile/view
*/
getOtherProfile(sessionId: string, request: IGetOtherProfileRequest): IGetOtherProfileResponse;
/**
* Handle client/profile/settings

View File

@ -114,9 +114,10 @@ export declare class BotEquipmentModGenerator {
/**
* Sort mod slots into an ordering that maximises chance of a successful weapon generation
* @param unsortedSlotKeys Array of mod slot strings to sort
* @param itemTplWithKeysToSort The Tpl of the item with mod keys being sorted
* @returns Sorted array
*/
protected sortModKeys(unsortedSlotKeys: string[]): string[];
protected sortModKeys(unsortedSlotKeys: string[], itemTplWithKeysToSort: string): string[];
/**
* Get a Slot property for an item (chamber/cartridge/slot)
* @param modSlot e.g patron_in_weapon

View File

@ -12,6 +12,7 @@ import { IBarterScheme } from "@spt/models/eft/common/tables/ITrader";
import { IOfferRequirement, IRagfairOffer, IRagfairOfferUser } from "@spt/models/eft/ragfair/IRagfairOffer";
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
import { IArmorPlateBlacklistSettings, IBarterDetails, IDynamic, IRagfairConfig } from "@spt/models/spt/config/IRagfairConfig";
import { ITraderConfig } from "@spt/models/spt/config/ITraderConfig";
import { ITplWithFleaPrice } from "@spt/models/spt/ragfair/ITplWithFleaPrice";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
@ -47,6 +48,7 @@ export declare class RagfairOfferGenerator {
protected configServer: ConfigServer;
protected cloner: ICloner;
protected ragfairConfig: IRagfairConfig;
protected traderConfig: ITraderConfig;
protected botConfig: IBotConfig;
protected allowedFleaPriceItemsForBarter: {
tpl: string;
@ -83,7 +85,7 @@ export declare class RagfairOfferGenerator {
* @param isTrader Is the user creating the offer a trader
* @returns IRagfairOfferUser
*/
createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser;
protected createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser;
/**
* Calculate the offer price that's listed on the flea listing
* @param offerRequirements barter requirements for offer

View File

@ -209,4 +209,10 @@ export declare class ProfileHelper {
* @returns Array of item objects
*/
getQuestItemsInProfile(profile: IPmcData): IItem[];
/**
* Return a favorites array in the format expected by the getOtherProfile call
* @param profile
* @returns An array of IItem objects representing the favorited data
*/
getOtherProfileFavorites(profile: IPmcData): IItem[];
}

View File

@ -282,10 +282,10 @@ export declare class QuestHelper {
*/
protected findAndAddHideoutProductionIdToProfile(pmcData: IPmcData, craftUnlockReward: IQuestReward, questDetails: IQuest, sessionID: string, response: IItemEventRouterResponse): void;
/**
* Find hideout craft id for the specified quest reward
* @param craftUnlockReward
* @param questDetails
* @returns
* Find hideout craft for the specified quest reward
* @param craftUnlockReward Reward item from quest with craft unlock details
* @param questDetails Quest with craft unlock reward
* @returns Hideout craft
*/
getRewardProductionMatch(craftUnlockReward: IQuestReward, questDetails: IQuest): IHideoutProduction[];
/**
@ -332,16 +332,15 @@ export declare class QuestHelper {
/**
* Create a clone of the given quest array with the rewards updated to reflect the
* given game version
*
* @param quests The list of quests to check
* @param gameVersion The game version of the profile
* @returns array of IQuest objects with the rewards filtered correctly for the game version
* @param quests List of quests to check
* @param gameVersion Game version of the profile
* @returns Array of IQuest objects with the rewards filtered correctly for the game version
*/
protected updateQuestsForGameEdition(quests: IQuest[], gameVersion: string): IQuest[];
/**
* Return a list of quests that would fail when supplied quest is completed
* @param completedQuestId quest completed id
* @returns array of IQuest objects
* @param completedQuestId Quest completed id
* @returns Array of IQuest objects
*/
protected getQuestsFromProfileFailedByCompletingQuest(completedQuestId: string, pmcProfile: IPmcData): IQuest[];
/**

View File

@ -67,6 +67,13 @@ export declare class RagfairOfferHelper {
* @returns Offers the player should see
*/
getValidOffers(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record<string, ITraderAssort>, pmcData: IPmcData): IRagfairOffer[];
/**
* Disable offer if item is flagged by tiered flea config
* @param tieredFlea Tiered flea settings from ragfair config
* @param offer Ragfair offer to check
* @param tieredFleaLimitTypes Dict of item types with player level to be viewable
* @param playerLevel Level of player viewing offer
*/
protected checkAndLockOfferFromPlayerTieredFlea(tieredFlea: ITieredFlea, offer: IRagfairOffer, tieredFleaLimitTypes: string[], playerLevel: number): void;
/**
* Get matching offers that require the desired item and filter out offers from non traders if player is below ragfair unlock level
@ -99,14 +106,14 @@ export declare class RagfairOfferHelper {
*/
traderOfferItemQuestLocked(offer: IRagfairOffer, traderAssorts: Record<string, ITraderAssort>): boolean;
/**
* Has a traders offer ran out of stock to sell to player
* Has trader offer ran out of stock to sell to player
* @param offer Offer to check stock of
* @returns true if out of stock
*/
protected traderOutOfStock(offer: IRagfairOffer): boolean;
/**
* Check if trader offers' BuyRestrictionMax value has been reached
* @param offer offer to check restriction properties of
* @param offer Offer to check restriction properties of
* @returns true if restriction reached, false if no restrictions/not reached
*/
protected traderBuyRestrictionReached(offer: IRagfairOffer): boolean;
@ -114,7 +121,7 @@ export declare class RagfairOfferHelper {
* Get an array of flea offers that are inaccessible to player due to their inadequate loyalty level
* @param offers Offers to check
* @param pmcProfile Players profile with trader loyalty levels
* @returns array of offer ids player cannot see
* @returns Array of offer ids player cannot see
*/
protected getLoyaltyLockedOffers(offers: IRagfairOffer[], pmcProfile: IPmcData): string[];
/**
@ -126,7 +133,7 @@ export declare class RagfairOfferHelper {
/**
* Count up all rootitem StackObjectsCount properties of an array of items
* @param itemsInInventoryToList items to sum up
* @returns Total count
* @returns Total stack count
*/
getTotalStackCountSize(itemsInInventoryToList: IItem[][]): number;
/**
@ -164,16 +171,16 @@ export declare class RagfairOfferHelper {
protected getLocalisedOfferSoldMessage(itemTpl: string, boughtAmount: number): string;
/**
* Check an offer passes the various search criteria the player requested
* @param searchRequest
* @param offer
* @param pmcData
* @returns True
* @param searchRequest Client search request
* @param offer Offer to check
* @param pmcData Player profile
* @returns True if offer passes criteria
*/
protected passesSearchFilterCriteria(searchRequest: ISearchRequestData, offer: IRagfairOffer, pmcData: IPmcData): boolean;
/**
* Check that the passed in offer item is functional
* @param offerRootItem The root item of the offer
* @param offer The flea offer
* @param offer Flea offer to check
* @returns True if the given item is functional
*/
isItemFunctional(offerRootItem: IItem, offer: IRagfairOffer): boolean;
@ -181,7 +188,7 @@ export declare class RagfairOfferHelper {
* Should a ragfair offer be visible to the player
* @param searchRequest Search request
* @param itemsToAdd ?
* @param traderAssorts Trader assort items
* @param traderAssorts Trader assort items - used for filtering out locked trader items
* @param offer The flea offer
* @param pmcProfile Player profile
* @returns True = should be shown to player

View File

@ -44,10 +44,10 @@ export declare class TraderAssortHelper {
* Filter out assorts not unlocked due to level OR quest completion
* @param sessionId session id
* @param traderId traders id
* @param flea Should assorts player hasn't unlocked be returned - default false
* @param showLockedAssorts Should assorts player hasn't unlocked be returned - default false
* @returns a traders' assorts
*/
getAssort(sessionId: string, traderId: string, flea?: boolean): ITraderAssort;
getAssort(sessionId: string, traderId: string, showLockedAssorts?: boolean): ITraderAssort;
/**
* Given the blacklist provided, remove root items from assort
* @param assortToFilter Trader assort to modify
@ -75,20 +75,10 @@ export declare class TraderAssortHelper {
* @returns true they need refreshing
*/
traderAssortsHaveExpired(traderID: string): boolean;
/**
* Iterate over all assorts barter_scheme values, find barters selling for money and multiply by multipler in config
* @param traderAssort Assorts to multiple price of
*/
protected multiplyItemPricesByConfigMultiplier(traderAssort: ITraderAssort): void;
/**
* Get an array of pristine trader items prior to any alteration by player (as they were on server start)
* @param traderId trader id
* @returns array of Items
*/
protected getPristineTraderAssorts(traderId: string): IItem[];
/**
* Returns generated ragfair offers in a trader assort format
* @returns Trader assort object
*/
protected getRagfairDataAsTraderAssort(): ITraderAssort;
}

View File

@ -153,7 +153,7 @@ export interface IInventory {
/** Key is hideout area enum numeric as string e.g. "24", value is area _id */
hideoutAreaStashes: Record<string, string>;
fastPanel: Record<string, string>;
favoriteItems: IItem[];
favoriteItems: string[];
}
export interface IBaseJsonSkills {
Common: Record<string, Common>;

View File

@ -169,6 +169,13 @@ export interface ISpt {
freeRepeatableRefreshUsedCount?: Record<string, number>;
/** When was a profile migrated, value is timestamp */
migrations?: Record<string, number>;
/** Cultist circle rewards received that are one time use, key (md5) is a combination of sacrificed + reward items */
cultistRewards?: Map<string, IAcceptedCultistReward>;
}
export interface IAcceptedCultistReward {
timestamp: number;
sacrificeItems: string[];
rewardItems: string[];
}
export interface IModDetails {
name: string;

View File

@ -0,0 +1,4 @@
export declare enum CircleRewardType {
RANDOM = 0,
HIDEOUT_TASK = 1
}

View File

@ -18,11 +18,21 @@ export interface ICultistCircleSettings {
maxRewardItemCount: number;
maxAttemptsToPickRewardsWithinBudget: number;
rewardPriceMultiplerMinMax: MinMax;
/** The odds that meeting the highest threshold gives you a bonus to crafting time */
bonusAmountMultiplier: number;
bonusChanceMultiplier: number;
/** What is considered a "high-value" item */
highValueThresholdRub: number;
/** Hideout/task reward crafts have a unique craft time */
hideoutTaskRewardTimeSeconds: number;
/** Rouble amount player needs to sacrifice to get chance of hideout/task rewards */
hideoutCraftSacrificeThresholdRub: number;
craftTimeThreshholds: ICraftTimeThreshhold[];
/** -1 means no override */
/** -1 means no override, value in seconds */
craftTimeOverride: number;
/** Specific reward pool when player sacrificed one specific item */
directRewards: Record<string, IDirectRewardSettings>;
/** Specific reward pool when player sacrifice specific item(s) */
directRewards: IDirectRewardSettings[];
/** Overrides for reward stack sizes, keyed by item tpl */
directRewardStackSize: Record<string, MinMax>;
/** Item tpls to exclude from the reward pool */
rewardItemBlacklist: string[];
@ -34,6 +44,9 @@ export interface ICraftTimeThreshhold extends MinMax {
craftTimeSeconds: number;
}
export interface IDirectRewardSettings {
rewardTpls: string[];
reward: string[];
requiredItems: string[];
craftTimeSeconds: number;
/** Is the reward a one time reward or can it be given multiple times */
repeatable: boolean;
}

View File

@ -4,10 +4,10 @@ import { ILootRequest } from "@spt/models/spt/services/ILootRequest";
export interface ITraderConfig extends IBaseConfig {
kind: "spt-trader";
updateTime: IUpdateTime[];
updateTimeDefault: number;
purchasesAreFoundInRaid: boolean;
/** Should trader reset times be set based on server start time (false = bsg time - on the hour) */
tradersResetFromServerStart: boolean;
updateTimeDefault: number;
traderPriceMultipler: number;
fence: IFenceConfig;
moddedTraders: IModdedTraders;

View File

@ -0,0 +1,8 @@
import { CircleRewardType } from "@spt/models/enums/hideout/CircleRewardType";
import { ICraftTimeThreshhold } from "@spt/models/spt/config/IHideoutConfig";
export interface ICircleCraftDetails {
time: number;
rewardType: CircleRewardType;
rewardAmountRoubles: number;
rewardDetails?: ICraftTimeThreshhold;
}

View File

@ -3,14 +3,17 @@ import { InventoryHelper } from "@spt/helpers/InventoryHelper";
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { PresetHelper } from "@spt/helpers/PresetHelper";
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
import { QuestHelper } from "@spt/helpers/QuestHelper";
import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { IBotHideoutArea } from "@spt/models/eft/common/tables/IBotBase";
import { IItem } from "@spt/models/eft/common/tables/IItem";
import { IStageRequirement } from "@spt/models/eft/hideout/IHideoutArea";
import { IHideoutCircleOfCultistProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutCircleOfCultistProductionStartRequestData";
import { IHideoutProduction, IHideoutProductionData, IRequirement, IRequirementBase } from "@spt/models/eft/hideout/IHideoutProduction";
import { IRequirement, IRequirementBase } from "@spt/models/eft/hideout/IHideoutProduction";
import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse";
import { IDirectRewardSettings, IHideoutConfig } from "@spt/models/spt/config/IHideoutConfig";
import { ICraftTimeThreshhold, ICultistCircleSettings, IDirectRewardSettings, IHideoutConfig } from "@spt/models/spt/config/IHideoutConfig";
import { ICircleCraftDetails } from "@spt/models/spt/hideout/ICircleCraftDetails";
import { IHideout } from "@spt/models/spt/hideout/IHideout";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { EventOutputHolder } from "@spt/routers/EventOutputHolder";
import { ConfigServer } from "@spt/servers/ConfigServer";
@ -33,13 +36,14 @@ export declare class CircleOfCultistService {
protected profileHelper: ProfileHelper;
protected inventoryHelper: InventoryHelper;
protected hideoutHelper: HideoutHelper;
protected questHelper: QuestHelper;
protected databaseService: DatabaseService;
protected itemFilterService: ItemFilterService;
protected seasonalEventService: SeasonalEventService;
protected configServer: ConfigServer;
protected static circleOfCultistSlotId: string;
protected hideoutConfig: IHideoutConfig;
constructor(logger: ILogger, timeUtil: TimeUtil, cloner: ICloner, eventOutputHolder: EventOutputHolder, randomUtil: RandomUtil, hashUtil: HashUtil, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, inventoryHelper: InventoryHelper, hideoutHelper: HideoutHelper, databaseService: DatabaseService, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer);
constructor(logger: ILogger, timeUtil: TimeUtil, cloner: ICloner, eventOutputHolder: EventOutputHolder, randomUtil: RandomUtil, hashUtil: HashUtil, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, inventoryHelper: InventoryHelper, hideoutHelper: HideoutHelper, questHelper: QuestHelper, databaseService: DatabaseService, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer);
/**
* Start a sacrifice event
* Generate rewards
@ -50,24 +54,38 @@ export declare class CircleOfCultistService {
* @returns IItemEventRouterResponse
*/
startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse;
/**
* Create a map of the possible direct rewards, keyed by the items needed to be sacrificed
* @param directRewards Direct rewards array from hideout config
* @returns Map
*/
protected generateSacrificedItemsCache(directRewards: IDirectRewardSettings[]): Map<string, IDirectRewardSettings>;
/**
* Get the reward amount multiple value based on players hideout management skill + configs rewardPriceMultiplerMinMax values
* @param pmcData Player profile
* @param cultistCircleSettings Circle config settings
* @returns Reward Amount Multipler
*/
protected getRewardAmountMultipler(pmcData: IPmcData, cultistCircleSettings: ICultistCircleSettings): number;
/**
* Register production inside player profile
* @param sessionId Session id
* @param pmcData Player profile
* @param recipeId Recipe id
* @param sacrificedItems Items player sacrificed
* @param rewardAmountRoubles Rouble amount to reward player in items with
* @param directRewardSettings OPTIONAL: If craft is giving direct rewards
* @param craftingTime How long the ritual should take
*/
protected registerCircleOfCultistProduction(sessionId: string, pmcData: IPmcData, recipeId: string, sacrificedItems: IItem[], rewardAmountRoubles: number, directRewardSettings?: IDirectRewardSettings): void;
protected registerCircleOfCultistProduction(sessionId: string, pmcData: IPmcData, recipeId: string, sacrificedItems: IItem[], craftingTime: number): void;
/**
* Get the circle craft time as seconds, value is based on reward item value
* OR rewards are direct, then use custom craft time defined in oarameter object
* And get the bonus status to determine what tier of reward is given
* @param rewardAmountRoubles Value of rewards in roubles
* @param directRewardSettings OPTIONAL: If craft is giving direct rewards
* @returns craft time seconds
* @param circleConfig Circle config values
* @param directRewardSettings OPTIONAL - Values related to direct reward being given
* @returns craft time + type of reward + reward details
*/
protected getCircleCraftTimeSeconds(rewardAmountRoubles: number, directRewardSettings?: IDirectRewardSettings): number;
protected getCircleCraftingInfo(rewardAmountRoubles: number, circleConfig: ICultistCircleSettings, directRewardSettings?: IDirectRewardSettings): ICircleCraftDetails;
protected getMatchingThreshold(thresholds: ICraftTimeThreshhold[], rewardAmountRoubles: number): ICraftTimeThreshhold;
/**
* Get the items player sacrificed in circle
* @param pmcData Player profile
@ -81,20 +99,40 @@ export declare class CircleOfCultistService {
* @param cultistCircleStashId Id of stash item
* @returns Array of item arrays
*/
protected getRewardsWithinBudget(rewardItemTplPool: string[], rewardBudget: number, cultistCircleStashId: string): IItem[][];
protected getRewardsWithinBudget(rewardItemTplPool: string[], rewardBudget: number, cultistCircleStashId: string, circleConfig: ICultistCircleSettings): IItem[][];
/**
* Give every item as a reward that's passed in
* @param rewardTpls Item tpls to turn into reward items
* Get direct rewards
* @param sessionId sessionId
* @param directReward Items sacrificed
* @param cultistCircleStashId Id of stash item
* @returns Array of item arrays
* @returns The reward object
*/
protected getExplicitRewards(explicitRewardSettings: IDirectRewardSettings, cultistCircleStashId: string): IItem[][];
protected getDirectRewards(sessionId: string, directReward: IDirectRewardSettings, cultistCircleStashId: string): IItem[][];
/**
* Check for direct rewards from what player sacrificed
* @param sessionId sessionId
* @param sacrificedItems Items sacrificed
* @returns Direct reward items to send to player
*/
protected checkForDirectReward(sessionId: string, sacrificedItems: IItem[], directRewardsCache: Map<string, IDirectRewardSettings>): IDirectRewardSettings;
/**
* Create an md5 key of the sacrificed + reward items
* @param directReward Direct reward to create key for
* @returns Key
*/
protected getDirectRewardHashKey(directReward: IDirectRewardSettings): string;
/**
* Explicit rewards have thier own stack sizes as they dont use a reward rouble pool
* @param rewardTpl Item being rewarded to get stack size of
* @returns stack size of item
*/
protected getExplicitRewardBaseTypeStackSize(rewardTpl: string): number;
protected getDirectRewardBaseTypeStackSize(rewardTpl: string): number;
/**
* Add a record to the players profile to signal they have accepted a non-repeatable direct reward
* @param sessionId Session id
* @param directReward Reward sent to player
*/
protected flagDirectRewardAsAcceptedInProfile(sessionId: string, directReward: IDirectRewardSettings): void;
/**
* Get the size of a reward items stack
* 1 for everything except ammo, ammo can be between min stack and max stack
@ -107,9 +145,26 @@ export declare class CircleOfCultistService {
* Get a pool of tpl IDs of items the player needs to complete hideout crafts/upgrade areas
* @param sessionId Session id
* @param pmcData Profile of player who will be getting the rewards
* @param rewardType Do we return bonus items (hideout/task items)
* @param cultistCircleConfig Circle config
* @returns Array of tpls
*/
protected getCultistCircleRewardPool(sessionId: string, pmcData: IPmcData): string[];
protected getCultistCircleRewardPool(sessionId: string, pmcData: IPmcData, craftingInfo: ICircleCraftDetails, cultistCircleConfig: ICultistCircleSettings): string[];
/**
* Check players profile for quests with hand-in requirements and add those required items to the pool
* @param pmcData Player profile
* @param itemRewardBlacklist Items not to add to pool
* @param rewardPool Pool to add items to
*/
protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set<string>): void;
/**
* Adds items the player needs to complete hideout crafts/upgrades to the reward pool
* @param hideoutDbData Hideout area data
* @param pmcData Player profile
* @param itemRewardBlacklist Items not to add to pool
* @param rewardPool Pool to add items to
*/
protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set<string>): void;
/**
* Get all active hideout areas
* @param areas Hideout areas to iterate over
@ -117,12 +172,13 @@ export declare class CircleOfCultistService {
*/
protected getPlayerAccessibleHideoutAreas(areas: IBotHideoutArea[]): IBotHideoutArea[];
/**
* Get all recipes the player has access to, includes base + unlocked recipes
* @param unlockedRecipes Recipes player has flagged as unlocked
* @param allRecipes All recipes
* @returns Array of recipes
* Get array of random reward items
* @param rewardPool Reward pool to add to
* @param itemRewardBlacklist Reward Blacklist
* @param itemsShouldBeHighValue Should these items meet the valuable threshold
* @returns rewardPool
*/
protected getPlayerAccessibleRecipes(unlockedRecipes: string[], allRecipes: IHideoutProductionData): IHideoutProduction[];
protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set<string>, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set<string>;
/**
* Iterate over passed in hideout requirements and return the Item
* @param requirements Requirements to iterate over

View File

@ -87,6 +87,12 @@ export declare class ProfileFixerService {
* @returns
*/
protected verifyQuestProductionUnlock(pmcProfile: IPmcData, productionUnlockReward: IQuestReward, questDetails: IQuest): void;
/**
* Initial release of SPT 3.10 used an incorrect favorites structure, reformat
* the structure to the correct MongoID array structure
* @param pmcProfile
*/
protected fixFavorites(pmcProfile: IPmcData): void;
/**
* If the profile has elite Hideout Managment skill, add the additional slots from globals
* NOTE: This seems redundant, but we will leave it here just incase.

View File

@ -138,6 +138,12 @@ export declare class SeasonalEventService {
*/
protected enableHalloweenSummonEvent(): void;
protected configureZombies(zombieSettings: IZombieSettings): void;
/**
* Get location ids of maps with an infection above 0
* @param locationInfections Dict of locations with their infection percentage
* @returns Array of location ids
*/
protected getLocationsWithZombies(locationInfections: Record<string, number>): string[];
/**
* BSG store the location ids differently inside `LocationInfection`, need to convert to matching location IDs
* @param infectedLocationKey Key to convert

View File

@ -1,38 +0,0 @@
import { ILogger } from "@spt/models/spt/utils/ILogger";
export declare class DatabaseDecompressionUtil {
protected logger: ILogger;
private compressedDir;
private assetsDir;
private compiled;
constructor(logger: ILogger);
/**
* Checks if the application is running in a compiled environment. A simple check is done to see if the relative
* assets directory exists. If it does not, the application is assumed to be running in a compiled environment. All
* relative asset paths are different within a compiled environment, so this simple check is sufficient.
*/
private isCompiled;
/**
* Initializes the database compression utility.
*
* This method will decompress all 7-zip archives within the compressed database directory. The decompressed files
* are placed in their respective directories based on the name and location of the compressed file.
*/
initialize(): Promise<void>;
/**
* Retrieves a list of all 7-zip archives within the compressed database directory.
*/
private getCompressedFiles;
/**
* Processes a compressed file by checking if the target directory is empty, and if so, decompressing the file into
* the target directory.
*/
private processCompressedFile;
/**
* Checks if a directory exists and is empty.
*/
private isDirectoryEmpty;
/**
* Decompresses a 7-zip archive to the target directory.
*/
private decompressFile;
}

View File

@ -106,77 +106,177 @@ export declare class RandomUtil {
protected cloner: ICloner;
protected logger: ILogger;
constructor(cloner: ICloner, logger: ILogger);
/**
* Generates a secure random number between 0 (inclusive) and 1 (exclusive).
*
* This method uses the `crypto` module to generate a 48-bit random integer,
* which is then divided by the maximum possible 48-bit integer value to
* produce a floating-point number in the range [0, 1).
*
* @returns A secure random number between 0 (inclusive) and 1 (exclusive).
*/
private getSecureRandomNumber;
/**
* Generates a random integer between the specified minimum and maximum values, inclusive.
*
* @param min - The minimum value (inclusive).
* @param max - The maximum value (inclusive).
* @returns A random integer between the specified minimum and maximum values.
*/
getInt(min: number, max: number): number;
/**
* Generates a random integer between 1 (inclusive) and the specified maximum value (exclusive).
* If the maximum value is less than or equal to 1, it returns 1.
*
* @param max - The upper bound (exclusive) for the random integer generation.
* @returns A random integer between 1 and max - 1, or 1 if max is less than or equal to 1.
*/
getIntEx(max: number): number;
/**
* Generates a random floating-point number within the specified range.
*
* @param min - The minimum value of the range (inclusive).
* @param max - The maximum value of the range (exclusive).
* @returns A random floating-point number between `min` (inclusive) and `max` (exclusive).
*/
getFloat(min: number, max: number): number;
/**
* Generates a random boolean value.
*
* @returns A random boolean value, where the probability of `true` and `false` is approximately equal.
*/
getBool(): boolean;
/**
* Calculates the percentage of a given number and returns the result.
*
* @param percent - The percentage to calculate.
* @param number - The number to calculate the percentage of.
* @param toFixed - The number of decimal places to round the result to (default is 2).
* @returns The calculated percentage of the given number, rounded to the specified number of decimal places.
*/
getPercentOfValue(percent: number, number: number, toFixed?: number): number;
/**
* Reduce a value by a percentage
* @param number Value to reduce
* @param percentage Percentage to reduce value by
* @returns Reduced value
* Reduces a given number by a specified percentage.
*
* @param number - The original number to be reduced.
* @param percentage - The percentage by which to reduce the number.
* @returns The reduced number after applying the percentage reduction.
*/
reduceValueByPercent(number: number, percentage: number): number;
/**
* Check if number passes a check out of 100
* @param chancePercent value check needs to be above
* @returns true if value passes check
* Determines if a random event occurs based on the given chance percentage.
*
* @param chancePercent - The percentage chance (0-100) that the event will occur.
* @returns `true` if the event occurs, `false` otherwise.
*/
getChance100(chancePercent: number): boolean;
/**
* Returns a random string from the provided array of strings.
*
* This method is separate from getArrayValue so we can use a generic inferance with getArrayValue.
*
* @param arr - The array of strings to select a random value from.
* @returns A randomly selected string from the array.
*/
getStringArrayValue(arr: string[]): string;
/**
* Returns a random element from the provided array.
*
* @template T - The type of elements in the array.
* @param arr - The array from which to select a random element.
* @returns A random element from the array.
*/
getArrayValue<T>(arr: T[]): T;
/**
* Retrieves a random key from the given object.
*
* @param node - The object from which to retrieve a key.
* @returns A string representing one of the keys of the node object.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
getKey(node: any): string;
/**
* Retrieves the value associated with a key from the given node object.
*
* @param node - An object with string keys and any type of values.
* @returns The value associated with the key obtained from the node.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
getKeyValue(node: {
[x: string]: any;
}): any;
/**
* Generate a normally distributed random number
* Uses the Box-Muller transform
* @param {number} mean Mean of the normal distribution
* @param {number} sigma Standard deviation of the normal distribution
* @returns {number} The value drawn
* Generates a normally distributed random number using the Box-Muller transform.
*
* @param mean - The mean (μ) of the normal distribution.
* @param sigma - The standard deviation (σ) of the normal distribution.
* @param attempt - The current attempt count to generate a valid number (default is 0).
* @returns A normally distributed random number.
*
* @remarks
* This function uses the Box-Muller transform to generate a normally distributed random number.
* If the generated number is less than 0, it will recursively attempt to generate a valid number up to 100 times.
* If it fails to generate a valid number after 100 attempts, it will return a random float between 0.01 and twice the mean.
*/
getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number;
/**
* Draw Random integer low inclusive, high exclusive
* if high is not set we draw from 0 to low (exclusive)
* @param {integer} low Lower bound inclusive, when high is not set, this is high
* @param {integer} high Higher bound exclusive
* @returns {integer} The random integer in [low, high)
* Generates a random integer between the specified range.
*
* @param low - The lower bound of the range (inclusive).
* @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`.
* @returns A random integer within the specified range.
*/
randInt(low: number, high?: number): number;
/**
* Draw a random element of the provided list N times to return an array of N random elements
* Drawing can be with or without replacement
* @param {array} list The array we want to draw randomly from
* @param {integer} count The number of times we want to draw
* @param {boolean} replacement Draw with or without replacement from the input array(default true)
* @return {array} Array consisting of N random elements
* Draws a specified number of random elements from a given list.
*
* @template T - The type of elements in the list.
* @param originalList - The list to draw elements from.
* @param count - The number of elements to draw. Defaults to 1.
* @param replacement - Whether to draw with replacement. Defaults to true.
* @returns An array containing the drawn elements.
*/
drawRandomFromList<T>(originalList: Array<T>, count?: number, replacement?: boolean): Array<T>;
/**
* Draw a random (top level) element of the provided dictionary N times to return an array of N random dictionary keys
* Drawing can be with or without replacement
* @param {any} dict The dictionary we want to draw randomly from
* @param {integer} count The number of times we want to draw
* @param {boolean} replacement Draw with ot without replacement from the input dict
* @return {array} Array consisting of N random keys of the dictionary
* Draws a specified number of random keys from a given dictionary.
*
* @param dict - The dictionary from which to draw keys.
* @param count - The number of keys to draw. Defaults to 1.
* @param replacement - Whether to draw with replacement. Defaults to true.
* @returns An array of randomly drawn keys from the dictionary.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
drawRandomFromDict(dict: any, count?: number, replacement?: boolean): any[];
/**
* Generates a biased random number within a specified range.
*
* @param min - The minimum value of the range (inclusive).
* @param max - The maximum value of the range (inclusive).
* @param shift - The bias shift to apply to the random number generation.
* @param n - The number of iterations to use for generating a Gaussian random number.
* @returns A biased random number within the specified range.
* @throws Will throw if `max` is less than `min` or if `n` is less than 1.
*/
getBiasedRandomNumber(min: number, max: number, shift: number, n: number): number;
/**
* Fisher-Yates shuffle an array
* @param array Array to shuffle
* @returns Shuffled array
* Shuffles an array in place using the Fisher-Yates algorithm.
*
* @template T - The type of elements in the array.
* @param array - The array to shuffle.
* @returns The shuffled array.
*/
shuffle<T>(array: Array<T>): Array<T>;
/**
* Rolls for a probability based on chance
* @param number Probability Chance as float (0-1)
* @returns If roll succeed or not
* @example
* rollForChanceProbability(0.25); // returns true 25% probability
* Rolls for a chance probability and returns whether the roll is successful.
*
* @param probabilityChance - The probability chance to roll for, represented as a number between 0 and 1.
* @returns `true` if the random number is less than or equal to the probability chance, otherwise `false`.
*/
rollForChanceProbability(probabilityChance: number): boolean;
}

View File

@ -118,6 +118,9 @@ export declare class ProfileController {
* Handle client/profile/status
*/
getProfileStatus(sessionId: string): IGetProfileStatusResponseData;
/**
* Handle client/profile/view
*/
getOtherProfile(sessionId: string, request: IGetOtherProfileRequest): IGetOtherProfileResponse;
/**
* Handle client/profile/settings

View File

@ -114,9 +114,10 @@ export declare class BotEquipmentModGenerator {
/**
* Sort mod slots into an ordering that maximises chance of a successful weapon generation
* @param unsortedSlotKeys Array of mod slot strings to sort
* @param itemTplWithKeysToSort The Tpl of the item with mod keys being sorted
* @returns Sorted array
*/
protected sortModKeys(unsortedSlotKeys: string[]): string[];
protected sortModKeys(unsortedSlotKeys: string[], itemTplWithKeysToSort: string): string[];
/**
* Get a Slot property for an item (chamber/cartridge/slot)
* @param modSlot e.g patron_in_weapon

View File

@ -12,6 +12,7 @@ import { IBarterScheme } from "@spt/models/eft/common/tables/ITrader";
import { IOfferRequirement, IRagfairOffer, IRagfairOfferUser } from "@spt/models/eft/ragfair/IRagfairOffer";
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
import { IArmorPlateBlacklistSettings, IBarterDetails, IDynamic, IRagfairConfig } from "@spt/models/spt/config/IRagfairConfig";
import { ITraderConfig } from "@spt/models/spt/config/ITraderConfig";
import { ITplWithFleaPrice } from "@spt/models/spt/ragfair/ITplWithFleaPrice";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
@ -47,6 +48,7 @@ export declare class RagfairOfferGenerator {
protected configServer: ConfigServer;
protected cloner: ICloner;
protected ragfairConfig: IRagfairConfig;
protected traderConfig: ITraderConfig;
protected botConfig: IBotConfig;
protected allowedFleaPriceItemsForBarter: {
tpl: string;
@ -83,7 +85,7 @@ export declare class RagfairOfferGenerator {
* @param isTrader Is the user creating the offer a trader
* @returns IRagfairOfferUser
*/
createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser;
protected createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser;
/**
* Calculate the offer price that's listed on the flea listing
* @param offerRequirements barter requirements for offer

View File

@ -209,4 +209,10 @@ export declare class ProfileHelper {
* @returns Array of item objects
*/
getQuestItemsInProfile(profile: IPmcData): IItem[];
/**
* Return a favorites array in the format expected by the getOtherProfile call
* @param profile
* @returns An array of IItem objects representing the favorited data
*/
getOtherProfileFavorites(profile: IPmcData): IItem[];
}

View File

@ -282,10 +282,10 @@ export declare class QuestHelper {
*/
protected findAndAddHideoutProductionIdToProfile(pmcData: IPmcData, craftUnlockReward: IQuestReward, questDetails: IQuest, sessionID: string, response: IItemEventRouterResponse): void;
/**
* Find hideout craft id for the specified quest reward
* @param craftUnlockReward
* @param questDetails
* @returns
* Find hideout craft for the specified quest reward
* @param craftUnlockReward Reward item from quest with craft unlock details
* @param questDetails Quest with craft unlock reward
* @returns Hideout craft
*/
getRewardProductionMatch(craftUnlockReward: IQuestReward, questDetails: IQuest): IHideoutProduction[];
/**
@ -332,16 +332,15 @@ export declare class QuestHelper {
/**
* Create a clone of the given quest array with the rewards updated to reflect the
* given game version
*
* @param quests The list of quests to check
* @param gameVersion The game version of the profile
* @returns array of IQuest objects with the rewards filtered correctly for the game version
* @param quests List of quests to check
* @param gameVersion Game version of the profile
* @returns Array of IQuest objects with the rewards filtered correctly for the game version
*/
protected updateQuestsForGameEdition(quests: IQuest[], gameVersion: string): IQuest[];
/**
* Return a list of quests that would fail when supplied quest is completed
* @param completedQuestId quest completed id
* @returns array of IQuest objects
* @param completedQuestId Quest completed id
* @returns Array of IQuest objects
*/
protected getQuestsFromProfileFailedByCompletingQuest(completedQuestId: string, pmcProfile: IPmcData): IQuest[];
/**

View File

@ -67,6 +67,13 @@ export declare class RagfairOfferHelper {
* @returns Offers the player should see
*/
getValidOffers(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record<string, ITraderAssort>, pmcData: IPmcData): IRagfairOffer[];
/**
* Disable offer if item is flagged by tiered flea config
* @param tieredFlea Tiered flea settings from ragfair config
* @param offer Ragfair offer to check
* @param tieredFleaLimitTypes Dict of item types with player level to be viewable
* @param playerLevel Level of player viewing offer
*/
protected checkAndLockOfferFromPlayerTieredFlea(tieredFlea: ITieredFlea, offer: IRagfairOffer, tieredFleaLimitTypes: string[], playerLevel: number): void;
/**
* Get matching offers that require the desired item and filter out offers from non traders if player is below ragfair unlock level
@ -99,14 +106,14 @@ export declare class RagfairOfferHelper {
*/
traderOfferItemQuestLocked(offer: IRagfairOffer, traderAssorts: Record<string, ITraderAssort>): boolean;
/**
* Has a traders offer ran out of stock to sell to player
* Has trader offer ran out of stock to sell to player
* @param offer Offer to check stock of
* @returns true if out of stock
*/
protected traderOutOfStock(offer: IRagfairOffer): boolean;
/**
* Check if trader offers' BuyRestrictionMax value has been reached
* @param offer offer to check restriction properties of
* @param offer Offer to check restriction properties of
* @returns true if restriction reached, false if no restrictions/not reached
*/
protected traderBuyRestrictionReached(offer: IRagfairOffer): boolean;
@ -114,7 +121,7 @@ export declare class RagfairOfferHelper {
* Get an array of flea offers that are inaccessible to player due to their inadequate loyalty level
* @param offers Offers to check
* @param pmcProfile Players profile with trader loyalty levels
* @returns array of offer ids player cannot see
* @returns Array of offer ids player cannot see
*/
protected getLoyaltyLockedOffers(offers: IRagfairOffer[], pmcProfile: IPmcData): string[];
/**
@ -126,7 +133,7 @@ export declare class RagfairOfferHelper {
/**
* Count up all rootitem StackObjectsCount properties of an array of items
* @param itemsInInventoryToList items to sum up
* @returns Total count
* @returns Total stack count
*/
getTotalStackCountSize(itemsInInventoryToList: IItem[][]): number;
/**
@ -164,16 +171,16 @@ export declare class RagfairOfferHelper {
protected getLocalisedOfferSoldMessage(itemTpl: string, boughtAmount: number): string;
/**
* Check an offer passes the various search criteria the player requested
* @param searchRequest
* @param offer
* @param pmcData
* @returns True
* @param searchRequest Client search request
* @param offer Offer to check
* @param pmcData Player profile
* @returns True if offer passes criteria
*/
protected passesSearchFilterCriteria(searchRequest: ISearchRequestData, offer: IRagfairOffer, pmcData: IPmcData): boolean;
/**
* Check that the passed in offer item is functional
* @param offerRootItem The root item of the offer
* @param offer The flea offer
* @param offer Flea offer to check
* @returns True if the given item is functional
*/
isItemFunctional(offerRootItem: IItem, offer: IRagfairOffer): boolean;
@ -181,7 +188,7 @@ export declare class RagfairOfferHelper {
* Should a ragfair offer be visible to the player
* @param searchRequest Search request
* @param itemsToAdd ?
* @param traderAssorts Trader assort items
* @param traderAssorts Trader assort items - used for filtering out locked trader items
* @param offer The flea offer
* @param pmcProfile Player profile
* @returns True = should be shown to player

View File

@ -44,10 +44,10 @@ export declare class TraderAssortHelper {
* Filter out assorts not unlocked due to level OR quest completion
* @param sessionId session id
* @param traderId traders id
* @param flea Should assorts player hasn't unlocked be returned - default false
* @param showLockedAssorts Should assorts player hasn't unlocked be returned - default false
* @returns a traders' assorts
*/
getAssort(sessionId: string, traderId: string, flea?: boolean): ITraderAssort;
getAssort(sessionId: string, traderId: string, showLockedAssorts?: boolean): ITraderAssort;
/**
* Given the blacklist provided, remove root items from assort
* @param assortToFilter Trader assort to modify
@ -75,20 +75,10 @@ export declare class TraderAssortHelper {
* @returns true they need refreshing
*/
traderAssortsHaveExpired(traderID: string): boolean;
/**
* Iterate over all assorts barter_scheme values, find barters selling for money and multiply by multipler in config
* @param traderAssort Assorts to multiple price of
*/
protected multiplyItemPricesByConfigMultiplier(traderAssort: ITraderAssort): void;
/**
* Get an array of pristine trader items prior to any alteration by player (as they were on server start)
* @param traderId trader id
* @returns array of Items
*/
protected getPristineTraderAssorts(traderId: string): IItem[];
/**
* Returns generated ragfair offers in a trader assort format
* @returns Trader assort object
*/
protected getRagfairDataAsTraderAssort(): ITraderAssort;
}

View File

@ -153,7 +153,7 @@ export interface IInventory {
/** Key is hideout area enum numeric as string e.g. "24", value is area _id */
hideoutAreaStashes: Record<string, string>;
fastPanel: Record<string, string>;
favoriteItems: IItem[];
favoriteItems: string[];
}
export interface IBaseJsonSkills {
Common: Record<string, Common>;

View File

@ -169,6 +169,13 @@ export interface ISpt {
freeRepeatableRefreshUsedCount?: Record<string, number>;
/** When was a profile migrated, value is timestamp */
migrations?: Record<string, number>;
/** Cultist circle rewards received that are one time use, key (md5) is a combination of sacrificed + reward items */
cultistRewards?: Map<string, IAcceptedCultistReward>;
}
export interface IAcceptedCultistReward {
timestamp: number;
sacrificeItems: string[];
rewardItems: string[];
}
export interface IModDetails {
name: string;

View File

@ -0,0 +1,4 @@
export declare enum CircleRewardType {
RANDOM = 0,
HIDEOUT_TASK = 1
}

View File

@ -18,11 +18,21 @@ export interface ICultistCircleSettings {
maxRewardItemCount: number;
maxAttemptsToPickRewardsWithinBudget: number;
rewardPriceMultiplerMinMax: MinMax;
/** The odds that meeting the highest threshold gives you a bonus to crafting time */
bonusAmountMultiplier: number;
bonusChanceMultiplier: number;
/** What is considered a "high-value" item */
highValueThresholdRub: number;
/** Hideout/task reward crafts have a unique craft time */
hideoutTaskRewardTimeSeconds: number;
/** Rouble amount player needs to sacrifice to get chance of hideout/task rewards */
hideoutCraftSacrificeThresholdRub: number;
craftTimeThreshholds: ICraftTimeThreshhold[];
/** -1 means no override */
/** -1 means no override, value in seconds */
craftTimeOverride: number;
/** Specific reward pool when player sacrificed one specific item */
directRewards: Record<string, IDirectRewardSettings>;
/** Specific reward pool when player sacrifice specific item(s) */
directRewards: IDirectRewardSettings[];
/** Overrides for reward stack sizes, keyed by item tpl */
directRewardStackSize: Record<string, MinMax>;
/** Item tpls to exclude from the reward pool */
rewardItemBlacklist: string[];
@ -34,6 +44,9 @@ export interface ICraftTimeThreshhold extends MinMax {
craftTimeSeconds: number;
}
export interface IDirectRewardSettings {
rewardTpls: string[];
reward: string[];
requiredItems: string[];
craftTimeSeconds: number;
/** Is the reward a one time reward or can it be given multiple times */
repeatable: boolean;
}

View File

@ -4,10 +4,10 @@ import { ILootRequest } from "@spt/models/spt/services/ILootRequest";
export interface ITraderConfig extends IBaseConfig {
kind: "spt-trader";
updateTime: IUpdateTime[];
updateTimeDefault: number;
purchasesAreFoundInRaid: boolean;
/** Should trader reset times be set based on server start time (false = bsg time - on the hour) */
tradersResetFromServerStart: boolean;
updateTimeDefault: number;
traderPriceMultipler: number;
fence: IFenceConfig;
moddedTraders: IModdedTraders;

View File

@ -0,0 +1,8 @@
import { CircleRewardType } from "@spt/models/enums/hideout/CircleRewardType";
import { ICraftTimeThreshhold } from "@spt/models/spt/config/IHideoutConfig";
export interface ICircleCraftDetails {
time: number;
rewardType: CircleRewardType;
rewardAmountRoubles: number;
rewardDetails?: ICraftTimeThreshhold;
}

View File

@ -3,14 +3,17 @@ import { InventoryHelper } from "@spt/helpers/InventoryHelper";
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { PresetHelper } from "@spt/helpers/PresetHelper";
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
import { QuestHelper } from "@spt/helpers/QuestHelper";
import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { IBotHideoutArea } from "@spt/models/eft/common/tables/IBotBase";
import { IItem } from "@spt/models/eft/common/tables/IItem";
import { IStageRequirement } from "@spt/models/eft/hideout/IHideoutArea";
import { IHideoutCircleOfCultistProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutCircleOfCultistProductionStartRequestData";
import { IHideoutProduction, IHideoutProductionData, IRequirement, IRequirementBase } from "@spt/models/eft/hideout/IHideoutProduction";
import { IRequirement, IRequirementBase } from "@spt/models/eft/hideout/IHideoutProduction";
import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse";
import { IDirectRewardSettings, IHideoutConfig } from "@spt/models/spt/config/IHideoutConfig";
import { ICraftTimeThreshhold, ICultistCircleSettings, IDirectRewardSettings, IHideoutConfig } from "@spt/models/spt/config/IHideoutConfig";
import { ICircleCraftDetails } from "@spt/models/spt/hideout/ICircleCraftDetails";
import { IHideout } from "@spt/models/spt/hideout/IHideout";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { EventOutputHolder } from "@spt/routers/EventOutputHolder";
import { ConfigServer } from "@spt/servers/ConfigServer";
@ -33,13 +36,14 @@ export declare class CircleOfCultistService {
protected profileHelper: ProfileHelper;
protected inventoryHelper: InventoryHelper;
protected hideoutHelper: HideoutHelper;
protected questHelper: QuestHelper;
protected databaseService: DatabaseService;
protected itemFilterService: ItemFilterService;
protected seasonalEventService: SeasonalEventService;
protected configServer: ConfigServer;
protected static circleOfCultistSlotId: string;
protected hideoutConfig: IHideoutConfig;
constructor(logger: ILogger, timeUtil: TimeUtil, cloner: ICloner, eventOutputHolder: EventOutputHolder, randomUtil: RandomUtil, hashUtil: HashUtil, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, inventoryHelper: InventoryHelper, hideoutHelper: HideoutHelper, databaseService: DatabaseService, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer);
constructor(logger: ILogger, timeUtil: TimeUtil, cloner: ICloner, eventOutputHolder: EventOutputHolder, randomUtil: RandomUtil, hashUtil: HashUtil, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, inventoryHelper: InventoryHelper, hideoutHelper: HideoutHelper, questHelper: QuestHelper, databaseService: DatabaseService, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer);
/**
* Start a sacrifice event
* Generate rewards
@ -50,24 +54,38 @@ export declare class CircleOfCultistService {
* @returns IItemEventRouterResponse
*/
startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse;
/**
* Create a map of the possible direct rewards, keyed by the items needed to be sacrificed
* @param directRewards Direct rewards array from hideout config
* @returns Map
*/
protected generateSacrificedItemsCache(directRewards: IDirectRewardSettings[]): Map<string, IDirectRewardSettings>;
/**
* Get the reward amount multiple value based on players hideout management skill + configs rewardPriceMultiplerMinMax values
* @param pmcData Player profile
* @param cultistCircleSettings Circle config settings
* @returns Reward Amount Multipler
*/
protected getRewardAmountMultipler(pmcData: IPmcData, cultistCircleSettings: ICultistCircleSettings): number;
/**
* Register production inside player profile
* @param sessionId Session id
* @param pmcData Player profile
* @param recipeId Recipe id
* @param sacrificedItems Items player sacrificed
* @param rewardAmountRoubles Rouble amount to reward player in items with
* @param directRewardSettings OPTIONAL: If craft is giving direct rewards
* @param craftingTime How long the ritual should take
*/
protected registerCircleOfCultistProduction(sessionId: string, pmcData: IPmcData, recipeId: string, sacrificedItems: IItem[], rewardAmountRoubles: number, directRewardSettings?: IDirectRewardSettings): void;
protected registerCircleOfCultistProduction(sessionId: string, pmcData: IPmcData, recipeId: string, sacrificedItems: IItem[], craftingTime: number): void;
/**
* Get the circle craft time as seconds, value is based on reward item value
* OR rewards are direct, then use custom craft time defined in oarameter object
* And get the bonus status to determine what tier of reward is given
* @param rewardAmountRoubles Value of rewards in roubles
* @param directRewardSettings OPTIONAL: If craft is giving direct rewards
* @returns craft time seconds
* @param circleConfig Circle config values
* @param directRewardSettings OPTIONAL - Values related to direct reward being given
* @returns craft time + type of reward + reward details
*/
protected getCircleCraftTimeSeconds(rewardAmountRoubles: number, directRewardSettings?: IDirectRewardSettings): number;
protected getCircleCraftingInfo(rewardAmountRoubles: number, circleConfig: ICultistCircleSettings, directRewardSettings?: IDirectRewardSettings): ICircleCraftDetails;
protected getMatchingThreshold(thresholds: ICraftTimeThreshhold[], rewardAmountRoubles: number): ICraftTimeThreshhold;
/**
* Get the items player sacrificed in circle
* @param pmcData Player profile
@ -81,20 +99,40 @@ export declare class CircleOfCultistService {
* @param cultistCircleStashId Id of stash item
* @returns Array of item arrays
*/
protected getRewardsWithinBudget(rewardItemTplPool: string[], rewardBudget: number, cultistCircleStashId: string): IItem[][];
protected getRewardsWithinBudget(rewardItemTplPool: string[], rewardBudget: number, cultistCircleStashId: string, circleConfig: ICultistCircleSettings): IItem[][];
/**
* Give every item as a reward that's passed in
* @param rewardTpls Item tpls to turn into reward items
* Get direct rewards
* @param sessionId sessionId
* @param directReward Items sacrificed
* @param cultistCircleStashId Id of stash item
* @returns Array of item arrays
* @returns The reward object
*/
protected getExplicitRewards(explicitRewardSettings: IDirectRewardSettings, cultistCircleStashId: string): IItem[][];
protected getDirectRewards(sessionId: string, directReward: IDirectRewardSettings, cultistCircleStashId: string): IItem[][];
/**
* Check for direct rewards from what player sacrificed
* @param sessionId sessionId
* @param sacrificedItems Items sacrificed
* @returns Direct reward items to send to player
*/
protected checkForDirectReward(sessionId: string, sacrificedItems: IItem[], directRewardsCache: Map<string, IDirectRewardSettings>): IDirectRewardSettings;
/**
* Create an md5 key of the sacrificed + reward items
* @param directReward Direct reward to create key for
* @returns Key
*/
protected getDirectRewardHashKey(directReward: IDirectRewardSettings): string;
/**
* Explicit rewards have thier own stack sizes as they dont use a reward rouble pool
* @param rewardTpl Item being rewarded to get stack size of
* @returns stack size of item
*/
protected getExplicitRewardBaseTypeStackSize(rewardTpl: string): number;
protected getDirectRewardBaseTypeStackSize(rewardTpl: string): number;
/**
* Add a record to the players profile to signal they have accepted a non-repeatable direct reward
* @param sessionId Session id
* @param directReward Reward sent to player
*/
protected flagDirectRewardAsAcceptedInProfile(sessionId: string, directReward: IDirectRewardSettings): void;
/**
* Get the size of a reward items stack
* 1 for everything except ammo, ammo can be between min stack and max stack
@ -107,9 +145,26 @@ export declare class CircleOfCultistService {
* Get a pool of tpl IDs of items the player needs to complete hideout crafts/upgrade areas
* @param sessionId Session id
* @param pmcData Profile of player who will be getting the rewards
* @param rewardType Do we return bonus items (hideout/task items)
* @param cultistCircleConfig Circle config
* @returns Array of tpls
*/
protected getCultistCircleRewardPool(sessionId: string, pmcData: IPmcData): string[];
protected getCultistCircleRewardPool(sessionId: string, pmcData: IPmcData, craftingInfo: ICircleCraftDetails, cultistCircleConfig: ICultistCircleSettings): string[];
/**
* Check players profile for quests with hand-in requirements and add those required items to the pool
* @param pmcData Player profile
* @param itemRewardBlacklist Items not to add to pool
* @param rewardPool Pool to add items to
*/
protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set<string>): void;
/**
* Adds items the player needs to complete hideout crafts/upgrades to the reward pool
* @param hideoutDbData Hideout area data
* @param pmcData Player profile
* @param itemRewardBlacklist Items not to add to pool
* @param rewardPool Pool to add items to
*/
protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set<string>): void;
/**
* Get all active hideout areas
* @param areas Hideout areas to iterate over
@ -117,12 +172,13 @@ export declare class CircleOfCultistService {
*/
protected getPlayerAccessibleHideoutAreas(areas: IBotHideoutArea[]): IBotHideoutArea[];
/**
* Get all recipes the player has access to, includes base + unlocked recipes
* @param unlockedRecipes Recipes player has flagged as unlocked
* @param allRecipes All recipes
* @returns Array of recipes
* Get array of random reward items
* @param rewardPool Reward pool to add to
* @param itemRewardBlacklist Reward Blacklist
* @param itemsShouldBeHighValue Should these items meet the valuable threshold
* @returns rewardPool
*/
protected getPlayerAccessibleRecipes(unlockedRecipes: string[], allRecipes: IHideoutProductionData): IHideoutProduction[];
protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set<string>, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set<string>;
/**
* Iterate over passed in hideout requirements and return the Item
* @param requirements Requirements to iterate over

View File

@ -87,6 +87,12 @@ export declare class ProfileFixerService {
* @returns
*/
protected verifyQuestProductionUnlock(pmcProfile: IPmcData, productionUnlockReward: IQuestReward, questDetails: IQuest): void;
/**
* Initial release of SPT 3.10 used an incorrect favorites structure, reformat
* the structure to the correct MongoID array structure
* @param pmcProfile
*/
protected fixFavorites(pmcProfile: IPmcData): void;
/**
* If the profile has elite Hideout Managment skill, add the additional slots from globals
* NOTE: This seems redundant, but we will leave it here just incase.

View File

@ -138,6 +138,12 @@ export declare class SeasonalEventService {
*/
protected enableHalloweenSummonEvent(): void;
protected configureZombies(zombieSettings: IZombieSettings): void;
/**
* Get location ids of maps with an infection above 0
* @param locationInfections Dict of locations with their infection percentage
* @returns Array of location ids
*/
protected getLocationsWithZombies(locationInfections: Record<string, number>): string[];
/**
* BSG store the location ids differently inside `LocationInfection`, need to convert to matching location IDs
* @param infectedLocationKey Key to convert

View File

@ -1,38 +0,0 @@
import { ILogger } from "@spt/models/spt/utils/ILogger";
export declare class DatabaseDecompressionUtil {
protected logger: ILogger;
private compressedDir;
private assetsDir;
private compiled;
constructor(logger: ILogger);
/**
* Checks if the application is running in a compiled environment. A simple check is done to see if the relative
* assets directory exists. If it does not, the application is assumed to be running in a compiled environment. All
* relative asset paths are different within a compiled environment, so this simple check is sufficient.
*/
private isCompiled;
/**
* Initializes the database compression utility.
*
* This method will decompress all 7-zip archives within the compressed database directory. The decompressed files
* are placed in their respective directories based on the name and location of the compressed file.
*/
initialize(): Promise<void>;
/**
* Retrieves a list of all 7-zip archives within the compressed database directory.
*/
private getCompressedFiles;
/**
* Processes a compressed file by checking if the target directory is empty, and if so, decompressing the file into
* the target directory.
*/
private processCompressedFile;
/**
* Checks if a directory exists and is empty.
*/
private isDirectoryEmpty;
/**
* Decompresses a 7-zip archive to the target directory.
*/
private decompressFile;
}

View File

@ -106,77 +106,177 @@ export declare class RandomUtil {
protected cloner: ICloner;
protected logger: ILogger;
constructor(cloner: ICloner, logger: ILogger);
/**
* Generates a secure random number between 0 (inclusive) and 1 (exclusive).
*
* This method uses the `crypto` module to generate a 48-bit random integer,
* which is then divided by the maximum possible 48-bit integer value to
* produce a floating-point number in the range [0, 1).
*
* @returns A secure random number between 0 (inclusive) and 1 (exclusive).
*/
private getSecureRandomNumber;
/**
* Generates a random integer between the specified minimum and maximum values, inclusive.
*
* @param min - The minimum value (inclusive).
* @param max - The maximum value (inclusive).
* @returns A random integer between the specified minimum and maximum values.
*/
getInt(min: number, max: number): number;
/**
* Generates a random integer between 1 (inclusive) and the specified maximum value (exclusive).
* If the maximum value is less than or equal to 1, it returns 1.
*
* @param max - The upper bound (exclusive) for the random integer generation.
* @returns A random integer between 1 and max - 1, or 1 if max is less than or equal to 1.
*/
getIntEx(max: number): number;
/**
* Generates a random floating-point number within the specified range.
*
* @param min - The minimum value of the range (inclusive).
* @param max - The maximum value of the range (exclusive).
* @returns A random floating-point number between `min` (inclusive) and `max` (exclusive).
*/
getFloat(min: number, max: number): number;
/**
* Generates a random boolean value.
*
* @returns A random boolean value, where the probability of `true` and `false` is approximately equal.
*/
getBool(): boolean;
/**
* Calculates the percentage of a given number and returns the result.
*
* @param percent - The percentage to calculate.
* @param number - The number to calculate the percentage of.
* @param toFixed - The number of decimal places to round the result to (default is 2).
* @returns The calculated percentage of the given number, rounded to the specified number of decimal places.
*/
getPercentOfValue(percent: number, number: number, toFixed?: number): number;
/**
* Reduce a value by a percentage
* @param number Value to reduce
* @param percentage Percentage to reduce value by
* @returns Reduced value
* Reduces a given number by a specified percentage.
*
* @param number - The original number to be reduced.
* @param percentage - The percentage by which to reduce the number.
* @returns The reduced number after applying the percentage reduction.
*/
reduceValueByPercent(number: number, percentage: number): number;
/**
* Check if number passes a check out of 100
* @param chancePercent value check needs to be above
* @returns true if value passes check
* Determines if a random event occurs based on the given chance percentage.
*
* @param chancePercent - The percentage chance (0-100) that the event will occur.
* @returns `true` if the event occurs, `false` otherwise.
*/
getChance100(chancePercent: number): boolean;
/**
* Returns a random string from the provided array of strings.
*
* This method is separate from getArrayValue so we can use a generic inferance with getArrayValue.
*
* @param arr - The array of strings to select a random value from.
* @returns A randomly selected string from the array.
*/
getStringArrayValue(arr: string[]): string;
/**
* Returns a random element from the provided array.
*
* @template T - The type of elements in the array.
* @param arr - The array from which to select a random element.
* @returns A random element from the array.
*/
getArrayValue<T>(arr: T[]): T;
/**
* Retrieves a random key from the given object.
*
* @param node - The object from which to retrieve a key.
* @returns A string representing one of the keys of the node object.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
getKey(node: any): string;
/**
* Retrieves the value associated with a key from the given node object.
*
* @param node - An object with string keys and any type of values.
* @returns The value associated with the key obtained from the node.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
getKeyValue(node: {
[x: string]: any;
}): any;
/**
* Generate a normally distributed random number
* Uses the Box-Muller transform
* @param {number} mean Mean of the normal distribution
* @param {number} sigma Standard deviation of the normal distribution
* @returns {number} The value drawn
* Generates a normally distributed random number using the Box-Muller transform.
*
* @param mean - The mean (μ) of the normal distribution.
* @param sigma - The standard deviation (σ) of the normal distribution.
* @param attempt - The current attempt count to generate a valid number (default is 0).
* @returns A normally distributed random number.
*
* @remarks
* This function uses the Box-Muller transform to generate a normally distributed random number.
* If the generated number is less than 0, it will recursively attempt to generate a valid number up to 100 times.
* If it fails to generate a valid number after 100 attempts, it will return a random float between 0.01 and twice the mean.
*/
getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number;
/**
* Draw Random integer low inclusive, high exclusive
* if high is not set we draw from 0 to low (exclusive)
* @param {integer} low Lower bound inclusive, when high is not set, this is high
* @param {integer} high Higher bound exclusive
* @returns {integer} The random integer in [low, high)
* Generates a random integer between the specified range.
*
* @param low - The lower bound of the range (inclusive).
* @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`.
* @returns A random integer within the specified range.
*/
randInt(low: number, high?: number): number;
/**
* Draw a random element of the provided list N times to return an array of N random elements
* Drawing can be with or without replacement
* @param {array} list The array we want to draw randomly from
* @param {integer} count The number of times we want to draw
* @param {boolean} replacement Draw with or without replacement from the input array(default true)
* @return {array} Array consisting of N random elements
* Draws a specified number of random elements from a given list.
*
* @template T - The type of elements in the list.
* @param originalList - The list to draw elements from.
* @param count - The number of elements to draw. Defaults to 1.
* @param replacement - Whether to draw with replacement. Defaults to true.
* @returns An array containing the drawn elements.
*/
drawRandomFromList<T>(originalList: Array<T>, count?: number, replacement?: boolean): Array<T>;
/**
* Draw a random (top level) element of the provided dictionary N times to return an array of N random dictionary keys
* Drawing can be with or without replacement
* @param {any} dict The dictionary we want to draw randomly from
* @param {integer} count The number of times we want to draw
* @param {boolean} replacement Draw with ot without replacement from the input dict
* @return {array} Array consisting of N random keys of the dictionary
* Draws a specified number of random keys from a given dictionary.
*
* @param dict - The dictionary from which to draw keys.
* @param count - The number of keys to draw. Defaults to 1.
* @param replacement - Whether to draw with replacement. Defaults to true.
* @returns An array of randomly drawn keys from the dictionary.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
drawRandomFromDict(dict: any, count?: number, replacement?: boolean): any[];
/**
* Generates a biased random number within a specified range.
*
* @param min - The minimum value of the range (inclusive).
* @param max - The maximum value of the range (inclusive).
* @param shift - The bias shift to apply to the random number generation.
* @param n - The number of iterations to use for generating a Gaussian random number.
* @returns A biased random number within the specified range.
* @throws Will throw if `max` is less than `min` or if `n` is less than 1.
*/
getBiasedRandomNumber(min: number, max: number, shift: number, n: number): number;
/**
* Fisher-Yates shuffle an array
* @param array Array to shuffle
* @returns Shuffled array
* Shuffles an array in place using the Fisher-Yates algorithm.
*
* @template T - The type of elements in the array.
* @param array - The array to shuffle.
* @returns The shuffled array.
*/
shuffle<T>(array: Array<T>): Array<T>;
/**
* Rolls for a probability based on chance
* @param number Probability Chance as float (0-1)
* @returns If roll succeed or not
* @example
* rollForChanceProbability(0.25); // returns true 25% probability
* Rolls for a chance probability and returns whether the roll is successful.
*
* @param probabilityChance - The probability chance to roll for, represented as a number between 0 and 1.
* @returns `true` if the random number is less than or equal to the probability chance, otherwise `false`.
*/
rollForChanceProbability(probabilityChance: number): boolean;
}

View File

@ -118,6 +118,9 @@ export declare class ProfileController {
* Handle client/profile/status
*/
getProfileStatus(sessionId: string): IGetProfileStatusResponseData;
/**
* Handle client/profile/view
*/
getOtherProfile(sessionId: string, request: IGetOtherProfileRequest): IGetOtherProfileResponse;
/**
* Handle client/profile/settings

View File

@ -114,9 +114,10 @@ export declare class BotEquipmentModGenerator {
/**
* Sort mod slots into an ordering that maximises chance of a successful weapon generation
* @param unsortedSlotKeys Array of mod slot strings to sort
* @param itemTplWithKeysToSort The Tpl of the item with mod keys being sorted
* @returns Sorted array
*/
protected sortModKeys(unsortedSlotKeys: string[]): string[];
protected sortModKeys(unsortedSlotKeys: string[], itemTplWithKeysToSort: string): string[];
/**
* Get a Slot property for an item (chamber/cartridge/slot)
* @param modSlot e.g patron_in_weapon

View File

@ -12,6 +12,7 @@ import { IBarterScheme } from "@spt/models/eft/common/tables/ITrader";
import { IOfferRequirement, IRagfairOffer, IRagfairOfferUser } from "@spt/models/eft/ragfair/IRagfairOffer";
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
import { IArmorPlateBlacklistSettings, IBarterDetails, IDynamic, IRagfairConfig } from "@spt/models/spt/config/IRagfairConfig";
import { ITraderConfig } from "@spt/models/spt/config/ITraderConfig";
import { ITplWithFleaPrice } from "@spt/models/spt/ragfair/ITplWithFleaPrice";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
@ -47,6 +48,7 @@ export declare class RagfairOfferGenerator {
protected configServer: ConfigServer;
protected cloner: ICloner;
protected ragfairConfig: IRagfairConfig;
protected traderConfig: ITraderConfig;
protected botConfig: IBotConfig;
protected allowedFleaPriceItemsForBarter: {
tpl: string;
@ -83,7 +85,7 @@ export declare class RagfairOfferGenerator {
* @param isTrader Is the user creating the offer a trader
* @returns IRagfairOfferUser
*/
createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser;
protected createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser;
/**
* Calculate the offer price that's listed on the flea listing
* @param offerRequirements barter requirements for offer

View File

@ -209,4 +209,10 @@ export declare class ProfileHelper {
* @returns Array of item objects
*/
getQuestItemsInProfile(profile: IPmcData): IItem[];
/**
* Return a favorites array in the format expected by the getOtherProfile call
* @param profile
* @returns An array of IItem objects representing the favorited data
*/
getOtherProfileFavorites(profile: IPmcData): IItem[];
}

View File

@ -282,10 +282,10 @@ export declare class QuestHelper {
*/
protected findAndAddHideoutProductionIdToProfile(pmcData: IPmcData, craftUnlockReward: IQuestReward, questDetails: IQuest, sessionID: string, response: IItemEventRouterResponse): void;
/**
* Find hideout craft id for the specified quest reward
* @param craftUnlockReward
* @param questDetails
* @returns
* Find hideout craft for the specified quest reward
* @param craftUnlockReward Reward item from quest with craft unlock details
* @param questDetails Quest with craft unlock reward
* @returns Hideout craft
*/
getRewardProductionMatch(craftUnlockReward: IQuestReward, questDetails: IQuest): IHideoutProduction[];
/**
@ -332,16 +332,15 @@ export declare class QuestHelper {
/**
* Create a clone of the given quest array with the rewards updated to reflect the
* given game version
*
* @param quests The list of quests to check
* @param gameVersion The game version of the profile
* @returns array of IQuest objects with the rewards filtered correctly for the game version
* @param quests List of quests to check
* @param gameVersion Game version of the profile
* @returns Array of IQuest objects with the rewards filtered correctly for the game version
*/
protected updateQuestsForGameEdition(quests: IQuest[], gameVersion: string): IQuest[];
/**
* Return a list of quests that would fail when supplied quest is completed
* @param completedQuestId quest completed id
* @returns array of IQuest objects
* @param completedQuestId Quest completed id
* @returns Array of IQuest objects
*/
protected getQuestsFromProfileFailedByCompletingQuest(completedQuestId: string, pmcProfile: IPmcData): IQuest[];
/**

View File

@ -67,6 +67,13 @@ export declare class RagfairOfferHelper {
* @returns Offers the player should see
*/
getValidOffers(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record<string, ITraderAssort>, pmcData: IPmcData): IRagfairOffer[];
/**
* Disable offer if item is flagged by tiered flea config
* @param tieredFlea Tiered flea settings from ragfair config
* @param offer Ragfair offer to check
* @param tieredFleaLimitTypes Dict of item types with player level to be viewable
* @param playerLevel Level of player viewing offer
*/
protected checkAndLockOfferFromPlayerTieredFlea(tieredFlea: ITieredFlea, offer: IRagfairOffer, tieredFleaLimitTypes: string[], playerLevel: number): void;
/**
* Get matching offers that require the desired item and filter out offers from non traders if player is below ragfair unlock level
@ -99,14 +106,14 @@ export declare class RagfairOfferHelper {
*/
traderOfferItemQuestLocked(offer: IRagfairOffer, traderAssorts: Record<string, ITraderAssort>): boolean;
/**
* Has a traders offer ran out of stock to sell to player
* Has trader offer ran out of stock to sell to player
* @param offer Offer to check stock of
* @returns true if out of stock
*/
protected traderOutOfStock(offer: IRagfairOffer): boolean;
/**
* Check if trader offers' BuyRestrictionMax value has been reached
* @param offer offer to check restriction properties of
* @param offer Offer to check restriction properties of
* @returns true if restriction reached, false if no restrictions/not reached
*/
protected traderBuyRestrictionReached(offer: IRagfairOffer): boolean;
@ -114,7 +121,7 @@ export declare class RagfairOfferHelper {
* Get an array of flea offers that are inaccessible to player due to their inadequate loyalty level
* @param offers Offers to check
* @param pmcProfile Players profile with trader loyalty levels
* @returns array of offer ids player cannot see
* @returns Array of offer ids player cannot see
*/
protected getLoyaltyLockedOffers(offers: IRagfairOffer[], pmcProfile: IPmcData): string[];
/**
@ -126,7 +133,7 @@ export declare class RagfairOfferHelper {
/**
* Count up all rootitem StackObjectsCount properties of an array of items
* @param itemsInInventoryToList items to sum up
* @returns Total count
* @returns Total stack count
*/
getTotalStackCountSize(itemsInInventoryToList: IItem[][]): number;
/**
@ -164,16 +171,16 @@ export declare class RagfairOfferHelper {
protected getLocalisedOfferSoldMessage(itemTpl: string, boughtAmount: number): string;
/**
* Check an offer passes the various search criteria the player requested
* @param searchRequest
* @param offer
* @param pmcData
* @returns True
* @param searchRequest Client search request
* @param offer Offer to check
* @param pmcData Player profile
* @returns True if offer passes criteria
*/
protected passesSearchFilterCriteria(searchRequest: ISearchRequestData, offer: IRagfairOffer, pmcData: IPmcData): boolean;
/**
* Check that the passed in offer item is functional
* @param offerRootItem The root item of the offer
* @param offer The flea offer
* @param offer Flea offer to check
* @returns True if the given item is functional
*/
isItemFunctional(offerRootItem: IItem, offer: IRagfairOffer): boolean;
@ -181,7 +188,7 @@ export declare class RagfairOfferHelper {
* Should a ragfair offer be visible to the player
* @param searchRequest Search request
* @param itemsToAdd ?
* @param traderAssorts Trader assort items
* @param traderAssorts Trader assort items - used for filtering out locked trader items
* @param offer The flea offer
* @param pmcProfile Player profile
* @returns True = should be shown to player

View File

@ -44,10 +44,10 @@ export declare class TraderAssortHelper {
* Filter out assorts not unlocked due to level OR quest completion
* @param sessionId session id
* @param traderId traders id
* @param flea Should assorts player hasn't unlocked be returned - default false
* @param showLockedAssorts Should assorts player hasn't unlocked be returned - default false
* @returns a traders' assorts
*/
getAssort(sessionId: string, traderId: string, flea?: boolean): ITraderAssort;
getAssort(sessionId: string, traderId: string, showLockedAssorts?: boolean): ITraderAssort;
/**
* Given the blacklist provided, remove root items from assort
* @param assortToFilter Trader assort to modify
@ -75,20 +75,10 @@ export declare class TraderAssortHelper {
* @returns true they need refreshing
*/
traderAssortsHaveExpired(traderID: string): boolean;
/**
* Iterate over all assorts barter_scheme values, find barters selling for money and multiply by multipler in config
* @param traderAssort Assorts to multiple price of
*/
protected multiplyItemPricesByConfigMultiplier(traderAssort: ITraderAssort): void;
/**
* Get an array of pristine trader items prior to any alteration by player (as they were on server start)
* @param traderId trader id
* @returns array of Items
*/
protected getPristineTraderAssorts(traderId: string): IItem[];
/**
* Returns generated ragfair offers in a trader assort format
* @returns Trader assort object
*/
protected getRagfairDataAsTraderAssort(): ITraderAssort;
}

View File

@ -153,7 +153,7 @@ export interface IInventory {
/** Key is hideout area enum numeric as string e.g. "24", value is area _id */
hideoutAreaStashes: Record<string, string>;
fastPanel: Record<string, string>;
favoriteItems: IItem[];
favoriteItems: string[];
}
export interface IBaseJsonSkills {
Common: Record<string, Common>;

View File

@ -169,6 +169,13 @@ export interface ISpt {
freeRepeatableRefreshUsedCount?: Record<string, number>;
/** When was a profile migrated, value is timestamp */
migrations?: Record<string, number>;
/** Cultist circle rewards received that are one time use, key (md5) is a combination of sacrificed + reward items */
cultistRewards?: Map<string, IAcceptedCultistReward>;
}
export interface IAcceptedCultistReward {
timestamp: number;
sacrificeItems: string[];
rewardItems: string[];
}
export interface IModDetails {
name: string;

View File

@ -0,0 +1,4 @@
export declare enum CircleRewardType {
RANDOM = 0,
HIDEOUT_TASK = 1
}

View File

@ -18,11 +18,21 @@ export interface ICultistCircleSettings {
maxRewardItemCount: number;
maxAttemptsToPickRewardsWithinBudget: number;
rewardPriceMultiplerMinMax: MinMax;
/** The odds that meeting the highest threshold gives you a bonus to crafting time */
bonusAmountMultiplier: number;
bonusChanceMultiplier: number;
/** What is considered a "high-value" item */
highValueThresholdRub: number;
/** Hideout/task reward crafts have a unique craft time */
hideoutTaskRewardTimeSeconds: number;
/** Rouble amount player needs to sacrifice to get chance of hideout/task rewards */
hideoutCraftSacrificeThresholdRub: number;
craftTimeThreshholds: ICraftTimeThreshhold[];
/** -1 means no override */
/** -1 means no override, value in seconds */
craftTimeOverride: number;
/** Specific reward pool when player sacrificed one specific item */
directRewards: Record<string, IDirectRewardSettings>;
/** Specific reward pool when player sacrifice specific item(s) */
directRewards: IDirectRewardSettings[];
/** Overrides for reward stack sizes, keyed by item tpl */
directRewardStackSize: Record<string, MinMax>;
/** Item tpls to exclude from the reward pool */
rewardItemBlacklist: string[];
@ -34,6 +44,9 @@ export interface ICraftTimeThreshhold extends MinMax {
craftTimeSeconds: number;
}
export interface IDirectRewardSettings {
rewardTpls: string[];
reward: string[];
requiredItems: string[];
craftTimeSeconds: number;
/** Is the reward a one time reward or can it be given multiple times */
repeatable: boolean;
}

View File

@ -4,10 +4,10 @@ import { ILootRequest } from "@spt/models/spt/services/ILootRequest";
export interface ITraderConfig extends IBaseConfig {
kind: "spt-trader";
updateTime: IUpdateTime[];
updateTimeDefault: number;
purchasesAreFoundInRaid: boolean;
/** Should trader reset times be set based on server start time (false = bsg time - on the hour) */
tradersResetFromServerStart: boolean;
updateTimeDefault: number;
traderPriceMultipler: number;
fence: IFenceConfig;
moddedTraders: IModdedTraders;

View File

@ -0,0 +1,8 @@
import { CircleRewardType } from "@spt/models/enums/hideout/CircleRewardType";
import { ICraftTimeThreshhold } from "@spt/models/spt/config/IHideoutConfig";
export interface ICircleCraftDetails {
time: number;
rewardType: CircleRewardType;
rewardAmountRoubles: number;
rewardDetails?: ICraftTimeThreshhold;
}

View File

@ -3,14 +3,17 @@ import { InventoryHelper } from "@spt/helpers/InventoryHelper";
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { PresetHelper } from "@spt/helpers/PresetHelper";
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
import { QuestHelper } from "@spt/helpers/QuestHelper";
import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { IBotHideoutArea } from "@spt/models/eft/common/tables/IBotBase";
import { IItem } from "@spt/models/eft/common/tables/IItem";
import { IStageRequirement } from "@spt/models/eft/hideout/IHideoutArea";
import { IHideoutCircleOfCultistProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutCircleOfCultistProductionStartRequestData";
import { IHideoutProduction, IHideoutProductionData, IRequirement, IRequirementBase } from "@spt/models/eft/hideout/IHideoutProduction";
import { IRequirement, IRequirementBase } from "@spt/models/eft/hideout/IHideoutProduction";
import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse";
import { IDirectRewardSettings, IHideoutConfig } from "@spt/models/spt/config/IHideoutConfig";
import { ICraftTimeThreshhold, ICultistCircleSettings, IDirectRewardSettings, IHideoutConfig } from "@spt/models/spt/config/IHideoutConfig";
import { ICircleCraftDetails } from "@spt/models/spt/hideout/ICircleCraftDetails";
import { IHideout } from "@spt/models/spt/hideout/IHideout";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { EventOutputHolder } from "@spt/routers/EventOutputHolder";
import { ConfigServer } from "@spt/servers/ConfigServer";
@ -33,13 +36,14 @@ export declare class CircleOfCultistService {
protected profileHelper: ProfileHelper;
protected inventoryHelper: InventoryHelper;
protected hideoutHelper: HideoutHelper;
protected questHelper: QuestHelper;
protected databaseService: DatabaseService;
protected itemFilterService: ItemFilterService;
protected seasonalEventService: SeasonalEventService;
protected configServer: ConfigServer;
protected static circleOfCultistSlotId: string;
protected hideoutConfig: IHideoutConfig;
constructor(logger: ILogger, timeUtil: TimeUtil, cloner: ICloner, eventOutputHolder: EventOutputHolder, randomUtil: RandomUtil, hashUtil: HashUtil, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, inventoryHelper: InventoryHelper, hideoutHelper: HideoutHelper, databaseService: DatabaseService, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer);
constructor(logger: ILogger, timeUtil: TimeUtil, cloner: ICloner, eventOutputHolder: EventOutputHolder, randomUtil: RandomUtil, hashUtil: HashUtil, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, inventoryHelper: InventoryHelper, hideoutHelper: HideoutHelper, questHelper: QuestHelper, databaseService: DatabaseService, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer);
/**
* Start a sacrifice event
* Generate rewards
@ -50,24 +54,38 @@ export declare class CircleOfCultistService {
* @returns IItemEventRouterResponse
*/
startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse;
/**
* Create a map of the possible direct rewards, keyed by the items needed to be sacrificed
* @param directRewards Direct rewards array from hideout config
* @returns Map
*/
protected generateSacrificedItemsCache(directRewards: IDirectRewardSettings[]): Map<string, IDirectRewardSettings>;
/**
* Get the reward amount multiple value based on players hideout management skill + configs rewardPriceMultiplerMinMax values
* @param pmcData Player profile
* @param cultistCircleSettings Circle config settings
* @returns Reward Amount Multipler
*/
protected getRewardAmountMultipler(pmcData: IPmcData, cultistCircleSettings: ICultistCircleSettings): number;
/**
* Register production inside player profile
* @param sessionId Session id
* @param pmcData Player profile
* @param recipeId Recipe id
* @param sacrificedItems Items player sacrificed
* @param rewardAmountRoubles Rouble amount to reward player in items with
* @param directRewardSettings OPTIONAL: If craft is giving direct rewards
* @param craftingTime How long the ritual should take
*/
protected registerCircleOfCultistProduction(sessionId: string, pmcData: IPmcData, recipeId: string, sacrificedItems: IItem[], rewardAmountRoubles: number, directRewardSettings?: IDirectRewardSettings): void;
protected registerCircleOfCultistProduction(sessionId: string, pmcData: IPmcData, recipeId: string, sacrificedItems: IItem[], craftingTime: number): void;
/**
* Get the circle craft time as seconds, value is based on reward item value
* OR rewards are direct, then use custom craft time defined in oarameter object
* And get the bonus status to determine what tier of reward is given
* @param rewardAmountRoubles Value of rewards in roubles
* @param directRewardSettings OPTIONAL: If craft is giving direct rewards
* @returns craft time seconds
* @param circleConfig Circle config values
* @param directRewardSettings OPTIONAL - Values related to direct reward being given
* @returns craft time + type of reward + reward details
*/
protected getCircleCraftTimeSeconds(rewardAmountRoubles: number, directRewardSettings?: IDirectRewardSettings): number;
protected getCircleCraftingInfo(rewardAmountRoubles: number, circleConfig: ICultistCircleSettings, directRewardSettings?: IDirectRewardSettings): ICircleCraftDetails;
protected getMatchingThreshold(thresholds: ICraftTimeThreshhold[], rewardAmountRoubles: number): ICraftTimeThreshhold;
/**
* Get the items player sacrificed in circle
* @param pmcData Player profile
@ -81,20 +99,40 @@ export declare class CircleOfCultistService {
* @param cultistCircleStashId Id of stash item
* @returns Array of item arrays
*/
protected getRewardsWithinBudget(rewardItemTplPool: string[], rewardBudget: number, cultistCircleStashId: string): IItem[][];
protected getRewardsWithinBudget(rewardItemTplPool: string[], rewardBudget: number, cultistCircleStashId: string, circleConfig: ICultistCircleSettings): IItem[][];
/**
* Give every item as a reward that's passed in
* @param rewardTpls Item tpls to turn into reward items
* Get direct rewards
* @param sessionId sessionId
* @param directReward Items sacrificed
* @param cultistCircleStashId Id of stash item
* @returns Array of item arrays
* @returns The reward object
*/
protected getExplicitRewards(explicitRewardSettings: IDirectRewardSettings, cultistCircleStashId: string): IItem[][];
protected getDirectRewards(sessionId: string, directReward: IDirectRewardSettings, cultistCircleStashId: string): IItem[][];
/**
* Check for direct rewards from what player sacrificed
* @param sessionId sessionId
* @param sacrificedItems Items sacrificed
* @returns Direct reward items to send to player
*/
protected checkForDirectReward(sessionId: string, sacrificedItems: IItem[], directRewardsCache: Map<string, IDirectRewardSettings>): IDirectRewardSettings;
/**
* Create an md5 key of the sacrificed + reward items
* @param directReward Direct reward to create key for
* @returns Key
*/
protected getDirectRewardHashKey(directReward: IDirectRewardSettings): string;
/**
* Explicit rewards have thier own stack sizes as they dont use a reward rouble pool
* @param rewardTpl Item being rewarded to get stack size of
* @returns stack size of item
*/
protected getExplicitRewardBaseTypeStackSize(rewardTpl: string): number;
protected getDirectRewardBaseTypeStackSize(rewardTpl: string): number;
/**
* Add a record to the players profile to signal they have accepted a non-repeatable direct reward
* @param sessionId Session id
* @param directReward Reward sent to player
*/
protected flagDirectRewardAsAcceptedInProfile(sessionId: string, directReward: IDirectRewardSettings): void;
/**
* Get the size of a reward items stack
* 1 for everything except ammo, ammo can be between min stack and max stack
@ -107,9 +145,26 @@ export declare class CircleOfCultistService {
* Get a pool of tpl IDs of items the player needs to complete hideout crafts/upgrade areas
* @param sessionId Session id
* @param pmcData Profile of player who will be getting the rewards
* @param rewardType Do we return bonus items (hideout/task items)
* @param cultistCircleConfig Circle config
* @returns Array of tpls
*/
protected getCultistCircleRewardPool(sessionId: string, pmcData: IPmcData): string[];
protected getCultistCircleRewardPool(sessionId: string, pmcData: IPmcData, craftingInfo: ICircleCraftDetails, cultistCircleConfig: ICultistCircleSettings): string[];
/**
* Check players profile for quests with hand-in requirements and add those required items to the pool
* @param pmcData Player profile
* @param itemRewardBlacklist Items not to add to pool
* @param rewardPool Pool to add items to
*/
protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set<string>): void;
/**
* Adds items the player needs to complete hideout crafts/upgrades to the reward pool
* @param hideoutDbData Hideout area data
* @param pmcData Player profile
* @param itemRewardBlacklist Items not to add to pool
* @param rewardPool Pool to add items to
*/
protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set<string>): void;
/**
* Get all active hideout areas
* @param areas Hideout areas to iterate over
@ -117,12 +172,13 @@ export declare class CircleOfCultistService {
*/
protected getPlayerAccessibleHideoutAreas(areas: IBotHideoutArea[]): IBotHideoutArea[];
/**
* Get all recipes the player has access to, includes base + unlocked recipes
* @param unlockedRecipes Recipes player has flagged as unlocked
* @param allRecipes All recipes
* @returns Array of recipes
* Get array of random reward items
* @param rewardPool Reward pool to add to
* @param itemRewardBlacklist Reward Blacklist
* @param itemsShouldBeHighValue Should these items meet the valuable threshold
* @returns rewardPool
*/
protected getPlayerAccessibleRecipes(unlockedRecipes: string[], allRecipes: IHideoutProductionData): IHideoutProduction[];
protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set<string>, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set<string>;
/**
* Iterate over passed in hideout requirements and return the Item
* @param requirements Requirements to iterate over

View File

@ -87,6 +87,12 @@ export declare class ProfileFixerService {
* @returns
*/
protected verifyQuestProductionUnlock(pmcProfile: IPmcData, productionUnlockReward: IQuestReward, questDetails: IQuest): void;
/**
* Initial release of SPT 3.10 used an incorrect favorites structure, reformat
* the structure to the correct MongoID array structure
* @param pmcProfile
*/
protected fixFavorites(pmcProfile: IPmcData): void;
/**
* If the profile has elite Hideout Managment skill, add the additional slots from globals
* NOTE: This seems redundant, but we will leave it here just incase.

View File

@ -138,6 +138,12 @@ export declare class SeasonalEventService {
*/
protected enableHalloweenSummonEvent(): void;
protected configureZombies(zombieSettings: IZombieSettings): void;
/**
* Get location ids of maps with an infection above 0
* @param locationInfections Dict of locations with their infection percentage
* @returns Array of location ids
*/
protected getLocationsWithZombies(locationInfections: Record<string, number>): string[];
/**
* BSG store the location ids differently inside `LocationInfection`, need to convert to matching location IDs
* @param infectedLocationKey Key to convert

View File

@ -1,38 +0,0 @@
import { ILogger } from "@spt/models/spt/utils/ILogger";
export declare class DatabaseDecompressionUtil {
protected logger: ILogger;
private compressedDir;
private assetsDir;
private compiled;
constructor(logger: ILogger);
/**
* Checks if the application is running in a compiled environment. A simple check is done to see if the relative
* assets directory exists. If it does not, the application is assumed to be running in a compiled environment. All
* relative asset paths are different within a compiled environment, so this simple check is sufficient.
*/
private isCompiled;
/**
* Initializes the database compression utility.
*
* This method will decompress all 7-zip archives within the compressed database directory. The decompressed files
* are placed in their respective directories based on the name and location of the compressed file.
*/
initialize(): Promise<void>;
/**
* Retrieves a list of all 7-zip archives within the compressed database directory.
*/
private getCompressedFiles;
/**
* Processes a compressed file by checking if the target directory is empty, and if so, decompressing the file into
* the target directory.
*/
private processCompressedFile;
/**
* Checks if a directory exists and is empty.
*/
private isDirectoryEmpty;
/**
* Decompresses a 7-zip archive to the target directory.
*/
private decompressFile;
}

View File

@ -106,77 +106,177 @@ export declare class RandomUtil {
protected cloner: ICloner;
protected logger: ILogger;
constructor(cloner: ICloner, logger: ILogger);
/**
* Generates a secure random number between 0 (inclusive) and 1 (exclusive).
*
* This method uses the `crypto` module to generate a 48-bit random integer,
* which is then divided by the maximum possible 48-bit integer value to
* produce a floating-point number in the range [0, 1).
*
* @returns A secure random number between 0 (inclusive) and 1 (exclusive).
*/
private getSecureRandomNumber;
/**
* Generates a random integer between the specified minimum and maximum values, inclusive.
*
* @param min - The minimum value (inclusive).
* @param max - The maximum value (inclusive).
* @returns A random integer between the specified minimum and maximum values.
*/
getInt(min: number, max: number): number;
/**
* Generates a random integer between 1 (inclusive) and the specified maximum value (exclusive).
* If the maximum value is less than or equal to 1, it returns 1.
*
* @param max - The upper bound (exclusive) for the random integer generation.
* @returns A random integer between 1 and max - 1, or 1 if max is less than or equal to 1.
*/
getIntEx(max: number): number;
/**
* Generates a random floating-point number within the specified range.
*
* @param min - The minimum value of the range (inclusive).
* @param max - The maximum value of the range (exclusive).
* @returns A random floating-point number between `min` (inclusive) and `max` (exclusive).
*/
getFloat(min: number, max: number): number;
/**
* Generates a random boolean value.
*
* @returns A random boolean value, where the probability of `true` and `false` is approximately equal.
*/
getBool(): boolean;
/**
* Calculates the percentage of a given number and returns the result.
*
* @param percent - The percentage to calculate.
* @param number - The number to calculate the percentage of.
* @param toFixed - The number of decimal places to round the result to (default is 2).
* @returns The calculated percentage of the given number, rounded to the specified number of decimal places.
*/
getPercentOfValue(percent: number, number: number, toFixed?: number): number;
/**
* Reduce a value by a percentage
* @param number Value to reduce
* @param percentage Percentage to reduce value by
* @returns Reduced value
* Reduces a given number by a specified percentage.
*
* @param number - The original number to be reduced.
* @param percentage - The percentage by which to reduce the number.
* @returns The reduced number after applying the percentage reduction.
*/
reduceValueByPercent(number: number, percentage: number): number;
/**
* Check if number passes a check out of 100
* @param chancePercent value check needs to be above
* @returns true if value passes check
* Determines if a random event occurs based on the given chance percentage.
*
* @param chancePercent - The percentage chance (0-100) that the event will occur.
* @returns `true` if the event occurs, `false` otherwise.
*/
getChance100(chancePercent: number): boolean;
/**
* Returns a random string from the provided array of strings.
*
* This method is separate from getArrayValue so we can use a generic inferance with getArrayValue.
*
* @param arr - The array of strings to select a random value from.
* @returns A randomly selected string from the array.
*/
getStringArrayValue(arr: string[]): string;
/**
* Returns a random element from the provided array.
*
* @template T - The type of elements in the array.
* @param arr - The array from which to select a random element.
* @returns A random element from the array.
*/
getArrayValue<T>(arr: T[]): T;
/**
* Retrieves a random key from the given object.
*
* @param node - The object from which to retrieve a key.
* @returns A string representing one of the keys of the node object.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
getKey(node: any): string;
/**
* Retrieves the value associated with a key from the given node object.
*
* @param node - An object with string keys and any type of values.
* @returns The value associated with the key obtained from the node.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
getKeyValue(node: {
[x: string]: any;
}): any;
/**
* Generate a normally distributed random number
* Uses the Box-Muller transform
* @param {number} mean Mean of the normal distribution
* @param {number} sigma Standard deviation of the normal distribution
* @returns {number} The value drawn
* Generates a normally distributed random number using the Box-Muller transform.
*
* @param mean - The mean (μ) of the normal distribution.
* @param sigma - The standard deviation (σ) of the normal distribution.
* @param attempt - The current attempt count to generate a valid number (default is 0).
* @returns A normally distributed random number.
*
* @remarks
* This function uses the Box-Muller transform to generate a normally distributed random number.
* If the generated number is less than 0, it will recursively attempt to generate a valid number up to 100 times.
* If it fails to generate a valid number after 100 attempts, it will return a random float between 0.01 and twice the mean.
*/
getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number;
/**
* Draw Random integer low inclusive, high exclusive
* if high is not set we draw from 0 to low (exclusive)
* @param {integer} low Lower bound inclusive, when high is not set, this is high
* @param {integer} high Higher bound exclusive
* @returns {integer} The random integer in [low, high)
* Generates a random integer between the specified range.
*
* @param low - The lower bound of the range (inclusive).
* @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`.
* @returns A random integer within the specified range.
*/
randInt(low: number, high?: number): number;
/**
* Draw a random element of the provided list N times to return an array of N random elements
* Drawing can be with or without replacement
* @param {array} list The array we want to draw randomly from
* @param {integer} count The number of times we want to draw
* @param {boolean} replacement Draw with or without replacement from the input array(default true)
* @return {array} Array consisting of N random elements
* Draws a specified number of random elements from a given list.
*
* @template T - The type of elements in the list.
* @param originalList - The list to draw elements from.
* @param count - The number of elements to draw. Defaults to 1.
* @param replacement - Whether to draw with replacement. Defaults to true.
* @returns An array containing the drawn elements.
*/
drawRandomFromList<T>(originalList: Array<T>, count?: number, replacement?: boolean): Array<T>;
/**
* Draw a random (top level) element of the provided dictionary N times to return an array of N random dictionary keys
* Drawing can be with or without replacement
* @param {any} dict The dictionary we want to draw randomly from
* @param {integer} count The number of times we want to draw
* @param {boolean} replacement Draw with ot without replacement from the input dict
* @return {array} Array consisting of N random keys of the dictionary
* Draws a specified number of random keys from a given dictionary.
*
* @param dict - The dictionary from which to draw keys.
* @param count - The number of keys to draw. Defaults to 1.
* @param replacement - Whether to draw with replacement. Defaults to true.
* @returns An array of randomly drawn keys from the dictionary.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
drawRandomFromDict(dict: any, count?: number, replacement?: boolean): any[];
/**
* Generates a biased random number within a specified range.
*
* @param min - The minimum value of the range (inclusive).
* @param max - The maximum value of the range (inclusive).
* @param shift - The bias shift to apply to the random number generation.
* @param n - The number of iterations to use for generating a Gaussian random number.
* @returns A biased random number within the specified range.
* @throws Will throw if `max` is less than `min` or if `n` is less than 1.
*/
getBiasedRandomNumber(min: number, max: number, shift: number, n: number): number;
/**
* Fisher-Yates shuffle an array
* @param array Array to shuffle
* @returns Shuffled array
* Shuffles an array in place using the Fisher-Yates algorithm.
*
* @template T - The type of elements in the array.
* @param array - The array to shuffle.
* @returns The shuffled array.
*/
shuffle<T>(array: Array<T>): Array<T>;
/**
* Rolls for a probability based on chance
* @param number Probability Chance as float (0-1)
* @returns If roll succeed or not
* @example
* rollForChanceProbability(0.25); // returns true 25% probability
* Rolls for a chance probability and returns whether the roll is successful.
*
* @param probabilityChance - The probability chance to roll for, represented as a number between 0 and 1.
* @returns `true` if the random number is less than or equal to the probability chance, otherwise `false`.
*/
rollForChanceProbability(probabilityChance: number): boolean;
}

View File

@ -118,6 +118,9 @@ export declare class ProfileController {
* Handle client/profile/status
*/
getProfileStatus(sessionId: string): IGetProfileStatusResponseData;
/**
* Handle client/profile/view
*/
getOtherProfile(sessionId: string, request: IGetOtherProfileRequest): IGetOtherProfileResponse;
/**
* Handle client/profile/settings

View File

@ -114,9 +114,10 @@ export declare class BotEquipmentModGenerator {
/**
* Sort mod slots into an ordering that maximises chance of a successful weapon generation
* @param unsortedSlotKeys Array of mod slot strings to sort
* @param itemTplWithKeysToSort The Tpl of the item with mod keys being sorted
* @returns Sorted array
*/
protected sortModKeys(unsortedSlotKeys: string[]): string[];
protected sortModKeys(unsortedSlotKeys: string[], itemTplWithKeysToSort: string): string[];
/**
* Get a Slot property for an item (chamber/cartridge/slot)
* @param modSlot e.g patron_in_weapon

View File

@ -12,6 +12,7 @@ import { IBarterScheme } from "@spt/models/eft/common/tables/ITrader";
import { IOfferRequirement, IRagfairOffer, IRagfairOfferUser } from "@spt/models/eft/ragfair/IRagfairOffer";
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
import { IArmorPlateBlacklistSettings, IBarterDetails, IDynamic, IRagfairConfig } from "@spt/models/spt/config/IRagfairConfig";
import { ITraderConfig } from "@spt/models/spt/config/ITraderConfig";
import { ITplWithFleaPrice } from "@spt/models/spt/ragfair/ITplWithFleaPrice";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
@ -47,6 +48,7 @@ export declare class RagfairOfferGenerator {
protected configServer: ConfigServer;
protected cloner: ICloner;
protected ragfairConfig: IRagfairConfig;
protected traderConfig: ITraderConfig;
protected botConfig: IBotConfig;
protected allowedFleaPriceItemsForBarter: {
tpl: string;
@ -83,7 +85,7 @@ export declare class RagfairOfferGenerator {
* @param isTrader Is the user creating the offer a trader
* @returns IRagfairOfferUser
*/
createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser;
protected createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser;
/**
* Calculate the offer price that's listed on the flea listing
* @param offerRequirements barter requirements for offer

View File

@ -209,4 +209,10 @@ export declare class ProfileHelper {
* @returns Array of item objects
*/
getQuestItemsInProfile(profile: IPmcData): IItem[];
/**
* Return a favorites array in the format expected by the getOtherProfile call
* @param profile
* @returns An array of IItem objects representing the favorited data
*/
getOtherProfileFavorites(profile: IPmcData): IItem[];
}

View File

@ -282,10 +282,10 @@ export declare class QuestHelper {
*/
protected findAndAddHideoutProductionIdToProfile(pmcData: IPmcData, craftUnlockReward: IQuestReward, questDetails: IQuest, sessionID: string, response: IItemEventRouterResponse): void;
/**
* Find hideout craft id for the specified quest reward
* @param craftUnlockReward
* @param questDetails
* @returns
* Find hideout craft for the specified quest reward
* @param craftUnlockReward Reward item from quest with craft unlock details
* @param questDetails Quest with craft unlock reward
* @returns Hideout craft
*/
getRewardProductionMatch(craftUnlockReward: IQuestReward, questDetails: IQuest): IHideoutProduction[];
/**
@ -332,16 +332,15 @@ export declare class QuestHelper {
/**
* Create a clone of the given quest array with the rewards updated to reflect the
* given game version
*
* @param quests The list of quests to check
* @param gameVersion The game version of the profile
* @returns array of IQuest objects with the rewards filtered correctly for the game version
* @param quests List of quests to check
* @param gameVersion Game version of the profile
* @returns Array of IQuest objects with the rewards filtered correctly for the game version
*/
protected updateQuestsForGameEdition(quests: IQuest[], gameVersion: string): IQuest[];
/**
* Return a list of quests that would fail when supplied quest is completed
* @param completedQuestId quest completed id
* @returns array of IQuest objects
* @param completedQuestId Quest completed id
* @returns Array of IQuest objects
*/
protected getQuestsFromProfileFailedByCompletingQuest(completedQuestId: string, pmcProfile: IPmcData): IQuest[];
/**

View File

@ -67,6 +67,13 @@ export declare class RagfairOfferHelper {
* @returns Offers the player should see
*/
getValidOffers(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record<string, ITraderAssort>, pmcData: IPmcData): IRagfairOffer[];
/**
* Disable offer if item is flagged by tiered flea config
* @param tieredFlea Tiered flea settings from ragfair config
* @param offer Ragfair offer to check
* @param tieredFleaLimitTypes Dict of item types with player level to be viewable
* @param playerLevel Level of player viewing offer
*/
protected checkAndLockOfferFromPlayerTieredFlea(tieredFlea: ITieredFlea, offer: IRagfairOffer, tieredFleaLimitTypes: string[], playerLevel: number): void;
/**
* Get matching offers that require the desired item and filter out offers from non traders if player is below ragfair unlock level
@ -99,14 +106,14 @@ export declare class RagfairOfferHelper {
*/
traderOfferItemQuestLocked(offer: IRagfairOffer, traderAssorts: Record<string, ITraderAssort>): boolean;
/**
* Has a traders offer ran out of stock to sell to player
* Has trader offer ran out of stock to sell to player
* @param offer Offer to check stock of
* @returns true if out of stock
*/
protected traderOutOfStock(offer: IRagfairOffer): boolean;
/**
* Check if trader offers' BuyRestrictionMax value has been reached
* @param offer offer to check restriction properties of
* @param offer Offer to check restriction properties of
* @returns true if restriction reached, false if no restrictions/not reached
*/
protected traderBuyRestrictionReached(offer: IRagfairOffer): boolean;
@ -114,7 +121,7 @@ export declare class RagfairOfferHelper {
* Get an array of flea offers that are inaccessible to player due to their inadequate loyalty level
* @param offers Offers to check
* @param pmcProfile Players profile with trader loyalty levels
* @returns array of offer ids player cannot see
* @returns Array of offer ids player cannot see
*/
protected getLoyaltyLockedOffers(offers: IRagfairOffer[], pmcProfile: IPmcData): string[];
/**
@ -126,7 +133,7 @@ export declare class RagfairOfferHelper {
/**
* Count up all rootitem StackObjectsCount properties of an array of items
* @param itemsInInventoryToList items to sum up
* @returns Total count
* @returns Total stack count
*/
getTotalStackCountSize(itemsInInventoryToList: IItem[][]): number;
/**
@ -164,16 +171,16 @@ export declare class RagfairOfferHelper {
protected getLocalisedOfferSoldMessage(itemTpl: string, boughtAmount: number): string;
/**
* Check an offer passes the various search criteria the player requested
* @param searchRequest
* @param offer
* @param pmcData
* @returns True
* @param searchRequest Client search request
* @param offer Offer to check
* @param pmcData Player profile
* @returns True if offer passes criteria
*/
protected passesSearchFilterCriteria(searchRequest: ISearchRequestData, offer: IRagfairOffer, pmcData: IPmcData): boolean;
/**
* Check that the passed in offer item is functional
* @param offerRootItem The root item of the offer
* @param offer The flea offer
* @param offer Flea offer to check
* @returns True if the given item is functional
*/
isItemFunctional(offerRootItem: IItem, offer: IRagfairOffer): boolean;
@ -181,7 +188,7 @@ export declare class RagfairOfferHelper {
* Should a ragfair offer be visible to the player
* @param searchRequest Search request
* @param itemsToAdd ?
* @param traderAssorts Trader assort items
* @param traderAssorts Trader assort items - used for filtering out locked trader items
* @param offer The flea offer
* @param pmcProfile Player profile
* @returns True = should be shown to player

View File

@ -44,10 +44,10 @@ export declare class TraderAssortHelper {
* Filter out assorts not unlocked due to level OR quest completion
* @param sessionId session id
* @param traderId traders id
* @param flea Should assorts player hasn't unlocked be returned - default false
* @param showLockedAssorts Should assorts player hasn't unlocked be returned - default false
* @returns a traders' assorts
*/
getAssort(sessionId: string, traderId: string, flea?: boolean): ITraderAssort;
getAssort(sessionId: string, traderId: string, showLockedAssorts?: boolean): ITraderAssort;
/**
* Given the blacklist provided, remove root items from assort
* @param assortToFilter Trader assort to modify
@ -75,20 +75,10 @@ export declare class TraderAssortHelper {
* @returns true they need refreshing
*/
traderAssortsHaveExpired(traderID: string): boolean;
/**
* Iterate over all assorts barter_scheme values, find barters selling for money and multiply by multipler in config
* @param traderAssort Assorts to multiple price of
*/
protected multiplyItemPricesByConfigMultiplier(traderAssort: ITraderAssort): void;
/**
* Get an array of pristine trader items prior to any alteration by player (as they were on server start)
* @param traderId trader id
* @returns array of Items
*/
protected getPristineTraderAssorts(traderId: string): IItem[];
/**
* Returns generated ragfair offers in a trader assort format
* @returns Trader assort object
*/
protected getRagfairDataAsTraderAssort(): ITraderAssort;
}

View File

@ -153,7 +153,7 @@ export interface IInventory {
/** Key is hideout area enum numeric as string e.g. "24", value is area _id */
hideoutAreaStashes: Record<string, string>;
fastPanel: Record<string, string>;
favoriteItems: IItem[];
favoriteItems: string[];
}
export interface IBaseJsonSkills {
Common: Record<string, Common>;

View File

@ -169,6 +169,13 @@ export interface ISpt {
freeRepeatableRefreshUsedCount?: Record<string, number>;
/** When was a profile migrated, value is timestamp */
migrations?: Record<string, number>;
/** Cultist circle rewards received that are one time use, key (md5) is a combination of sacrificed + reward items */
cultistRewards?: Map<string, IAcceptedCultistReward>;
}
export interface IAcceptedCultistReward {
timestamp: number;
sacrificeItems: string[];
rewardItems: string[];
}
export interface IModDetails {
name: string;

View File

@ -0,0 +1,4 @@
export declare enum CircleRewardType {
RANDOM = 0,
HIDEOUT_TASK = 1
}

View File

@ -18,11 +18,21 @@ export interface ICultistCircleSettings {
maxRewardItemCount: number;
maxAttemptsToPickRewardsWithinBudget: number;
rewardPriceMultiplerMinMax: MinMax;
/** The odds that meeting the highest threshold gives you a bonus to crafting time */
bonusAmountMultiplier: number;
bonusChanceMultiplier: number;
/** What is considered a "high-value" item */
highValueThresholdRub: number;
/** Hideout/task reward crafts have a unique craft time */
hideoutTaskRewardTimeSeconds: number;
/** Rouble amount player needs to sacrifice to get chance of hideout/task rewards */
hideoutCraftSacrificeThresholdRub: number;
craftTimeThreshholds: ICraftTimeThreshhold[];
/** -1 means no override */
/** -1 means no override, value in seconds */
craftTimeOverride: number;
/** Specific reward pool when player sacrificed one specific item */
directRewards: Record<string, IDirectRewardSettings>;
/** Specific reward pool when player sacrifice specific item(s) */
directRewards: IDirectRewardSettings[];
/** Overrides for reward stack sizes, keyed by item tpl */
directRewardStackSize: Record<string, MinMax>;
/** Item tpls to exclude from the reward pool */
rewardItemBlacklist: string[];
@ -34,6 +44,9 @@ export interface ICraftTimeThreshhold extends MinMax {
craftTimeSeconds: number;
}
export interface IDirectRewardSettings {
rewardTpls: string[];
reward: string[];
requiredItems: string[];
craftTimeSeconds: number;
/** Is the reward a one time reward or can it be given multiple times */
repeatable: boolean;
}

View File

@ -4,10 +4,10 @@ import { ILootRequest } from "@spt/models/spt/services/ILootRequest";
export interface ITraderConfig extends IBaseConfig {
kind: "spt-trader";
updateTime: IUpdateTime[];
updateTimeDefault: number;
purchasesAreFoundInRaid: boolean;
/** Should trader reset times be set based on server start time (false = bsg time - on the hour) */
tradersResetFromServerStart: boolean;
updateTimeDefault: number;
traderPriceMultipler: number;
fence: IFenceConfig;
moddedTraders: IModdedTraders;

View File

@ -0,0 +1,8 @@
import { CircleRewardType } from "@spt/models/enums/hideout/CircleRewardType";
import { ICraftTimeThreshhold } from "@spt/models/spt/config/IHideoutConfig";
export interface ICircleCraftDetails {
time: number;
rewardType: CircleRewardType;
rewardAmountRoubles: number;
rewardDetails?: ICraftTimeThreshhold;
}

View File

@ -3,14 +3,17 @@ import { InventoryHelper } from "@spt/helpers/InventoryHelper";
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { PresetHelper } from "@spt/helpers/PresetHelper";
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
import { QuestHelper } from "@spt/helpers/QuestHelper";
import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { IBotHideoutArea } from "@spt/models/eft/common/tables/IBotBase";
import { IItem } from "@spt/models/eft/common/tables/IItem";
import { IStageRequirement } from "@spt/models/eft/hideout/IHideoutArea";
import { IHideoutCircleOfCultistProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutCircleOfCultistProductionStartRequestData";
import { IHideoutProduction, IHideoutProductionData, IRequirement, IRequirementBase } from "@spt/models/eft/hideout/IHideoutProduction";
import { IRequirement, IRequirementBase } from "@spt/models/eft/hideout/IHideoutProduction";
import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse";
import { IDirectRewardSettings, IHideoutConfig } from "@spt/models/spt/config/IHideoutConfig";
import { ICraftTimeThreshhold, ICultistCircleSettings, IDirectRewardSettings, IHideoutConfig } from "@spt/models/spt/config/IHideoutConfig";
import { ICircleCraftDetails } from "@spt/models/spt/hideout/ICircleCraftDetails";
import { IHideout } from "@spt/models/spt/hideout/IHideout";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { EventOutputHolder } from "@spt/routers/EventOutputHolder";
import { ConfigServer } from "@spt/servers/ConfigServer";
@ -33,13 +36,14 @@ export declare class CircleOfCultistService {
protected profileHelper: ProfileHelper;
protected inventoryHelper: InventoryHelper;
protected hideoutHelper: HideoutHelper;
protected questHelper: QuestHelper;
protected databaseService: DatabaseService;
protected itemFilterService: ItemFilterService;
protected seasonalEventService: SeasonalEventService;
protected configServer: ConfigServer;
protected static circleOfCultistSlotId: string;
protected hideoutConfig: IHideoutConfig;
constructor(logger: ILogger, timeUtil: TimeUtil, cloner: ICloner, eventOutputHolder: EventOutputHolder, randomUtil: RandomUtil, hashUtil: HashUtil, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, inventoryHelper: InventoryHelper, hideoutHelper: HideoutHelper, databaseService: DatabaseService, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer);
constructor(logger: ILogger, timeUtil: TimeUtil, cloner: ICloner, eventOutputHolder: EventOutputHolder, randomUtil: RandomUtil, hashUtil: HashUtil, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, inventoryHelper: InventoryHelper, hideoutHelper: HideoutHelper, questHelper: QuestHelper, databaseService: DatabaseService, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer);
/**
* Start a sacrifice event
* Generate rewards
@ -50,24 +54,38 @@ export declare class CircleOfCultistService {
* @returns IItemEventRouterResponse
*/
startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse;
/**
* Create a map of the possible direct rewards, keyed by the items needed to be sacrificed
* @param directRewards Direct rewards array from hideout config
* @returns Map
*/
protected generateSacrificedItemsCache(directRewards: IDirectRewardSettings[]): Map<string, IDirectRewardSettings>;
/**
* Get the reward amount multiple value based on players hideout management skill + configs rewardPriceMultiplerMinMax values
* @param pmcData Player profile
* @param cultistCircleSettings Circle config settings
* @returns Reward Amount Multipler
*/
protected getRewardAmountMultipler(pmcData: IPmcData, cultistCircleSettings: ICultistCircleSettings): number;
/**
* Register production inside player profile
* @param sessionId Session id
* @param pmcData Player profile
* @param recipeId Recipe id
* @param sacrificedItems Items player sacrificed
* @param rewardAmountRoubles Rouble amount to reward player in items with
* @param directRewardSettings OPTIONAL: If craft is giving direct rewards
* @param craftingTime How long the ritual should take
*/
protected registerCircleOfCultistProduction(sessionId: string, pmcData: IPmcData, recipeId: string, sacrificedItems: IItem[], rewardAmountRoubles: number, directRewardSettings?: IDirectRewardSettings): void;
protected registerCircleOfCultistProduction(sessionId: string, pmcData: IPmcData, recipeId: string, sacrificedItems: IItem[], craftingTime: number): void;
/**
* Get the circle craft time as seconds, value is based on reward item value
* OR rewards are direct, then use custom craft time defined in oarameter object
* And get the bonus status to determine what tier of reward is given
* @param rewardAmountRoubles Value of rewards in roubles
* @param directRewardSettings OPTIONAL: If craft is giving direct rewards
* @returns craft time seconds
* @param circleConfig Circle config values
* @param directRewardSettings OPTIONAL - Values related to direct reward being given
* @returns craft time + type of reward + reward details
*/
protected getCircleCraftTimeSeconds(rewardAmountRoubles: number, directRewardSettings?: IDirectRewardSettings): number;
protected getCircleCraftingInfo(rewardAmountRoubles: number, circleConfig: ICultistCircleSettings, directRewardSettings?: IDirectRewardSettings): ICircleCraftDetails;
protected getMatchingThreshold(thresholds: ICraftTimeThreshhold[], rewardAmountRoubles: number): ICraftTimeThreshhold;
/**
* Get the items player sacrificed in circle
* @param pmcData Player profile
@ -81,20 +99,40 @@ export declare class CircleOfCultistService {
* @param cultistCircleStashId Id of stash item
* @returns Array of item arrays
*/
protected getRewardsWithinBudget(rewardItemTplPool: string[], rewardBudget: number, cultistCircleStashId: string): IItem[][];
protected getRewardsWithinBudget(rewardItemTplPool: string[], rewardBudget: number, cultistCircleStashId: string, circleConfig: ICultistCircleSettings): IItem[][];
/**
* Give every item as a reward that's passed in
* @param rewardTpls Item tpls to turn into reward items
* Get direct rewards
* @param sessionId sessionId
* @param directReward Items sacrificed
* @param cultistCircleStashId Id of stash item
* @returns Array of item arrays
* @returns The reward object
*/
protected getExplicitRewards(explicitRewardSettings: IDirectRewardSettings, cultistCircleStashId: string): IItem[][];
protected getDirectRewards(sessionId: string, directReward: IDirectRewardSettings, cultistCircleStashId: string): IItem[][];
/**
* Check for direct rewards from what player sacrificed
* @param sessionId sessionId
* @param sacrificedItems Items sacrificed
* @returns Direct reward items to send to player
*/
protected checkForDirectReward(sessionId: string, sacrificedItems: IItem[], directRewardsCache: Map<string, IDirectRewardSettings>): IDirectRewardSettings;
/**
* Create an md5 key of the sacrificed + reward items
* @param directReward Direct reward to create key for
* @returns Key
*/
protected getDirectRewardHashKey(directReward: IDirectRewardSettings): string;
/**
* Explicit rewards have thier own stack sizes as they dont use a reward rouble pool
* @param rewardTpl Item being rewarded to get stack size of
* @returns stack size of item
*/
protected getExplicitRewardBaseTypeStackSize(rewardTpl: string): number;
protected getDirectRewardBaseTypeStackSize(rewardTpl: string): number;
/**
* Add a record to the players profile to signal they have accepted a non-repeatable direct reward
* @param sessionId Session id
* @param directReward Reward sent to player
*/
protected flagDirectRewardAsAcceptedInProfile(sessionId: string, directReward: IDirectRewardSettings): void;
/**
* Get the size of a reward items stack
* 1 for everything except ammo, ammo can be between min stack and max stack
@ -107,9 +145,26 @@ export declare class CircleOfCultistService {
* Get a pool of tpl IDs of items the player needs to complete hideout crafts/upgrade areas
* @param sessionId Session id
* @param pmcData Profile of player who will be getting the rewards
* @param rewardType Do we return bonus items (hideout/task items)
* @param cultistCircleConfig Circle config
* @returns Array of tpls
*/
protected getCultistCircleRewardPool(sessionId: string, pmcData: IPmcData): string[];
protected getCultistCircleRewardPool(sessionId: string, pmcData: IPmcData, craftingInfo: ICircleCraftDetails, cultistCircleConfig: ICultistCircleSettings): string[];
/**
* Check players profile for quests with hand-in requirements and add those required items to the pool
* @param pmcData Player profile
* @param itemRewardBlacklist Items not to add to pool
* @param rewardPool Pool to add items to
*/
protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set<string>): void;
/**
* Adds items the player needs to complete hideout crafts/upgrades to the reward pool
* @param hideoutDbData Hideout area data
* @param pmcData Player profile
* @param itemRewardBlacklist Items not to add to pool
* @param rewardPool Pool to add items to
*/
protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set<string>): void;
/**
* Get all active hideout areas
* @param areas Hideout areas to iterate over
@ -117,12 +172,13 @@ export declare class CircleOfCultistService {
*/
protected getPlayerAccessibleHideoutAreas(areas: IBotHideoutArea[]): IBotHideoutArea[];
/**
* Get all recipes the player has access to, includes base + unlocked recipes
* @param unlockedRecipes Recipes player has flagged as unlocked
* @param allRecipes All recipes
* @returns Array of recipes
* Get array of random reward items
* @param rewardPool Reward pool to add to
* @param itemRewardBlacklist Reward Blacklist
* @param itemsShouldBeHighValue Should these items meet the valuable threshold
* @returns rewardPool
*/
protected getPlayerAccessibleRecipes(unlockedRecipes: string[], allRecipes: IHideoutProductionData): IHideoutProduction[];
protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set<string>, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set<string>;
/**
* Iterate over passed in hideout requirements and return the Item
* @param requirements Requirements to iterate over

View File

@ -87,6 +87,12 @@ export declare class ProfileFixerService {
* @returns
*/
protected verifyQuestProductionUnlock(pmcProfile: IPmcData, productionUnlockReward: IQuestReward, questDetails: IQuest): void;
/**
* Initial release of SPT 3.10 used an incorrect favorites structure, reformat
* the structure to the correct MongoID array structure
* @param pmcProfile
*/
protected fixFavorites(pmcProfile: IPmcData): void;
/**
* If the profile has elite Hideout Managment skill, add the additional slots from globals
* NOTE: This seems redundant, but we will leave it here just incase.

View File

@ -138,6 +138,12 @@ export declare class SeasonalEventService {
*/
protected enableHalloweenSummonEvent(): void;
protected configureZombies(zombieSettings: IZombieSettings): void;
/**
* Get location ids of maps with an infection above 0
* @param locationInfections Dict of locations with their infection percentage
* @returns Array of location ids
*/
protected getLocationsWithZombies(locationInfections: Record<string, number>): string[];
/**
* BSG store the location ids differently inside `LocationInfection`, need to convert to matching location IDs
* @param infectedLocationKey Key to convert

View File

@ -1,38 +0,0 @@
import { ILogger } from "@spt/models/spt/utils/ILogger";
export declare class DatabaseDecompressionUtil {
protected logger: ILogger;
private compressedDir;
private assetsDir;
private compiled;
constructor(logger: ILogger);
/**
* Checks if the application is running in a compiled environment. A simple check is done to see if the relative
* assets directory exists. If it does not, the application is assumed to be running in a compiled environment. All
* relative asset paths are different within a compiled environment, so this simple check is sufficient.
*/
private isCompiled;
/**
* Initializes the database compression utility.
*
* This method will decompress all 7-zip archives within the compressed database directory. The decompressed files
* are placed in their respective directories based on the name and location of the compressed file.
*/
initialize(): Promise<void>;
/**
* Retrieves a list of all 7-zip archives within the compressed database directory.
*/
private getCompressedFiles;
/**
* Processes a compressed file by checking if the target directory is empty, and if so, decompressing the file into
* the target directory.
*/
private processCompressedFile;
/**
* Checks if a directory exists and is empty.
*/
private isDirectoryEmpty;
/**
* Decompresses a 7-zip archive to the target directory.
*/
private decompressFile;
}

View File

@ -106,77 +106,177 @@ export declare class RandomUtil {
protected cloner: ICloner;
protected logger: ILogger;
constructor(cloner: ICloner, logger: ILogger);
/**
* Generates a secure random number between 0 (inclusive) and 1 (exclusive).
*
* This method uses the `crypto` module to generate a 48-bit random integer,
* which is then divided by the maximum possible 48-bit integer value to
* produce a floating-point number in the range [0, 1).
*
* @returns A secure random number between 0 (inclusive) and 1 (exclusive).
*/
private getSecureRandomNumber;
/**
* Generates a random integer between the specified minimum and maximum values, inclusive.
*
* @param min - The minimum value (inclusive).
* @param max - The maximum value (inclusive).
* @returns A random integer between the specified minimum and maximum values.
*/
getInt(min: number, max: number): number;
/**
* Generates a random integer between 1 (inclusive) and the specified maximum value (exclusive).
* If the maximum value is less than or equal to 1, it returns 1.
*
* @param max - The upper bound (exclusive) for the random integer generation.
* @returns A random integer between 1 and max - 1, or 1 if max is less than or equal to 1.
*/
getIntEx(max: number): number;
/**
* Generates a random floating-point number within the specified range.
*
* @param min - The minimum value of the range (inclusive).
* @param max - The maximum value of the range (exclusive).
* @returns A random floating-point number between `min` (inclusive) and `max` (exclusive).
*/
getFloat(min: number, max: number): number;
/**
* Generates a random boolean value.
*
* @returns A random boolean value, where the probability of `true` and `false` is approximately equal.
*/
getBool(): boolean;
/**
* Calculates the percentage of a given number and returns the result.
*
* @param percent - The percentage to calculate.
* @param number - The number to calculate the percentage of.
* @param toFixed - The number of decimal places to round the result to (default is 2).
* @returns The calculated percentage of the given number, rounded to the specified number of decimal places.
*/
getPercentOfValue(percent: number, number: number, toFixed?: number): number;
/**
* Reduce a value by a percentage
* @param number Value to reduce
* @param percentage Percentage to reduce value by
* @returns Reduced value
* Reduces a given number by a specified percentage.
*
* @param number - The original number to be reduced.
* @param percentage - The percentage by which to reduce the number.
* @returns The reduced number after applying the percentage reduction.
*/
reduceValueByPercent(number: number, percentage: number): number;
/**
* Check if number passes a check out of 100
* @param chancePercent value check needs to be above
* @returns true if value passes check
* Determines if a random event occurs based on the given chance percentage.
*
* @param chancePercent - The percentage chance (0-100) that the event will occur.
* @returns `true` if the event occurs, `false` otherwise.
*/
getChance100(chancePercent: number): boolean;
/**
* Returns a random string from the provided array of strings.
*
* This method is separate from getArrayValue so we can use a generic inferance with getArrayValue.
*
* @param arr - The array of strings to select a random value from.
* @returns A randomly selected string from the array.
*/
getStringArrayValue(arr: string[]): string;
/**
* Returns a random element from the provided array.
*
* @template T - The type of elements in the array.
* @param arr - The array from which to select a random element.
* @returns A random element from the array.
*/
getArrayValue<T>(arr: T[]): T;
/**
* Retrieves a random key from the given object.
*
* @param node - The object from which to retrieve a key.
* @returns A string representing one of the keys of the node object.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
getKey(node: any): string;
/**
* Retrieves the value associated with a key from the given node object.
*
* @param node - An object with string keys and any type of values.
* @returns The value associated with the key obtained from the node.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
getKeyValue(node: {
[x: string]: any;
}): any;
/**
* Generate a normally distributed random number
* Uses the Box-Muller transform
* @param {number} mean Mean of the normal distribution
* @param {number} sigma Standard deviation of the normal distribution
* @returns {number} The value drawn
* Generates a normally distributed random number using the Box-Muller transform.
*
* @param mean - The mean (μ) of the normal distribution.
* @param sigma - The standard deviation (σ) of the normal distribution.
* @param attempt - The current attempt count to generate a valid number (default is 0).
* @returns A normally distributed random number.
*
* @remarks
* This function uses the Box-Muller transform to generate a normally distributed random number.
* If the generated number is less than 0, it will recursively attempt to generate a valid number up to 100 times.
* If it fails to generate a valid number after 100 attempts, it will return a random float between 0.01 and twice the mean.
*/
getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number;
/**
* Draw Random integer low inclusive, high exclusive
* if high is not set we draw from 0 to low (exclusive)
* @param {integer} low Lower bound inclusive, when high is not set, this is high
* @param {integer} high Higher bound exclusive
* @returns {integer} The random integer in [low, high)
* Generates a random integer between the specified range.
*
* @param low - The lower bound of the range (inclusive).
* @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`.
* @returns A random integer within the specified range.
*/
randInt(low: number, high?: number): number;
/**
* Draw a random element of the provided list N times to return an array of N random elements
* Drawing can be with or without replacement
* @param {array} list The array we want to draw randomly from
* @param {integer} count The number of times we want to draw
* @param {boolean} replacement Draw with or without replacement from the input array(default true)
* @return {array} Array consisting of N random elements
* Draws a specified number of random elements from a given list.
*
* @template T - The type of elements in the list.
* @param originalList - The list to draw elements from.
* @param count - The number of elements to draw. Defaults to 1.
* @param replacement - Whether to draw with replacement. Defaults to true.
* @returns An array containing the drawn elements.
*/
drawRandomFromList<T>(originalList: Array<T>, count?: number, replacement?: boolean): Array<T>;
/**
* Draw a random (top level) element of the provided dictionary N times to return an array of N random dictionary keys
* Drawing can be with or without replacement
* @param {any} dict The dictionary we want to draw randomly from
* @param {integer} count The number of times we want to draw
* @param {boolean} replacement Draw with ot without replacement from the input dict
* @return {array} Array consisting of N random keys of the dictionary
* Draws a specified number of random keys from a given dictionary.
*
* @param dict - The dictionary from which to draw keys.
* @param count - The number of keys to draw. Defaults to 1.
* @param replacement - Whether to draw with replacement. Defaults to true.
* @returns An array of randomly drawn keys from the dictionary.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
drawRandomFromDict(dict: any, count?: number, replacement?: boolean): any[];
/**
* Generates a biased random number within a specified range.
*
* @param min - The minimum value of the range (inclusive).
* @param max - The maximum value of the range (inclusive).
* @param shift - The bias shift to apply to the random number generation.
* @param n - The number of iterations to use for generating a Gaussian random number.
* @returns A biased random number within the specified range.
* @throws Will throw if `max` is less than `min` or if `n` is less than 1.
*/
getBiasedRandomNumber(min: number, max: number, shift: number, n: number): number;
/**
* Fisher-Yates shuffle an array
* @param array Array to shuffle
* @returns Shuffled array
* Shuffles an array in place using the Fisher-Yates algorithm.
*
* @template T - The type of elements in the array.
* @param array - The array to shuffle.
* @returns The shuffled array.
*/
shuffle<T>(array: Array<T>): Array<T>;
/**
* Rolls for a probability based on chance
* @param number Probability Chance as float (0-1)
* @returns If roll succeed or not
* @example
* rollForChanceProbability(0.25); // returns true 25% probability
* Rolls for a chance probability and returns whether the roll is successful.
*
* @param probabilityChance - The probability chance to roll for, represented as a number between 0 and 1.
* @returns `true` if the random number is less than or equal to the probability chance, otherwise `false`.
*/
rollForChanceProbability(probabilityChance: number): boolean;
}

View File

@ -118,6 +118,9 @@ export declare class ProfileController {
* Handle client/profile/status
*/
getProfileStatus(sessionId: string): IGetProfileStatusResponseData;
/**
* Handle client/profile/view
*/
getOtherProfile(sessionId: string, request: IGetOtherProfileRequest): IGetOtherProfileResponse;
/**
* Handle client/profile/settings

View File

@ -114,9 +114,10 @@ export declare class BotEquipmentModGenerator {
/**
* Sort mod slots into an ordering that maximises chance of a successful weapon generation
* @param unsortedSlotKeys Array of mod slot strings to sort
* @param itemTplWithKeysToSort The Tpl of the item with mod keys being sorted
* @returns Sorted array
*/
protected sortModKeys(unsortedSlotKeys: string[]): string[];
protected sortModKeys(unsortedSlotKeys: string[], itemTplWithKeysToSort: string): string[];
/**
* Get a Slot property for an item (chamber/cartridge/slot)
* @param modSlot e.g patron_in_weapon

View File

@ -12,6 +12,7 @@ import { IBarterScheme } from "@spt/models/eft/common/tables/ITrader";
import { IOfferRequirement, IRagfairOffer, IRagfairOfferUser } from "@spt/models/eft/ragfair/IRagfairOffer";
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
import { IArmorPlateBlacklistSettings, IBarterDetails, IDynamic, IRagfairConfig } from "@spt/models/spt/config/IRagfairConfig";
import { ITraderConfig } from "@spt/models/spt/config/ITraderConfig";
import { ITplWithFleaPrice } from "@spt/models/spt/ragfair/ITplWithFleaPrice";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
@ -47,6 +48,7 @@ export declare class RagfairOfferGenerator {
protected configServer: ConfigServer;
protected cloner: ICloner;
protected ragfairConfig: IRagfairConfig;
protected traderConfig: ITraderConfig;
protected botConfig: IBotConfig;
protected allowedFleaPriceItemsForBarter: {
tpl: string;
@ -83,7 +85,7 @@ export declare class RagfairOfferGenerator {
* @param isTrader Is the user creating the offer a trader
* @returns IRagfairOfferUser
*/
createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser;
protected createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser;
/**
* Calculate the offer price that's listed on the flea listing
* @param offerRequirements barter requirements for offer

View File

@ -209,4 +209,10 @@ export declare class ProfileHelper {
* @returns Array of item objects
*/
getQuestItemsInProfile(profile: IPmcData): IItem[];
/**
* Return a favorites array in the format expected by the getOtherProfile call
* @param profile
* @returns An array of IItem objects representing the favorited data
*/
getOtherProfileFavorites(profile: IPmcData): IItem[];
}

View File

@ -282,10 +282,10 @@ export declare class QuestHelper {
*/
protected findAndAddHideoutProductionIdToProfile(pmcData: IPmcData, craftUnlockReward: IQuestReward, questDetails: IQuest, sessionID: string, response: IItemEventRouterResponse): void;
/**
* Find hideout craft id for the specified quest reward
* @param craftUnlockReward
* @param questDetails
* @returns
* Find hideout craft for the specified quest reward
* @param craftUnlockReward Reward item from quest with craft unlock details
* @param questDetails Quest with craft unlock reward
* @returns Hideout craft
*/
getRewardProductionMatch(craftUnlockReward: IQuestReward, questDetails: IQuest): IHideoutProduction[];
/**
@ -332,16 +332,15 @@ export declare class QuestHelper {
/**
* Create a clone of the given quest array with the rewards updated to reflect the
* given game version
*
* @param quests The list of quests to check
* @param gameVersion The game version of the profile
* @returns array of IQuest objects with the rewards filtered correctly for the game version
* @param quests List of quests to check
* @param gameVersion Game version of the profile
* @returns Array of IQuest objects with the rewards filtered correctly for the game version
*/
protected updateQuestsForGameEdition(quests: IQuest[], gameVersion: string): IQuest[];
/**
* Return a list of quests that would fail when supplied quest is completed
* @param completedQuestId quest completed id
* @returns array of IQuest objects
* @param completedQuestId Quest completed id
* @returns Array of IQuest objects
*/
protected getQuestsFromProfileFailedByCompletingQuest(completedQuestId: string, pmcProfile: IPmcData): IQuest[];
/**

View File

@ -67,6 +67,13 @@ export declare class RagfairOfferHelper {
* @returns Offers the player should see
*/
getValidOffers(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record<string, ITraderAssort>, pmcData: IPmcData): IRagfairOffer[];
/**
* Disable offer if item is flagged by tiered flea config
* @param tieredFlea Tiered flea settings from ragfair config
* @param offer Ragfair offer to check
* @param tieredFleaLimitTypes Dict of item types with player level to be viewable
* @param playerLevel Level of player viewing offer
*/
protected checkAndLockOfferFromPlayerTieredFlea(tieredFlea: ITieredFlea, offer: IRagfairOffer, tieredFleaLimitTypes: string[], playerLevel: number): void;
/**
* Get matching offers that require the desired item and filter out offers from non traders if player is below ragfair unlock level
@ -99,14 +106,14 @@ export declare class RagfairOfferHelper {
*/
traderOfferItemQuestLocked(offer: IRagfairOffer, traderAssorts: Record<string, ITraderAssort>): boolean;
/**
* Has a traders offer ran out of stock to sell to player
* Has trader offer ran out of stock to sell to player
* @param offer Offer to check stock of
* @returns true if out of stock
*/
protected traderOutOfStock(offer: IRagfairOffer): boolean;
/**
* Check if trader offers' BuyRestrictionMax value has been reached
* @param offer offer to check restriction properties of
* @param offer Offer to check restriction properties of
* @returns true if restriction reached, false if no restrictions/not reached
*/
protected traderBuyRestrictionReached(offer: IRagfairOffer): boolean;
@ -114,7 +121,7 @@ export declare class RagfairOfferHelper {
* Get an array of flea offers that are inaccessible to player due to their inadequate loyalty level
* @param offers Offers to check
* @param pmcProfile Players profile with trader loyalty levels
* @returns array of offer ids player cannot see
* @returns Array of offer ids player cannot see
*/
protected getLoyaltyLockedOffers(offers: IRagfairOffer[], pmcProfile: IPmcData): string[];
/**
@ -126,7 +133,7 @@ export declare class RagfairOfferHelper {
/**
* Count up all rootitem StackObjectsCount properties of an array of items
* @param itemsInInventoryToList items to sum up
* @returns Total count
* @returns Total stack count
*/
getTotalStackCountSize(itemsInInventoryToList: IItem[][]): number;
/**
@ -164,16 +171,16 @@ export declare class RagfairOfferHelper {
protected getLocalisedOfferSoldMessage(itemTpl: string, boughtAmount: number): string;
/**
* Check an offer passes the various search criteria the player requested
* @param searchRequest
* @param offer
* @param pmcData
* @returns True
* @param searchRequest Client search request
* @param offer Offer to check
* @param pmcData Player profile
* @returns True if offer passes criteria
*/
protected passesSearchFilterCriteria(searchRequest: ISearchRequestData, offer: IRagfairOffer, pmcData: IPmcData): boolean;
/**
* Check that the passed in offer item is functional
* @param offerRootItem The root item of the offer
* @param offer The flea offer
* @param offer Flea offer to check
* @returns True if the given item is functional
*/
isItemFunctional(offerRootItem: IItem, offer: IRagfairOffer): boolean;
@ -181,7 +188,7 @@ export declare class RagfairOfferHelper {
* Should a ragfair offer be visible to the player
* @param searchRequest Search request
* @param itemsToAdd ?
* @param traderAssorts Trader assort items
* @param traderAssorts Trader assort items - used for filtering out locked trader items
* @param offer The flea offer
* @param pmcProfile Player profile
* @returns True = should be shown to player

View File

@ -44,10 +44,10 @@ export declare class TraderAssortHelper {
* Filter out assorts not unlocked due to level OR quest completion
* @param sessionId session id
* @param traderId traders id
* @param flea Should assorts player hasn't unlocked be returned - default false
* @param showLockedAssorts Should assorts player hasn't unlocked be returned - default false
* @returns a traders' assorts
*/
getAssort(sessionId: string, traderId: string, flea?: boolean): ITraderAssort;
getAssort(sessionId: string, traderId: string, showLockedAssorts?: boolean): ITraderAssort;
/**
* Given the blacklist provided, remove root items from assort
* @param assortToFilter Trader assort to modify
@ -75,20 +75,10 @@ export declare class TraderAssortHelper {
* @returns true they need refreshing
*/
traderAssortsHaveExpired(traderID: string): boolean;
/**
* Iterate over all assorts barter_scheme values, find barters selling for money and multiply by multipler in config
* @param traderAssort Assorts to multiple price of
*/
protected multiplyItemPricesByConfigMultiplier(traderAssort: ITraderAssort): void;
/**
* Get an array of pristine trader items prior to any alteration by player (as they were on server start)
* @param traderId trader id
* @returns array of Items
*/
protected getPristineTraderAssorts(traderId: string): IItem[];
/**
* Returns generated ragfair offers in a trader assort format
* @returns Trader assort object
*/
protected getRagfairDataAsTraderAssort(): ITraderAssort;
}

View File

@ -153,7 +153,7 @@ export interface IInventory {
/** Key is hideout area enum numeric as string e.g. "24", value is area _id */
hideoutAreaStashes: Record<string, string>;
fastPanel: Record<string, string>;
favoriteItems: IItem[];
favoriteItems: string[];
}
export interface IBaseJsonSkills {
Common: Record<string, Common>;

View File

@ -169,6 +169,13 @@ export interface ISpt {
freeRepeatableRefreshUsedCount?: Record<string, number>;
/** When was a profile migrated, value is timestamp */
migrations?: Record<string, number>;
/** Cultist circle rewards received that are one time use, key (md5) is a combination of sacrificed + reward items */
cultistRewards?: Map<string, IAcceptedCultistReward>;
}
export interface IAcceptedCultistReward {
timestamp: number;
sacrificeItems: string[];
rewardItems: string[];
}
export interface IModDetails {
name: string;

View File

@ -0,0 +1,4 @@
export declare enum CircleRewardType {
RANDOM = 0,
HIDEOUT_TASK = 1
}

View File

@ -18,11 +18,21 @@ export interface ICultistCircleSettings {
maxRewardItemCount: number;
maxAttemptsToPickRewardsWithinBudget: number;
rewardPriceMultiplerMinMax: MinMax;
/** The odds that meeting the highest threshold gives you a bonus to crafting time */
bonusAmountMultiplier: number;
bonusChanceMultiplier: number;
/** What is considered a "high-value" item */
highValueThresholdRub: number;
/** Hideout/task reward crafts have a unique craft time */
hideoutTaskRewardTimeSeconds: number;
/** Rouble amount player needs to sacrifice to get chance of hideout/task rewards */
hideoutCraftSacrificeThresholdRub: number;
craftTimeThreshholds: ICraftTimeThreshhold[];
/** -1 means no override */
/** -1 means no override, value in seconds */
craftTimeOverride: number;
/** Specific reward pool when player sacrificed one specific item */
directRewards: Record<string, IDirectRewardSettings>;
/** Specific reward pool when player sacrifice specific item(s) */
directRewards: IDirectRewardSettings[];
/** Overrides for reward stack sizes, keyed by item tpl */
directRewardStackSize: Record<string, MinMax>;
/** Item tpls to exclude from the reward pool */
rewardItemBlacklist: string[];
@ -34,6 +44,9 @@ export interface ICraftTimeThreshhold extends MinMax {
craftTimeSeconds: number;
}
export interface IDirectRewardSettings {
rewardTpls: string[];
reward: string[];
requiredItems: string[];
craftTimeSeconds: number;
/** Is the reward a one time reward or can it be given multiple times */
repeatable: boolean;
}

View File

@ -4,10 +4,10 @@ import { ILootRequest } from "@spt/models/spt/services/ILootRequest";
export interface ITraderConfig extends IBaseConfig {
kind: "spt-trader";
updateTime: IUpdateTime[];
updateTimeDefault: number;
purchasesAreFoundInRaid: boolean;
/** Should trader reset times be set based on server start time (false = bsg time - on the hour) */
tradersResetFromServerStart: boolean;
updateTimeDefault: number;
traderPriceMultipler: number;
fence: IFenceConfig;
moddedTraders: IModdedTraders;

View File

@ -0,0 +1,8 @@
import { CircleRewardType } from "@spt/models/enums/hideout/CircleRewardType";
import { ICraftTimeThreshhold } from "@spt/models/spt/config/IHideoutConfig";
export interface ICircleCraftDetails {
time: number;
rewardType: CircleRewardType;
rewardAmountRoubles: number;
rewardDetails?: ICraftTimeThreshhold;
}

View File

@ -3,14 +3,17 @@ import { InventoryHelper } from "@spt/helpers/InventoryHelper";
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { PresetHelper } from "@spt/helpers/PresetHelper";
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
import { QuestHelper } from "@spt/helpers/QuestHelper";
import { IPmcData } from "@spt/models/eft/common/IPmcData";
import { IBotHideoutArea } from "@spt/models/eft/common/tables/IBotBase";
import { IItem } from "@spt/models/eft/common/tables/IItem";
import { IStageRequirement } from "@spt/models/eft/hideout/IHideoutArea";
import { IHideoutCircleOfCultistProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutCircleOfCultistProductionStartRequestData";
import { IHideoutProduction, IHideoutProductionData, IRequirement, IRequirementBase } from "@spt/models/eft/hideout/IHideoutProduction";
import { IRequirement, IRequirementBase } from "@spt/models/eft/hideout/IHideoutProduction";
import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse";
import { IDirectRewardSettings, IHideoutConfig } from "@spt/models/spt/config/IHideoutConfig";
import { ICraftTimeThreshhold, ICultistCircleSettings, IDirectRewardSettings, IHideoutConfig } from "@spt/models/spt/config/IHideoutConfig";
import { ICircleCraftDetails } from "@spt/models/spt/hideout/ICircleCraftDetails";
import { IHideout } from "@spt/models/spt/hideout/IHideout";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { EventOutputHolder } from "@spt/routers/EventOutputHolder";
import { ConfigServer } from "@spt/servers/ConfigServer";
@ -33,13 +36,14 @@ export declare class CircleOfCultistService {
protected profileHelper: ProfileHelper;
protected inventoryHelper: InventoryHelper;
protected hideoutHelper: HideoutHelper;
protected questHelper: QuestHelper;
protected databaseService: DatabaseService;
protected itemFilterService: ItemFilterService;
protected seasonalEventService: SeasonalEventService;
protected configServer: ConfigServer;
protected static circleOfCultistSlotId: string;
protected hideoutConfig: IHideoutConfig;
constructor(logger: ILogger, timeUtil: TimeUtil, cloner: ICloner, eventOutputHolder: EventOutputHolder, randomUtil: RandomUtil, hashUtil: HashUtil, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, inventoryHelper: InventoryHelper, hideoutHelper: HideoutHelper, databaseService: DatabaseService, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer);
constructor(logger: ILogger, timeUtil: TimeUtil, cloner: ICloner, eventOutputHolder: EventOutputHolder, randomUtil: RandomUtil, hashUtil: HashUtil, itemHelper: ItemHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, inventoryHelper: InventoryHelper, hideoutHelper: HideoutHelper, questHelper: QuestHelper, databaseService: DatabaseService, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer);
/**
* Start a sacrifice event
* Generate rewards
@ -50,24 +54,38 @@ export declare class CircleOfCultistService {
* @returns IItemEventRouterResponse
*/
startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse;
/**
* Create a map of the possible direct rewards, keyed by the items needed to be sacrificed
* @param directRewards Direct rewards array from hideout config
* @returns Map
*/
protected generateSacrificedItemsCache(directRewards: IDirectRewardSettings[]): Map<string, IDirectRewardSettings>;
/**
* Get the reward amount multiple value based on players hideout management skill + configs rewardPriceMultiplerMinMax values
* @param pmcData Player profile
* @param cultistCircleSettings Circle config settings
* @returns Reward Amount Multipler
*/
protected getRewardAmountMultipler(pmcData: IPmcData, cultistCircleSettings: ICultistCircleSettings): number;
/**
* Register production inside player profile
* @param sessionId Session id
* @param pmcData Player profile
* @param recipeId Recipe id
* @param sacrificedItems Items player sacrificed
* @param rewardAmountRoubles Rouble amount to reward player in items with
* @param directRewardSettings OPTIONAL: If craft is giving direct rewards
* @param craftingTime How long the ritual should take
*/
protected registerCircleOfCultistProduction(sessionId: string, pmcData: IPmcData, recipeId: string, sacrificedItems: IItem[], rewardAmountRoubles: number, directRewardSettings?: IDirectRewardSettings): void;
protected registerCircleOfCultistProduction(sessionId: string, pmcData: IPmcData, recipeId: string, sacrificedItems: IItem[], craftingTime: number): void;
/**
* Get the circle craft time as seconds, value is based on reward item value
* OR rewards are direct, then use custom craft time defined in oarameter object
* And get the bonus status to determine what tier of reward is given
* @param rewardAmountRoubles Value of rewards in roubles
* @param directRewardSettings OPTIONAL: If craft is giving direct rewards
* @returns craft time seconds
* @param circleConfig Circle config values
* @param directRewardSettings OPTIONAL - Values related to direct reward being given
* @returns craft time + type of reward + reward details
*/
protected getCircleCraftTimeSeconds(rewardAmountRoubles: number, directRewardSettings?: IDirectRewardSettings): number;
protected getCircleCraftingInfo(rewardAmountRoubles: number, circleConfig: ICultistCircleSettings, directRewardSettings?: IDirectRewardSettings): ICircleCraftDetails;
protected getMatchingThreshold(thresholds: ICraftTimeThreshhold[], rewardAmountRoubles: number): ICraftTimeThreshhold;
/**
* Get the items player sacrificed in circle
* @param pmcData Player profile
@ -81,20 +99,40 @@ export declare class CircleOfCultistService {
* @param cultistCircleStashId Id of stash item
* @returns Array of item arrays
*/
protected getRewardsWithinBudget(rewardItemTplPool: string[], rewardBudget: number, cultistCircleStashId: string): IItem[][];
protected getRewardsWithinBudget(rewardItemTplPool: string[], rewardBudget: number, cultistCircleStashId: string, circleConfig: ICultistCircleSettings): IItem[][];
/**
* Give every item as a reward that's passed in
* @param rewardTpls Item tpls to turn into reward items
* Get direct rewards
* @param sessionId sessionId
* @param directReward Items sacrificed
* @param cultistCircleStashId Id of stash item
* @returns Array of item arrays
* @returns The reward object
*/
protected getExplicitRewards(explicitRewardSettings: IDirectRewardSettings, cultistCircleStashId: string): IItem[][];
protected getDirectRewards(sessionId: string, directReward: IDirectRewardSettings, cultistCircleStashId: string): IItem[][];
/**
* Check for direct rewards from what player sacrificed
* @param sessionId sessionId
* @param sacrificedItems Items sacrificed
* @returns Direct reward items to send to player
*/
protected checkForDirectReward(sessionId: string, sacrificedItems: IItem[], directRewardsCache: Map<string, IDirectRewardSettings>): IDirectRewardSettings;
/**
* Create an md5 key of the sacrificed + reward items
* @param directReward Direct reward to create key for
* @returns Key
*/
protected getDirectRewardHashKey(directReward: IDirectRewardSettings): string;
/**
* Explicit rewards have thier own stack sizes as they dont use a reward rouble pool
* @param rewardTpl Item being rewarded to get stack size of
* @returns stack size of item
*/
protected getExplicitRewardBaseTypeStackSize(rewardTpl: string): number;
protected getDirectRewardBaseTypeStackSize(rewardTpl: string): number;
/**
* Add a record to the players profile to signal they have accepted a non-repeatable direct reward
* @param sessionId Session id
* @param directReward Reward sent to player
*/
protected flagDirectRewardAsAcceptedInProfile(sessionId: string, directReward: IDirectRewardSettings): void;
/**
* Get the size of a reward items stack
* 1 for everything except ammo, ammo can be between min stack and max stack
@ -107,9 +145,26 @@ export declare class CircleOfCultistService {
* Get a pool of tpl IDs of items the player needs to complete hideout crafts/upgrade areas
* @param sessionId Session id
* @param pmcData Profile of player who will be getting the rewards
* @param rewardType Do we return bonus items (hideout/task items)
* @param cultistCircleConfig Circle config
* @returns Array of tpls
*/
protected getCultistCircleRewardPool(sessionId: string, pmcData: IPmcData): string[];
protected getCultistCircleRewardPool(sessionId: string, pmcData: IPmcData, craftingInfo: ICircleCraftDetails, cultistCircleConfig: ICultistCircleSettings): string[];
/**
* Check players profile for quests with hand-in requirements and add those required items to the pool
* @param pmcData Player profile
* @param itemRewardBlacklist Items not to add to pool
* @param rewardPool Pool to add items to
*/
protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set<string>): void;
/**
* Adds items the player needs to complete hideout crafts/upgrades to the reward pool
* @param hideoutDbData Hideout area data
* @param pmcData Player profile
* @param itemRewardBlacklist Items not to add to pool
* @param rewardPool Pool to add items to
*/
protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set<string>): void;
/**
* Get all active hideout areas
* @param areas Hideout areas to iterate over
@ -117,12 +172,13 @@ export declare class CircleOfCultistService {
*/
protected getPlayerAccessibleHideoutAreas(areas: IBotHideoutArea[]): IBotHideoutArea[];
/**
* Get all recipes the player has access to, includes base + unlocked recipes
* @param unlockedRecipes Recipes player has flagged as unlocked
* @param allRecipes All recipes
* @returns Array of recipes
* Get array of random reward items
* @param rewardPool Reward pool to add to
* @param itemRewardBlacklist Reward Blacklist
* @param itemsShouldBeHighValue Should these items meet the valuable threshold
* @returns rewardPool
*/
protected getPlayerAccessibleRecipes(unlockedRecipes: string[], allRecipes: IHideoutProductionData): IHideoutProduction[];
protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set<string>, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set<string>;
/**
* Iterate over passed in hideout requirements and return the Item
* @param requirements Requirements to iterate over

View File

@ -87,6 +87,12 @@ export declare class ProfileFixerService {
* @returns
*/
protected verifyQuestProductionUnlock(pmcProfile: IPmcData, productionUnlockReward: IQuestReward, questDetails: IQuest): void;
/**
* Initial release of SPT 3.10 used an incorrect favorites structure, reformat
* the structure to the correct MongoID array structure
* @param pmcProfile
*/
protected fixFavorites(pmcProfile: IPmcData): void;
/**
* If the profile has elite Hideout Managment skill, add the additional slots from globals
* NOTE: This seems redundant, but we will leave it here just incase.

View File

@ -138,6 +138,12 @@ export declare class SeasonalEventService {
*/
protected enableHalloweenSummonEvent(): void;
protected configureZombies(zombieSettings: IZombieSettings): void;
/**
* Get location ids of maps with an infection above 0
* @param locationInfections Dict of locations with their infection percentage
* @returns Array of location ids
*/
protected getLocationsWithZombies(locationInfections: Record<string, number>): string[];
/**
* BSG store the location ids differently inside `LocationInfection`, need to convert to matching location IDs
* @param infectedLocationKey Key to convert

View File

@ -1,38 +0,0 @@
import { ILogger } from "@spt/models/spt/utils/ILogger";
export declare class DatabaseDecompressionUtil {
protected logger: ILogger;
private compressedDir;
private assetsDir;
private compiled;
constructor(logger: ILogger);
/**
* Checks if the application is running in a compiled environment. A simple check is done to see if the relative
* assets directory exists. If it does not, the application is assumed to be running in a compiled environment. All
* relative asset paths are different within a compiled environment, so this simple check is sufficient.
*/
private isCompiled;
/**
* Initializes the database compression utility.
*
* This method will decompress all 7-zip archives within the compressed database directory. The decompressed files
* are placed in their respective directories based on the name and location of the compressed file.
*/
initialize(): Promise<void>;
/**
* Retrieves a list of all 7-zip archives within the compressed database directory.
*/
private getCompressedFiles;
/**
* Processes a compressed file by checking if the target directory is empty, and if so, decompressing the file into
* the target directory.
*/
private processCompressedFile;
/**
* Checks if a directory exists and is empty.
*/
private isDirectoryEmpty;
/**
* Decompresses a 7-zip archive to the target directory.
*/
private decompressFile;
}

View File

@ -106,77 +106,177 @@ export declare class RandomUtil {
protected cloner: ICloner;
protected logger: ILogger;
constructor(cloner: ICloner, logger: ILogger);
/**
* Generates a secure random number between 0 (inclusive) and 1 (exclusive).
*
* This method uses the `crypto` module to generate a 48-bit random integer,
* which is then divided by the maximum possible 48-bit integer value to
* produce a floating-point number in the range [0, 1).
*
* @returns A secure random number between 0 (inclusive) and 1 (exclusive).
*/
private getSecureRandomNumber;
/**
* Generates a random integer between the specified minimum and maximum values, inclusive.
*
* @param min - The minimum value (inclusive).
* @param max - The maximum value (inclusive).
* @returns A random integer between the specified minimum and maximum values.
*/
getInt(min: number, max: number): number;
/**
* Generates a random integer between 1 (inclusive) and the specified maximum value (exclusive).
* If the maximum value is less than or equal to 1, it returns 1.
*
* @param max - The upper bound (exclusive) for the random integer generation.
* @returns A random integer between 1 and max - 1, or 1 if max is less than or equal to 1.
*/
getIntEx(max: number): number;
/**
* Generates a random floating-point number within the specified range.
*
* @param min - The minimum value of the range (inclusive).
* @param max - The maximum value of the range (exclusive).
* @returns A random floating-point number between `min` (inclusive) and `max` (exclusive).
*/
getFloat(min: number, max: number): number;
/**
* Generates a random boolean value.
*
* @returns A random boolean value, where the probability of `true` and `false` is approximately equal.
*/
getBool(): boolean;
/**
* Calculates the percentage of a given number and returns the result.
*
* @param percent - The percentage to calculate.
* @param number - The number to calculate the percentage of.
* @param toFixed - The number of decimal places to round the result to (default is 2).
* @returns The calculated percentage of the given number, rounded to the specified number of decimal places.
*/
getPercentOfValue(percent: number, number: number, toFixed?: number): number;
/**
* Reduce a value by a percentage
* @param number Value to reduce
* @param percentage Percentage to reduce value by
* @returns Reduced value
* Reduces a given number by a specified percentage.
*
* @param number - The original number to be reduced.
* @param percentage - The percentage by which to reduce the number.
* @returns The reduced number after applying the percentage reduction.
*/
reduceValueByPercent(number: number, percentage: number): number;
/**
* Check if number passes a check out of 100
* @param chancePercent value check needs to be above
* @returns true if value passes check
* Determines if a random event occurs based on the given chance percentage.
*
* @param chancePercent - The percentage chance (0-100) that the event will occur.
* @returns `true` if the event occurs, `false` otherwise.
*/
getChance100(chancePercent: number): boolean;
/**
* Returns a random string from the provided array of strings.
*
* This method is separate from getArrayValue so we can use a generic inferance with getArrayValue.
*
* @param arr - The array of strings to select a random value from.
* @returns A randomly selected string from the array.
*/
getStringArrayValue(arr: string[]): string;
/**
* Returns a random element from the provided array.
*
* @template T - The type of elements in the array.
* @param arr - The array from which to select a random element.
* @returns A random element from the array.
*/
getArrayValue<T>(arr: T[]): T;
/**
* Retrieves a random key from the given object.
*
* @param node - The object from which to retrieve a key.
* @returns A string representing one of the keys of the node object.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
getKey(node: any): string;
/**
* Retrieves the value associated with a key from the given node object.
*
* @param node - An object with string keys and any type of values.
* @returns The value associated with the key obtained from the node.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
getKeyValue(node: {
[x: string]: any;
}): any;
/**
* Generate a normally distributed random number
* Uses the Box-Muller transform
* @param {number} mean Mean of the normal distribution
* @param {number} sigma Standard deviation of the normal distribution
* @returns {number} The value drawn
* Generates a normally distributed random number using the Box-Muller transform.
*
* @param mean - The mean (μ) of the normal distribution.
* @param sigma - The standard deviation (σ) of the normal distribution.
* @param attempt - The current attempt count to generate a valid number (default is 0).
* @returns A normally distributed random number.
*
* @remarks
* This function uses the Box-Muller transform to generate a normally distributed random number.
* If the generated number is less than 0, it will recursively attempt to generate a valid number up to 100 times.
* If it fails to generate a valid number after 100 attempts, it will return a random float between 0.01 and twice the mean.
*/
getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number;
/**
* Draw Random integer low inclusive, high exclusive
* if high is not set we draw from 0 to low (exclusive)
* @param {integer} low Lower bound inclusive, when high is not set, this is high
* @param {integer} high Higher bound exclusive
* @returns {integer} The random integer in [low, high)
* Generates a random integer between the specified range.
*
* @param low - The lower bound of the range (inclusive).
* @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`.
* @returns A random integer within the specified range.
*/
randInt(low: number, high?: number): number;
/**
* Draw a random element of the provided list N times to return an array of N random elements
* Drawing can be with or without replacement
* @param {array} list The array we want to draw randomly from
* @param {integer} count The number of times we want to draw
* @param {boolean} replacement Draw with or without replacement from the input array(default true)
* @return {array} Array consisting of N random elements
* Draws a specified number of random elements from a given list.
*
* @template T - The type of elements in the list.
* @param originalList - The list to draw elements from.
* @param count - The number of elements to draw. Defaults to 1.
* @param replacement - Whether to draw with replacement. Defaults to true.
* @returns An array containing the drawn elements.
*/
drawRandomFromList<T>(originalList: Array<T>, count?: number, replacement?: boolean): Array<T>;
/**
* Draw a random (top level) element of the provided dictionary N times to return an array of N random dictionary keys
* Drawing can be with or without replacement
* @param {any} dict The dictionary we want to draw randomly from
* @param {integer} count The number of times we want to draw
* @param {boolean} replacement Draw with ot without replacement from the input dict
* @return {array} Array consisting of N random keys of the dictionary
* Draws a specified number of random keys from a given dictionary.
*
* @param dict - The dictionary from which to draw keys.
* @param count - The number of keys to draw. Defaults to 1.
* @param replacement - Whether to draw with replacement. Defaults to true.
* @returns An array of randomly drawn keys from the dictionary.
*
* TODO: v3.11 - This method is not type-safe and should be refactored to use a more specific type:
* https://github.com/sp-tarkov/server/pull/972/commits/f2b8efe211d95f71aec0a4bc84f4542335433412
*/
drawRandomFromDict(dict: any, count?: number, replacement?: boolean): any[];
/**
* Generates a biased random number within a specified range.
*
* @param min - The minimum value of the range (inclusive).
* @param max - The maximum value of the range (inclusive).
* @param shift - The bias shift to apply to the random number generation.
* @param n - The number of iterations to use for generating a Gaussian random number.
* @returns A biased random number within the specified range.
* @throws Will throw if `max` is less than `min` or if `n` is less than 1.
*/
getBiasedRandomNumber(min: number, max: number, shift: number, n: number): number;
/**
* Fisher-Yates shuffle an array
* @param array Array to shuffle
* @returns Shuffled array
* Shuffles an array in place using the Fisher-Yates algorithm.
*
* @template T - The type of elements in the array.
* @param array - The array to shuffle.
* @returns The shuffled array.
*/
shuffle<T>(array: Array<T>): Array<T>;
/**
* Rolls for a probability based on chance
* @param number Probability Chance as float (0-1)
* @returns If roll succeed or not
* @example
* rollForChanceProbability(0.25); // returns true 25% probability
* Rolls for a chance probability and returns whether the roll is successful.
*
* @param probabilityChance - The probability chance to roll for, represented as a number between 0 and 1.
* @returns `true` if the random number is less than or equal to the probability chance, otherwise `false`.
*/
rollForChanceProbability(probabilityChance: number): boolean;
}

View File

@ -118,6 +118,9 @@ export declare class ProfileController {
* Handle client/profile/status
*/
getProfileStatus(sessionId: string): IGetProfileStatusResponseData;
/**
* Handle client/profile/view
*/
getOtherProfile(sessionId: string, request: IGetOtherProfileRequest): IGetOtherProfileResponse;
/**
* Handle client/profile/settings

View File

@ -114,9 +114,10 @@ export declare class BotEquipmentModGenerator {
/**
* Sort mod slots into an ordering that maximises chance of a successful weapon generation
* @param unsortedSlotKeys Array of mod slot strings to sort
* @param itemTplWithKeysToSort The Tpl of the item with mod keys being sorted
* @returns Sorted array
*/
protected sortModKeys(unsortedSlotKeys: string[]): string[];
protected sortModKeys(unsortedSlotKeys: string[], itemTplWithKeysToSort: string): string[];
/**
* Get a Slot property for an item (chamber/cartridge/slot)
* @param modSlot e.g patron_in_weapon

View File

@ -12,6 +12,7 @@ import { IBarterScheme } from "@spt/models/eft/common/tables/ITrader";
import { IOfferRequirement, IRagfairOffer, IRagfairOfferUser } from "@spt/models/eft/ragfair/IRagfairOffer";
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
import { IArmorPlateBlacklistSettings, IBarterDetails, IDynamic, IRagfairConfig } from "@spt/models/spt/config/IRagfairConfig";
import { ITraderConfig } from "@spt/models/spt/config/ITraderConfig";
import { ITplWithFleaPrice } from "@spt/models/spt/ragfair/ITplWithFleaPrice";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
@ -47,6 +48,7 @@ export declare class RagfairOfferGenerator {
protected configServer: ConfigServer;
protected cloner: ICloner;
protected ragfairConfig: IRagfairConfig;
protected traderConfig: ITraderConfig;
protected botConfig: IBotConfig;
protected allowedFleaPriceItemsForBarter: {
tpl: string;
@ -83,7 +85,7 @@ export declare class RagfairOfferGenerator {
* @param isTrader Is the user creating the offer a trader
* @returns IRagfairOfferUser
*/
createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser;
protected createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser;
/**
* Calculate the offer price that's listed on the flea listing
* @param offerRequirements barter requirements for offer

View File

@ -209,4 +209,10 @@ export declare class ProfileHelper {
* @returns Array of item objects
*/
getQuestItemsInProfile(profile: IPmcData): IItem[];
/**
* Return a favorites array in the format expected by the getOtherProfile call
* @param profile
* @returns An array of IItem objects representing the favorited data
*/
getOtherProfileFavorites(profile: IPmcData): IItem[];
}

View File

@ -282,10 +282,10 @@ export declare class QuestHelper {
*/
protected findAndAddHideoutProductionIdToProfile(pmcData: IPmcData, craftUnlockReward: IQuestReward, questDetails: IQuest, sessionID: string, response: IItemEventRouterResponse): void;
/**
* Find hideout craft id for the specified quest reward
* @param craftUnlockReward
* @param questDetails
* @returns
* Find hideout craft for the specified quest reward
* @param craftUnlockReward Reward item from quest with craft unlock details
* @param questDetails Quest with craft unlock reward
* @returns Hideout craft
*/
getRewardProductionMatch(craftUnlockReward: IQuestReward, questDetails: IQuest): IHideoutProduction[];
/**
@ -332,16 +332,15 @@ export declare class QuestHelper {
/**
* Create a clone of the given quest array with the rewards updated to reflect the
* given game version
*
* @param quests The list of quests to check
* @param gameVersion The game version of the profile
* @returns array of IQuest objects with the rewards filtered correctly for the game version
* @param quests List of quests to check
* @param gameVersion Game version of the profile
* @returns Array of IQuest objects with the rewards filtered correctly for the game version
*/
protected updateQuestsForGameEdition(quests: IQuest[], gameVersion: string): IQuest[];
/**
* Return a list of quests that would fail when supplied quest is completed
* @param completedQuestId quest completed id
* @returns array of IQuest objects
* @param completedQuestId Quest completed id
* @returns Array of IQuest objects
*/
protected getQuestsFromProfileFailedByCompletingQuest(completedQuestId: string, pmcProfile: IPmcData): IQuest[];
/**

View File

@ -67,6 +67,13 @@ export declare class RagfairOfferHelper {
* @returns Offers the player should see
*/
getValidOffers(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record<string, ITraderAssort>, pmcData: IPmcData): IRagfairOffer[];
/**
* Disable offer if item is flagged by tiered flea config
* @param tieredFlea Tiered flea settings from ragfair config
* @param offer Ragfair offer to check
* @param tieredFleaLimitTypes Dict of item types with player level to be viewable
* @param playerLevel Level of player viewing offer
*/
protected checkAndLockOfferFromPlayerTieredFlea(tieredFlea: ITieredFlea, offer: IRagfairOffer, tieredFleaLimitTypes: string[], playerLevel: number): void;
/**
* Get matching offers that require the desired item and filter out offers from non traders if player is below ragfair unlock level
@ -99,14 +106,14 @@ export declare class RagfairOfferHelper {
*/
traderOfferItemQuestLocked(offer: IRagfairOffer, traderAssorts: Record<string, ITraderAssort>): boolean;
/**
* Has a traders offer ran out of stock to sell to player
* Has trader offer ran out of stock to sell to player
* @param offer Offer to check stock of
* @returns true if out of stock
*/
protected traderOutOfStock(offer: IRagfairOffer): boolean;
/**
* Check if trader offers' BuyRestrictionMax value has been reached
* @param offer offer to check restriction properties of
* @param offer Offer to check restriction properties of
* @returns true if restriction reached, false if no restrictions/not reached
*/
protected traderBuyRestrictionReached(offer: IRagfairOffer): boolean;
@ -114,7 +121,7 @@ export declare class RagfairOfferHelper {
* Get an array of flea offers that are inaccessible to player due to their inadequate loyalty level
* @param offers Offers to check
* @param pmcProfile Players profile with trader loyalty levels
* @returns array of offer ids player cannot see
* @returns Array of offer ids player cannot see
*/
protected getLoyaltyLockedOffers(offers: IRagfairOffer[], pmcProfile: IPmcData): string[];
/**
@ -126,7 +133,7 @@ export declare class RagfairOfferHelper {
/**
* Count up all rootitem StackObjectsCount properties of an array of items
* @param itemsInInventoryToList items to sum up
* @returns Total count
* @returns Total stack count
*/
getTotalStackCountSize(itemsInInventoryToList: IItem[][]): number;
/**
@ -164,16 +171,16 @@ export declare class RagfairOfferHelper {
protected getLocalisedOfferSoldMessage(itemTpl: string, boughtAmount: number): string;
/**
* Check an offer passes the various search criteria the player requested
* @param searchRequest
* @param offer
* @param pmcData
* @returns True
* @param searchRequest Client search request
* @param offer Offer to check
* @param pmcData Player profile
* @returns True if offer passes criteria
*/
protected passesSearchFilterCriteria(searchRequest: ISearchRequestData, offer: IRagfairOffer, pmcData: IPmcData): boolean;
/**
* Check that the passed in offer item is functional
* @param offerRootItem The root item of the offer
* @param offer The flea offer
* @param offer Flea offer to check
* @returns True if the given item is functional
*/
isItemFunctional(offerRootItem: IItem, offer: IRagfairOffer): boolean;
@ -181,7 +188,7 @@ export declare class RagfairOfferHelper {
* Should a ragfair offer be visible to the player
* @param searchRequest Search request
* @param itemsToAdd ?
* @param traderAssorts Trader assort items
* @param traderAssorts Trader assort items - used for filtering out locked trader items
* @param offer The flea offer
* @param pmcProfile Player profile
* @returns True = should be shown to player

View File

@ -44,10 +44,10 @@ export declare class TraderAssortHelper {
* Filter out assorts not unlocked due to level OR quest completion
* @param sessionId session id
* @param traderId traders id
* @param flea Should assorts player hasn't unlocked be returned - default false
* @param showLockedAssorts Should assorts player hasn't unlocked be returned - default false
* @returns a traders' assorts
*/
getAssort(sessionId: string, traderId: string, flea?: boolean): ITraderAssort;
getAssort(sessionId: string, traderId: string, showLockedAssorts?: boolean): ITraderAssort;
/**
* Given the blacklist provided, remove root items from assort
* @param assortToFilter Trader assort to modify
@ -75,20 +75,10 @@ export declare class TraderAssortHelper {
* @returns true they need refreshing
*/
traderAssortsHaveExpired(traderID: string): boolean;
/**
* Iterate over all assorts barter_scheme values, find barters selling for money and multiply by multipler in config
* @param traderAssort Assorts to multiple price of
*/
protected multiplyItemPricesByConfigMultiplier(traderAssort: ITraderAssort): void;
/**
* Get an array of pristine trader items prior to any alteration by player (as they were on server start)
* @param traderId trader id
* @returns array of Items
*/
protected getPristineTraderAssorts(traderId: string): IItem[];
/**
* Returns generated ragfair offers in a trader assort format
* @returns Trader assort object
*/
protected getRagfairDataAsTraderAssort(): ITraderAssort;
}

View File

@ -153,7 +153,7 @@ export interface IInventory {
/** Key is hideout area enum numeric as string e.g. "24", value is area _id */
hideoutAreaStashes: Record<string, string>;
fastPanel: Record<string, string>;
favoriteItems: IItem[];
favoriteItems: string[];
}
export interface IBaseJsonSkills {
Common: Record<string, Common>;

View File

@ -169,6 +169,13 @@ export interface ISpt {
freeRepeatableRefreshUsedCount?: Record<string, number>;
/** When was a profile migrated, value is timestamp */
migrations?: Record<string, number>;
/** Cultist circle rewards received that are one time use, key (md5) is a combination of sacrificed + reward items */
cultistRewards?: Map<string, IAcceptedCultistReward>;
}
export interface IAcceptedCultistReward {
timestamp: number;
sacrificeItems: string[];
rewardItems: string[];
}
export interface IModDetails {
name: string;

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