374 #20

Merged
chomp merged 2 commits from 374 into master 2023-12-04 14:36:22 -05:00
673 changed files with 5393 additions and 1072 deletions

View File

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

View File

@ -8,6 +8,7 @@ import { IGameEmptyCrcRequestData } from "@spt-aki/models/eft/game/IGameEmptyCrc
import { IGameKeepAliveResponse } from "@spt-aki/models/eft/game/IGameKeepAliveResponse";
import { IGameLogoutResponseData } from "@spt-aki/models/eft/game/IGameLogoutResponseData";
import { IGameStartResponse } from "@spt-aki/models/eft/game/IGameStartResponse";
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
import { IReportNicknameRequestData } from "@spt-aki/models/eft/game/IReportNicknameRequestData";
import { IServerDetails } from "@spt-aki/models/eft/game/IServerDetails";
import { IVersionValidateRequestData } from "@spt-aki/models/eft/game/IVersionValidateRequestData";
@ -68,5 +69,10 @@ declare class GameCallbacks implements OnLoad {
*/
getVersion(url: string, info: IEmptyRequestData, sessionID: string): string;
reportNickname(url: string, info: IReportNicknameRequestData, sessionID: string): INullResponseData;
/**
* Handle singleplayer/settings/getRaidTime
* @returns string
*/
getRaidTime(url: string, request: IGetRaidTimeRequest, sessionID: string): any;
}
export { GameCallbacks };

View File

@ -10,11 +10,12 @@ export declare class ApplicationContext {
*
* const activePlayerSessionId = this.applicationContext.getLatestValue(ContextVariableType.SESSION_ID).getValue<string>();
*
* const matchInfo = this.applicationContext.getLatestValue(ContextVariableType.MATCH_INFO).getValue<IStartOfflineRaidRequestData>();
* const matchInfo = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION).getValue<IGetRaidConfigurationRequestData>();
* @param type
* @returns
*/
getLatestValue(type: ContextVariableType): ContextVariable;
getValues(type: ContextVariableType): ContextVariable[];
addValue(type: ContextVariableType, value: any): void;
clearValues(type: ContextVariableType): void;
}

View File

@ -6,5 +6,6 @@ export declare enum ContextVariableType {
/** Timestamp when client first connected */
CLIENT_START_TIMESTAMP = 2,
/** When player is loading into map and loot is requested */
REGISTER_PLAYER_REQUEST = 3
REGISTER_PLAYER_REQUEST = 3,
RAID_ADJUSTMENTS = 4
}

View File

@ -9,6 +9,8 @@ import { ICheckVersionResponse } from "@spt-aki/models/eft/game/ICheckVersionRes
import { ICurrentGroupResponse } from "@spt-aki/models/eft/game/ICurrentGroupResponse";
import { IGameConfigResponse } from "@spt-aki/models/eft/game/IGameConfigResponse";
import { IGameKeepAliveResponse } from "@spt-aki/models/eft/game/IGameKeepAliveResponse";
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
import { IGetRaidTimeResponse } from "@spt-aki/models/eft/game/IGetRaidTimeResponse";
import { IServerDetails } from "@spt-aki/models/eft/game/IServerDetails";
import { IAkiProfile } from "@spt-aki/models/eft/profile/IAkiProfile";
import { ICoreConfig } from "@spt-aki/models/spt/config/ICoreConfig";
@ -26,7 +28,9 @@ import { ItemBaseClassService } from "@spt-aki/services/ItemBaseClassService";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { OpenZoneService } from "@spt-aki/services/OpenZoneService";
import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService";
import { RaidTimeAdjustmentService } from "@spt-aki/services/RaidTimeAdjustmentService";
import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
import { HashUtil } from "@spt-aki/utils/HashUtil";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
@ -35,6 +39,7 @@ export declare class GameController {
protected databaseServer: DatabaseServer;
protected jsonUtil: JsonUtil;
protected timeUtil: TimeUtil;
protected hashUtil: HashUtil;
protected preAkiModLoader: PreAkiModLoader;
protected httpServerHelper: HttpServerHelper;
protected randomUtil: RandomUtil;
@ -47,6 +52,7 @@ export declare class GameController {
protected seasonalEventService: SeasonalEventService;
protected itemBaseClassService: ItemBaseClassService;
protected giftService: GiftService;
protected raidTimeAdjustmentService: RaidTimeAdjustmentService;
protected applicationContext: ApplicationContext;
protected configServer: ConfigServer;
protected httpConfig: IHttpConfig;
@ -55,7 +61,7 @@ export declare class GameController {
protected ragfairConfig: IRagfairConfig;
protected pmcConfig: IPmcConfig;
protected lootConfig: ILootConfig;
constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer);
constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, raidTimeAdjustmentService: RaidTimeAdjustmentService, applicationContext: ApplicationContext, configServer: ConfigServer);
load(): void;
/**
* Handle client/game/start
@ -90,6 +96,10 @@ export declare class GameController {
* Handle client/game/keepalive
*/
getKeepAlive(sessionId: string): IGameKeepAliveResponse;
/**
* Handle singleplayer/settings/getRaidTime
*/
getRaidTime(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse;
/**
* BSG have two values for shotgun dispersion, we make sure both have the same value
*/

View File

@ -101,7 +101,7 @@ export declare class HideoutController {
*/
protected addUpdateInventoryItemToProfile(pmcData: IPmcData, dbHideoutData: IHideoutArea, hideoutStage: Stage): void;
/**
* @param output Objet to send to client
* @param output Object to send to client
* @param sessionID Session/player id
* @param areaType Hideout area that had stash added
* @param hideoutDbData Hideout area that caused addition of stash

View File

@ -95,9 +95,14 @@ export declare class InraidController {
/**
* Does provided profile contain any condition counters
* @param profile Profile to check for condition counters
* @returns
* @returns Profile has condition counters
*/
protected profileHasConditionCounters(profile: IPmcData): boolean;
/**
* Scav quest progress isnt transferred automatically from scav to pmc, we do this manually
* @param scavProfile Scav profile with quest progress post-raid
* @param pmcProfile Server pmc profile to copy scav quest progress into
*/
protected migrateScavQuestProgressToPmcProfile(scavProfile: IPmcData, pmcProfile: IPmcData): void;
/**
* Is the player dead after a raid - dead is anything other than "survived" / "runner"

View File

@ -1,3 +1,4 @@
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
import { LocationGenerator } from "@spt-aki/generators/LocationGenerator";
import { LootGenerator } from "@spt-aki/generators/LootGenerator";
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
@ -13,6 +14,7 @@ import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { RaidTimeAdjustmentService } from "@spt-aki/services/RaidTimeAdjustmentService";
import { HashUtil } from "@spt-aki/utils/HashUtil";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
@ -25,13 +27,15 @@ export declare class LocationController {
protected logger: ILogger;
protected locationGenerator: LocationGenerator;
protected localisationService: LocalisationService;
protected raidTimeAdjustmentService: RaidTimeAdjustmentService;
protected lootGenerator: LootGenerator;
protected databaseServer: DatabaseServer;
protected timeUtil: TimeUtil;
protected configServer: ConfigServer;
protected applicationContext: ApplicationContext;
protected airdropConfig: IAirdropConfig;
protected locationConfig: ILocationConfig;
constructor(jsonUtil: JsonUtil, hashUtil: HashUtil, randomUtil: RandomUtil, weightedRandomHelper: WeightedRandomHelper, logger: ILogger, locationGenerator: LocationGenerator, localisationService: LocalisationService, lootGenerator: LootGenerator, databaseServer: DatabaseServer, timeUtil: TimeUtil, configServer: ConfigServer);
constructor(jsonUtil: JsonUtil, hashUtil: HashUtil, randomUtil: RandomUtil, weightedRandomHelper: WeightedRandomHelper, logger: ILogger, locationGenerator: LocationGenerator, localisationService: LocalisationService, raidTimeAdjustmentService: RaidTimeAdjustmentService, lootGenerator: LootGenerator, databaseServer: DatabaseServer, timeUtil: TimeUtil, configServer: ConfigServer, applicationContext: ApplicationContext);
/**
* Handle client/location/getLocalloot
* Get a location (map) with generated loot data

View File

@ -82,7 +82,7 @@ export declare class QuestController {
* @param pmcData Profile to update
* @param acceptedQuest Quest accepted
* @param sessionID Session id
* @returns client response
* @returns Client response
*/
acceptQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse;
/**

View File

@ -41,7 +41,7 @@ declare class TradeController {
/** Handle RagFairBuyOffer event */
confirmRagfairTrading(pmcData: IPmcData, body: IProcessRagfairTradeRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle SellAllFromSavage event */
sellScavItemsToFence(pmcData: IPmcData, body: ISellScavItemsToFenceRequestData, sessionId: string): IItemEventRouterResponse;
sellScavItemsToFence(pmcData: IPmcData, request: ISellScavItemsToFenceRequestData, sessionId: string): IItemEventRouterResponse;
/**
* Sell all sellable items to a trader from inventory
* WILL DELETE ITEMS FROM INVENTORY + CHILDREN OF ITEMS SOLD

View File

@ -73,12 +73,13 @@ export declare class BotWeaponGenerator {
*/
generateWeaponByTpl(sessionId: string, weaponTpl: string, equipmentSlot: string, botTemplateInventory: Inventory, weaponParentId: string, modChances: ModsChances, botRole: string, isPmc: boolean, botLevel: number): GenerateWeaponResult;
/**
* Insert a cartridge into a weapon
* Insert a cartridge(s) into a weapon
* Handles all chambers - patron_in_weapon, patron_in_weapon_000 etc
* @param weaponWithModsArray Weapon and mods
* @param ammoTpl Cartridge to add to weapon
* @param desiredSlotId name of slot, e.g. patron_in_weapon
* @param chamberSlotIds name of slots to create or add ammo to
*/
protected addCartridgeToChamber(weaponWithModsArray: Item[], ammoTpl: string, desiredSlotId: string): void;
protected addCartridgeToChamber(weaponWithModsArray: Item[], ammoTpl: string, chamberSlotIds: string[]): void;
/**
* Create array with weapon base as only element and
* add additional properties based on weapon type

View File

@ -121,11 +121,11 @@ export declare class LocationGenerator {
generateDynamicLoot(dynamicLootDist: ILooseLoot, staticAmmoDist: Record<string, IStaticAmmoDetails[]>, locationName: string): SpawnpointTemplate[];
/**
* Add forced spawn point loot into loot parameter array
* @param loot array to add forced loot to
* @param forcedSpawnPoints forced loot to add
* @param name of map currently generating forced loot for
* @param lootLocationTemplates array to add forced loot spawn locations to
* @param forcedSpawnPoints forced Forced loot locations that must be added
* @param locationName Name of map currently having force loot created for
*/
protected addForcedLoot(loot: SpawnpointTemplate[], forcedSpawnPoints: SpawnpointsForced[], locationName: string): void;
protected addForcedLoot(lootLocationTemplates: SpawnpointTemplate[], forcedSpawnPoints: SpawnpointsForced[], locationName: string): void;
/**
* Create array of item (with child items) and return
* @param chosenComposedKey Key we want to look up items for

View File

@ -2,15 +2,24 @@ import { IInventoryMagGen } from "@spt-aki/generators/weapongen/IInventoryMagGen
import { InventoryMagGen } from "@spt-aki/generators/weapongen/InventoryMagGen";
import { BotWeaponGeneratorHelper } from "@spt-aki/helpers/BotWeaponGeneratorHelper";
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
export declare class ExternalInventoryMagGen implements IInventoryMagGen {
protected logger: ILogger;
protected itemHelper: ItemHelper;
protected localisationService: LocalisationService;
protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper;
constructor(logger: ILogger, itemHelper: ItemHelper, localisationService: LocalisationService, botWeaponGeneratorHelper: BotWeaponGeneratorHelper);
protected randomUtil: RandomUtil;
constructor(logger: ILogger, itemHelper: ItemHelper, localisationService: LocalisationService, botWeaponGeneratorHelper: BotWeaponGeneratorHelper, randomUtil: RandomUtil);
getPriority(): number;
canHandleInventoryMagGen(inventoryMagGen: InventoryMagGen): boolean;
process(inventoryMagGen: InventoryMagGen): void;
/**
* Get a random compatible external magazine for a weapon, excluses internal magazines from possible pool
* @param weaponTpl Weapon to get mag for
* @returns tpl of magazine
*/
protected getRandomExternalMagazineForInternalMagazineGun(weaponTpl: string, magazineBlacklist: string[]): ITemplateItem;
}

View File

@ -1,4 +1,5 @@
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
declare class LookupItem<T, I> {
readonly byId: Map<string, T>;
readonly byParent: Map<string, I[]>;
@ -11,9 +12,10 @@ export declare class LookupCollection {
}
export declare class HandbookHelper {
protected databaseServer: DatabaseServer;
protected jsonUtil: JsonUtil;
protected lookupCacheGenerated: boolean;
protected handbookPriceCache: LookupCollection;
constructor(databaseServer: DatabaseServer);
constructor(databaseServer: DatabaseServer, jsonUtil: JsonUtil);
/**
* Create an in-memory cache of all items with associated handbook price in handbookPriceCache class
*/

View File

@ -15,6 +15,7 @@ import { SaveServer } from "@spt-aki/servers/SaveServer";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { ProfileHelper } from "./ProfileHelper";
export declare class InRaidHelper {
protected logger: ILogger;
protected saveServer: SaveServer;
@ -22,6 +23,7 @@ export declare class InRaidHelper {
protected itemHelper: ItemHelper;
protected databaseServer: DatabaseServer;
protected inventoryHelper: InventoryHelper;
protected profileHelper: ProfileHelper;
protected questHelper: QuestHelper;
protected paymentHelper: PaymentHelper;
protected localisationService: LocalisationService;
@ -29,7 +31,7 @@ export declare class InRaidHelper {
protected configServer: ConfigServer;
protected lostOnDeathConfig: ILostOnDeathConfig;
protected inRaidConfig: IInRaidConfig;
constructor(logger: ILogger, saveServer: SaveServer, jsonUtil: JsonUtil, itemHelper: ItemHelper, databaseServer: DatabaseServer, inventoryHelper: InventoryHelper, questHelper: QuestHelper, paymentHelper: PaymentHelper, localisationService: LocalisationService, profileFixerService: ProfileFixerService, configServer: ConfigServer);
constructor(logger: ILogger, saveServer: SaveServer, jsonUtil: JsonUtil, itemHelper: ItemHelper, databaseServer: DatabaseServer, inventoryHelper: InventoryHelper, profileHelper: ProfileHelper, questHelper: QuestHelper, paymentHelper: PaymentHelper, localisationService: LocalisationService, profileFixerService: ProfileFixerService, configServer: ConfigServer);
/**
* Lookup quest item loss from lostOnDeath config
* @returns True if items should be removed from inventory
@ -64,16 +66,36 @@ export declare class InRaidHelper {
* @param sessionID Session id
* @returns Reset profile object
*/
updateProfileBaseStats(profileData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionID: string): IPmcData;
updateProfileBaseStats(profileData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionID: string): void;
/**
* Look for quests not are now status = fail that were not failed pre-raid and run the failQuest() function
* Reset the skill points earned in a raid to 0, ready for next raid
* @param profile Profile to update
*/
protected resetSkillPointsEarnedDuringRaid(profile: IPmcData): void;
/** Check counters are correct in profile */
protected validateBackendCounters(saveProgressRequest: ISaveProgressRequestData, profileData: IPmcData): void;
/**
* Update various serverPMC profile values; quests/limb hp/trader standing with values post-raic
* @param pmcData Server PMC profile
* @param saveProgressRequest Post-raid request data
* @param sessionId Session id
*/
updatePmcProfileDataPostRaid(pmcData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionId: string): void;
/**
* Update scav quest values on server profile with updated values post-raid
* @param scavData Server scav profile
* @param saveProgressRequest Post-raid request data
* @param sessionId Session id
*/
updateScavProfileDataPostRaid(scavData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionId: string): void;
/**
* Look for quests with status = fail that were not failed pre-raid and run the failQuest() function
* @param sessionId Player id
* @param pmcData Player profile
* @param preRaidQuests Quests prior to starting raid
* @param postRaidQuests Quest after raid
* @param postRaidProfile Profile sent by client
*/
protected processFailedQuests(sessionId: string, pmcData: IPmcData, preRaidQuests: IQuestStatus[], postRaidQuests: IQuestStatus[]): void;
protected resetSkillPointsEarnedDuringRaid(profile: IPmcData): void;
protected processFailedQuests(sessionId: string, pmcData: IPmcData, preRaidQuests: IQuestStatus[], postRaidProfile: IPostRaidPmcData): void;
/**
* Take body part effects from client profile and apply to server profile
* @param saveProgressRequest post-raid request

View File

@ -323,7 +323,7 @@ declare class ItemHelper {
* Chose a randomly weighted cartridge that fits
* @param caliber Desired caliber
* @param staticAmmoDist Cartridges and thier weights
* @returns Tpl of cartrdige
* @returns Tpl of cartridge
*/
protected drawAmmoTpl(caliber: string, staticAmmoDist: Record<string, IStaticAmmoDetails[]>): string;
/**

View File

@ -206,16 +206,23 @@ export declare class QuestHelper {
* @param questId Id of the quest to alter the status of
*/
updateQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void;
/**
* Resets a quests values back to its chosen state
* @param pmcData Profile to update
* @param newQuestState New state the quest should be in
* @param questId Id of the quest to alter the status of
*/
resetQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void;
/**
* Give player quest rewards - Skills/exp/trader standing/items/assort unlocks - Returns reward items player earned
* @param pmcData Player profile
* @param profileData Player profile (scav or pmc)
* @param questId questId of quest to get rewards for
* @param state State of the quest to get rewards for
* @param sessionId Session id
* @param questResponse Response to send back to client
* @returns Array of reward objects
*/
applyQuestReward(pmcData: IPmcData, questId: string, state: QuestStatus, sessionId: string, questResponse: IItemEventRouterResponse): Reward[];
applyQuestReward(profileData: IPmcData, questId: string, state: QuestStatus, sessionId: string, questResponse: IItemEventRouterResponse): Reward[];
/**
* WIP - Find hideout craft id and add to unlockedProductionRecipe array in player profile
* also update client response recipeUnlocked array with craft id

View File

@ -25,7 +25,7 @@ export declare class WeightedRandomHelper {
* @param {number[]} weights
* @returns {{item: any, index: number}}
*/
weightedRandom(items: string | any[], weights: string | any[]): {
weightedRandom(items: any[], weights: any[]): {
item: any;
index: number;
};

View File

@ -309,6 +309,8 @@ export interface Productive {
sptIsScavCase?: boolean;
/** Some crafts are always inProgress, but need to be reset, e.g. water collector */
sptIsComplete?: boolean;
/** Is the craft a Continuous, e.g bitcoins/water collector */
sptIsContinuous?: boolean;
}
export interface Production extends Productive {
RecipeId: string;
@ -361,7 +363,7 @@ export interface IQuestStatus {
startTime: number;
status: QuestStatus;
statusTimers?: Record<string, number>;
/** SPT specific property */
/** Property does not exist in live profile data, but is used by ProfileChanges.questsStatus when sent to client*/
completedConditions?: string[];
availableAfter?: number;
}
@ -373,14 +375,6 @@ export interface TraderInfo {
unlocked: boolean;
disabled: boolean;
}
/** This object is sent to the client as part of traderRelations */
export interface TraderData {
salesSum: number;
standing: number;
loyalty: number;
unlocked: boolean;
disabled: boolean;
}
export interface RagfairInfo {
rating: number;
isRatingGrowing: boolean;

View File

@ -0,0 +1,4 @@
export interface IGetRaidTimeRequest {
Side: string;
Location: string;
}

View File

@ -0,0 +1,12 @@
export interface IGetRaidTimeResponse {
RaidTimeMinutes: number;
NewSurviveTimeSeconds: number;
OriginalSurvivalTimeSeconds: number;
ExitChanges: ExtractChange[];
}
export interface ExtractChange {
Name: string;
MinTime?: number;
MaxTime?: number;
Chance?: number;
}

View File

@ -1,4 +1,4 @@
import { Health, IQuestStatus, Productive, Skills, TraderData } from "@spt-aki/models/eft/common/tables/IBotBase";
import { Health, IQuestStatus, Productive, Skills } from "@spt-aki/models/eft/common/tables/IBotBase";
import { Item, Upd } from "@spt-aki/models/eft/common/tables/IItem";
import { IQuest } from "@spt-aki/models/eft/common/tables/IQuest";
import { IPmcDataRepeatableQuest } from "@spt-aki/models/eft/common/tables/IRepeatableQuests";
@ -62,6 +62,14 @@ export interface Improvement {
completed: boolean;
improveCompleteTimestamp: number;
}
/** Related to TraderInfo */
export interface TraderData {
salesSum: number;
standing: number;
loyalty: number;
unlocked: boolean;
disabled: boolean;
}
export interface Product {
_id: string;
_tpl?: string;

View File

@ -54,6 +54,7 @@ export declare enum BaseClasses {
GRENADE_LAUNCHER = "5447bedf4bdc2d87278b4568",
SPECIAL_WEAPON = "5447bee84bdc2dc3278b4569",
SPEC_ITEM = "5447e0e74bdc2d3c308b4567",
SPRING_DRIVEN_CYLINDER = "627a137bf21bc425b06ab944",
KNIFE = "5447e1d04bdc2dff2f8b4567",
AMMO = "5485a8684bdc2da71d8b4567",
AMMO_BOX = "543be5cb4bdc2deb348b4568",

View File

@ -1,4 +1,6 @@
export declare enum ItemAddedResult {
UNKNOWN = -1,
SUCCESS = 1,
NO_SPACE = 2
NO_SPACE = 2,
NO_CONTAINERS = 3
}

View File

@ -25,6 +25,8 @@ export interface IBotConfig extends IBaseConfig {
showTypeInNickname: boolean;
/** What ai brain should a normal scav use per map */
assaultBrainType: Record<string, Record<string, number>>;
/** What ai brain should a player scav use per map */
playerScavBrainType: Record<string, Record<string, number>>;
/** Max number of bots that can be spawned in a raid at any one time */
maxBotCap: Record<string, number>;
/** Chance scav has fake pscav name e.g. Scav name (player name) */

View File

@ -19,6 +19,8 @@ export interface IGameFixes {
fixShotgunDispersion: boolean;
/** Remove items added by mods when the mod no longer exists - can fix dead profiles stuck at game load*/
removeModItemsFromProfile: boolean;
/** Fix issues that cause the game to not start due to inventory item issues */
fixProfileBreakingInventoryItemIssues: boolean;
}
export interface IServerFeatures {
autoInstallModDependencies: boolean;

View File

@ -36,15 +36,8 @@ export interface ILocationConfig extends IBaseConfig {
allowDuplicateItemsInStaticContainers: boolean;
/** Key: map, value: loose loot ids to ignore */
looseLootBlacklist: Record<string, string[]>;
}
export interface IContainerRandomistionSettings {
enabled: boolean;
/** What maps can use the container randomisation feature */
maps: Record<string, boolean>;
/** Some container types don't work when randomised */
containerTypesToNotRandomise: string[];
containerGroupMinSizeMultiplier: number;
containerGroupMaxSizeMultiplier: number;
/** Key: map, value: settings to control how long scav raids are*/
scavRaidTimeSettings: IScavRaidTimeSettings;
}
export interface IFixEmptyBotWavesSettings {
enabled: boolean;
@ -86,3 +79,30 @@ export interface LootMultiplier {
terminal: number;
town: number;
}
export interface IContainerRandomistionSettings {
enabled: boolean;
/** What maps can use the container randomisation feature */
maps: Record<string, boolean>;
/** Some container types don't work when randomised */
containerTypesToNotRandomise: string[];
containerGroupMinSizeMultiplier: number;
containerGroupMaxSizeMultiplier: number;
}
export interface IScavRaidTimeSettings {
settings: IScavRaidTimeConfigSettings;
maps: Record<string, IScavRaidTimeLocationSettings>;
}
export interface IScavRaidTimeConfigSettings {
trainArrivalDelayObservedSeconds: number;
}
export interface IScavRaidTimeLocationSettings {
/** Should loot be reduced by same percent length of raid is reduced by */
reduceLootByPercent: boolean;
minStaticLootPercent: number;
minDynamicLootPercent: number;
/** Chance raid time is reduced */
reducedChancePercent: number;
reductionPercentWeights: Record<string, number>;
/** Should bot waves be removed / spawn times be adjusted */
adjustWaves: boolean;
}

View File

@ -0,0 +1,8 @@
export interface IRaidChanges {
/** What percentage of dynamic loot should the map contain */
dynamicLootPercent: number;
/** What percentage of static loot should the map contain */
staticLootPercent: number;
/** How many seconds into the raid is the player simulated to spawn in at */
simulatedRaidStartSeconds: number;
}

View File

@ -1,6 +1,7 @@
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
import { IHideoutImprovement, Productive, TraderData, TraderInfo } from "@spt-aki/models/eft/common/tables/IBotBase";
import { IHideoutImprovement, Productive, TraderInfo } from "@spt-aki/models/eft/common/tables/IBotBase";
import { TraderData } from "@spt-aki/models/eft/itemEvent/IItemEventRouterBase";
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
@ -48,5 +49,5 @@ export declare class EventOutputHolder {
* Required as continuous productions don't reset and stay at 100% completion but client thinks it hasn't started
* @param productions Productions in a profile
*/
protected resetSptIsCompleteFlaggedCrafts(productions: Record<string, Productive>): void;
protected cleanUpCompleteCraftsInProfile(productions: Record<string, Productive>): void;
}

View File

@ -41,6 +41,11 @@ export declare class ProfileFixerService {
* @param pmcProfile profile to check and fix
*/
checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void;
/**
* Find issues in the scav profile data that may cause issues
* @param scavProfile profile to check and fix
*/
checkForAndFixScavProfileIssues(scavProfile: IPmcData): void;
protected addMissingGunStandContainerImprovements(pmcProfile: IPmcData): void;
protected ensureGunStandLevelsMatch(pmcProfile: IPmcData): void;
protected addHideoutAreaStashes(pmcProfile: IPmcData): void;
@ -67,9 +72,9 @@ export declare class ProfileFixerService {
* Adjust profile quest status and statusTimers object values
* quest.status is numeric e.g. 2
* quest.statusTimers keys are numeric as strings e.g. "2"
* @param pmcProfile profile to update
* @param profile profile to update
*/
protected updateProfileQuestDataValues(pmcProfile: IPmcData): void;
protected updateProfileQuestDataValues(profile: IPmcData): void;
protected addMissingRepeatableQuestsProperty(pmcProfile: IPmcData): void;
/**
* Some profiles have hideout maxed and therefore no improvements
@ -115,6 +120,11 @@ export declare class ProfileFixerService {
* @param pmcProfile Profile to check inventory of
*/
checkForOrphanedModdedItems(sessionId: string, fullProfile: IAkiProfile): void;
/**
* Attempt to fix common item issues that corrupt profiles
* @param pmcProfile Profile to check items of
*/
fixProfileBreakingInventoryItemIssues(pmcProfile: IPmcData): void;
/**
* Add `Improvements` object to hideout if missing - added in eft 13.0.21469
* @param pmcProfile profile to update

View File

@ -0,0 +1,60 @@
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
import { ILocationBase } from "@spt-aki/models/eft/common/ILocationBase";
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
import { ExtractChange, IGetRaidTimeResponse } from "@spt-aki/models/eft/game/IGetRaidTimeResponse";
import { ILocationConfig, IScavRaidTimeLocationSettings, LootMultiplier } from "@spt-aki/models/spt/config/ILocationConfig";
import { IRaidChanges } from "@spt-aki/models/spt/location/IRaidChanges";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
export declare class RaidTimeAdjustmentService {
protected logger: ILogger;
protected databaseServer: DatabaseServer;
protected randomUtil: RandomUtil;
protected weightedRandomHelper: WeightedRandomHelper;
protected applicationContext: ApplicationContext;
protected configServer: ConfigServer;
protected locationConfig: ILocationConfig;
constructor(logger: ILogger, databaseServer: DatabaseServer, randomUtil: RandomUtil, weightedRandomHelper: WeightedRandomHelper, applicationContext: ApplicationContext, configServer: ConfigServer);
/**
* Make alterations to the base map data passed in
* Loot multipliers/waves/wave start times
* @param raidAdjustments Changes to process on map
* @param mapBase Map to adjust
*/
makeAdjustmentsToMap(raidAdjustments: IRaidChanges, mapBase: ILocationBase): void;
/**
* Adjust the loot multiplier values passed in to be a % of their original value
* @param mapLootMultiplers Multiplers to adjust
* @param loosePercent Percent to change values to
*/
protected adjustLootMultipliers(mapLootMultiplers: LootMultiplier, loosePercent: number): void;
/**
* Adjust bot waves to act as if player spawned later
* @param mapBase map to adjust
* @param raidAdjustments Map adjustments
*/
protected adjustWaves(mapBase: ILocationBase, raidAdjustments: IRaidChanges): void;
/**
* Create a randomised adjustment to the raid based on map data in location.json
* @param sessionId Session id
* @param request Raid adjustment request
* @returns Response to send to client
*/
getRaidAdjustments(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse;
/**
* Get raid start time settings for specific map
* @param location Map Location e.g. bigmap
* @returns IScavRaidTimeLocationSettings
*/
protected getMapSettings(location: string): IScavRaidTimeLocationSettings;
/**
* Adjust exit times to handle scavs entering raids part-way through
* @param mapBase Map base file player is on
* @param newRaidTimeMinutes How long raid is in minutes
* @returns List of exit changes to send to client
*/
protected getExitAdjustments(mapBase: ILocationBase, newRaidTimeMinutes: number): ExtractChange[];
}

View File

@ -15,6 +15,13 @@ export declare class HttpResponseUtil {
* @returns
*/
noBody(data: any): any;
/**
* Game client needs server responses in a particular format
* @param data
* @param err
* @param errmsg
* @returns
*/
getBody<T>(data: T, err?: number, errmsg?: any): IGetBodyResponseData<T>;
getUnclearedBody(data: any, err?: number, errmsg?: any): string;
emptyResponse(): IGetBodyResponseData<string>;

View File

@ -111,6 +111,13 @@ export declare class RandomUtil {
getFloat(min: number, max: number): number;
getBool(): boolean;
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
*/
reduceValueByPercent(number: number, percentage: number): number;
/**
* Check if number passes a check out of 100
* @param chancePercent value check needs to be above

View File

@ -8,6 +8,7 @@ import { IGameEmptyCrcRequestData } from "@spt-aki/models/eft/game/IGameEmptyCrc
import { IGameKeepAliveResponse } from "@spt-aki/models/eft/game/IGameKeepAliveResponse";
import { IGameLogoutResponseData } from "@spt-aki/models/eft/game/IGameLogoutResponseData";
import { IGameStartResponse } from "@spt-aki/models/eft/game/IGameStartResponse";
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
import { IReportNicknameRequestData } from "@spt-aki/models/eft/game/IReportNicknameRequestData";
import { IServerDetails } from "@spt-aki/models/eft/game/IServerDetails";
import { IVersionValidateRequestData } from "@spt-aki/models/eft/game/IVersionValidateRequestData";
@ -68,5 +69,10 @@ declare class GameCallbacks implements OnLoad {
*/
getVersion(url: string, info: IEmptyRequestData, sessionID: string): string;
reportNickname(url: string, info: IReportNicknameRequestData, sessionID: string): INullResponseData;
/**
* Handle singleplayer/settings/getRaidTime
* @returns string
*/
getRaidTime(url: string, request: IGetRaidTimeRequest, sessionID: string): any;
}
export { GameCallbacks };

View File

@ -10,11 +10,12 @@ export declare class ApplicationContext {
*
* const activePlayerSessionId = this.applicationContext.getLatestValue(ContextVariableType.SESSION_ID).getValue<string>();
*
* const matchInfo = this.applicationContext.getLatestValue(ContextVariableType.MATCH_INFO).getValue<IStartOfflineRaidRequestData>();
* const matchInfo = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION).getValue<IGetRaidConfigurationRequestData>();
* @param type
* @returns
*/
getLatestValue(type: ContextVariableType): ContextVariable;
getValues(type: ContextVariableType): ContextVariable[];
addValue(type: ContextVariableType, value: any): void;
clearValues(type: ContextVariableType): void;
}

View File

@ -6,5 +6,6 @@ export declare enum ContextVariableType {
/** Timestamp when client first connected */
CLIENT_START_TIMESTAMP = 2,
/** When player is loading into map and loot is requested */
REGISTER_PLAYER_REQUEST = 3
REGISTER_PLAYER_REQUEST = 3,
RAID_ADJUSTMENTS = 4
}

View File

@ -9,6 +9,8 @@ import { ICheckVersionResponse } from "@spt-aki/models/eft/game/ICheckVersionRes
import { ICurrentGroupResponse } from "@spt-aki/models/eft/game/ICurrentGroupResponse";
import { IGameConfigResponse } from "@spt-aki/models/eft/game/IGameConfigResponse";
import { IGameKeepAliveResponse } from "@spt-aki/models/eft/game/IGameKeepAliveResponse";
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
import { IGetRaidTimeResponse } from "@spt-aki/models/eft/game/IGetRaidTimeResponse";
import { IServerDetails } from "@spt-aki/models/eft/game/IServerDetails";
import { IAkiProfile } from "@spt-aki/models/eft/profile/IAkiProfile";
import { ICoreConfig } from "@spt-aki/models/spt/config/ICoreConfig";
@ -26,7 +28,9 @@ import { ItemBaseClassService } from "@spt-aki/services/ItemBaseClassService";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { OpenZoneService } from "@spt-aki/services/OpenZoneService";
import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService";
import { RaidTimeAdjustmentService } from "@spt-aki/services/RaidTimeAdjustmentService";
import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
import { HashUtil } from "@spt-aki/utils/HashUtil";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
@ -35,6 +39,7 @@ export declare class GameController {
protected databaseServer: DatabaseServer;
protected jsonUtil: JsonUtil;
protected timeUtil: TimeUtil;
protected hashUtil: HashUtil;
protected preAkiModLoader: PreAkiModLoader;
protected httpServerHelper: HttpServerHelper;
protected randomUtil: RandomUtil;
@ -47,6 +52,7 @@ export declare class GameController {
protected seasonalEventService: SeasonalEventService;
protected itemBaseClassService: ItemBaseClassService;
protected giftService: GiftService;
protected raidTimeAdjustmentService: RaidTimeAdjustmentService;
protected applicationContext: ApplicationContext;
protected configServer: ConfigServer;
protected httpConfig: IHttpConfig;
@ -55,7 +61,7 @@ export declare class GameController {
protected ragfairConfig: IRagfairConfig;
protected pmcConfig: IPmcConfig;
protected lootConfig: ILootConfig;
constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer);
constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, raidTimeAdjustmentService: RaidTimeAdjustmentService, applicationContext: ApplicationContext, configServer: ConfigServer);
load(): void;
/**
* Handle client/game/start
@ -90,6 +96,10 @@ export declare class GameController {
* Handle client/game/keepalive
*/
getKeepAlive(sessionId: string): IGameKeepAliveResponse;
/**
* Handle singleplayer/settings/getRaidTime
*/
getRaidTime(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse;
/**
* BSG have two values for shotgun dispersion, we make sure both have the same value
*/

View File

@ -101,7 +101,7 @@ export declare class HideoutController {
*/
protected addUpdateInventoryItemToProfile(pmcData: IPmcData, dbHideoutData: IHideoutArea, hideoutStage: Stage): void;
/**
* @param output Objet to send to client
* @param output Object to send to client
* @param sessionID Session/player id
* @param areaType Hideout area that had stash added
* @param hideoutDbData Hideout area that caused addition of stash

View File

@ -95,9 +95,14 @@ export declare class InraidController {
/**
* Does provided profile contain any condition counters
* @param profile Profile to check for condition counters
* @returns
* @returns Profile has condition counters
*/
protected profileHasConditionCounters(profile: IPmcData): boolean;
/**
* Scav quest progress isnt transferred automatically from scav to pmc, we do this manually
* @param scavProfile Scav profile with quest progress post-raid
* @param pmcProfile Server pmc profile to copy scav quest progress into
*/
protected migrateScavQuestProgressToPmcProfile(scavProfile: IPmcData, pmcProfile: IPmcData): void;
/**
* Is the player dead after a raid - dead is anything other than "survived" / "runner"

View File

@ -1,3 +1,4 @@
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
import { LocationGenerator } from "@spt-aki/generators/LocationGenerator";
import { LootGenerator } from "@spt-aki/generators/LootGenerator";
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
@ -13,6 +14,7 @@ import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { RaidTimeAdjustmentService } from "@spt-aki/services/RaidTimeAdjustmentService";
import { HashUtil } from "@spt-aki/utils/HashUtil";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
@ -25,13 +27,15 @@ export declare class LocationController {
protected logger: ILogger;
protected locationGenerator: LocationGenerator;
protected localisationService: LocalisationService;
protected raidTimeAdjustmentService: RaidTimeAdjustmentService;
protected lootGenerator: LootGenerator;
protected databaseServer: DatabaseServer;
protected timeUtil: TimeUtil;
protected configServer: ConfigServer;
protected applicationContext: ApplicationContext;
protected airdropConfig: IAirdropConfig;
protected locationConfig: ILocationConfig;
constructor(jsonUtil: JsonUtil, hashUtil: HashUtil, randomUtil: RandomUtil, weightedRandomHelper: WeightedRandomHelper, logger: ILogger, locationGenerator: LocationGenerator, localisationService: LocalisationService, lootGenerator: LootGenerator, databaseServer: DatabaseServer, timeUtil: TimeUtil, configServer: ConfigServer);
constructor(jsonUtil: JsonUtil, hashUtil: HashUtil, randomUtil: RandomUtil, weightedRandomHelper: WeightedRandomHelper, logger: ILogger, locationGenerator: LocationGenerator, localisationService: LocalisationService, raidTimeAdjustmentService: RaidTimeAdjustmentService, lootGenerator: LootGenerator, databaseServer: DatabaseServer, timeUtil: TimeUtil, configServer: ConfigServer, applicationContext: ApplicationContext);
/**
* Handle client/location/getLocalloot
* Get a location (map) with generated loot data

View File

@ -82,7 +82,7 @@ export declare class QuestController {
* @param pmcData Profile to update
* @param acceptedQuest Quest accepted
* @param sessionID Session id
* @returns client response
* @returns Client response
*/
acceptQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse;
/**

View File

@ -41,7 +41,7 @@ declare class TradeController {
/** Handle RagFairBuyOffer event */
confirmRagfairTrading(pmcData: IPmcData, body: IProcessRagfairTradeRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle SellAllFromSavage event */
sellScavItemsToFence(pmcData: IPmcData, body: ISellScavItemsToFenceRequestData, sessionId: string): IItemEventRouterResponse;
sellScavItemsToFence(pmcData: IPmcData, request: ISellScavItemsToFenceRequestData, sessionId: string): IItemEventRouterResponse;
/**
* Sell all sellable items to a trader from inventory
* WILL DELETE ITEMS FROM INVENTORY + CHILDREN OF ITEMS SOLD

View File

@ -73,12 +73,13 @@ export declare class BotWeaponGenerator {
*/
generateWeaponByTpl(sessionId: string, weaponTpl: string, equipmentSlot: string, botTemplateInventory: Inventory, weaponParentId: string, modChances: ModsChances, botRole: string, isPmc: boolean, botLevel: number): GenerateWeaponResult;
/**
* Insert a cartridge into a weapon
* Insert a cartridge(s) into a weapon
* Handles all chambers - patron_in_weapon, patron_in_weapon_000 etc
* @param weaponWithModsArray Weapon and mods
* @param ammoTpl Cartridge to add to weapon
* @param desiredSlotId name of slot, e.g. patron_in_weapon
* @param chamberSlotIds name of slots to create or add ammo to
*/
protected addCartridgeToChamber(weaponWithModsArray: Item[], ammoTpl: string, desiredSlotId: string): void;
protected addCartridgeToChamber(weaponWithModsArray: Item[], ammoTpl: string, chamberSlotIds: string[]): void;
/**
* Create array with weapon base as only element and
* add additional properties based on weapon type

View File

@ -121,11 +121,11 @@ export declare class LocationGenerator {
generateDynamicLoot(dynamicLootDist: ILooseLoot, staticAmmoDist: Record<string, IStaticAmmoDetails[]>, locationName: string): SpawnpointTemplate[];
/**
* Add forced spawn point loot into loot parameter array
* @param loot array to add forced loot to
* @param forcedSpawnPoints forced loot to add
* @param name of map currently generating forced loot for
* @param lootLocationTemplates array to add forced loot spawn locations to
* @param forcedSpawnPoints forced Forced loot locations that must be added
* @param locationName Name of map currently having force loot created for
*/
protected addForcedLoot(loot: SpawnpointTemplate[], forcedSpawnPoints: SpawnpointsForced[], locationName: string): void;
protected addForcedLoot(lootLocationTemplates: SpawnpointTemplate[], forcedSpawnPoints: SpawnpointsForced[], locationName: string): void;
/**
* Create array of item (with child items) and return
* @param chosenComposedKey Key we want to look up items for

View File

@ -2,15 +2,24 @@ import { IInventoryMagGen } from "@spt-aki/generators/weapongen/IInventoryMagGen
import { InventoryMagGen } from "@spt-aki/generators/weapongen/InventoryMagGen";
import { BotWeaponGeneratorHelper } from "@spt-aki/helpers/BotWeaponGeneratorHelper";
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
export declare class ExternalInventoryMagGen implements IInventoryMagGen {
protected logger: ILogger;
protected itemHelper: ItemHelper;
protected localisationService: LocalisationService;
protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper;
constructor(logger: ILogger, itemHelper: ItemHelper, localisationService: LocalisationService, botWeaponGeneratorHelper: BotWeaponGeneratorHelper);
protected randomUtil: RandomUtil;
constructor(logger: ILogger, itemHelper: ItemHelper, localisationService: LocalisationService, botWeaponGeneratorHelper: BotWeaponGeneratorHelper, randomUtil: RandomUtil);
getPriority(): number;
canHandleInventoryMagGen(inventoryMagGen: InventoryMagGen): boolean;
process(inventoryMagGen: InventoryMagGen): void;
/**
* Get a random compatible external magazine for a weapon, excluses internal magazines from possible pool
* @param weaponTpl Weapon to get mag for
* @returns tpl of magazine
*/
protected getRandomExternalMagazineForInternalMagazineGun(weaponTpl: string, magazineBlacklist: string[]): ITemplateItem;
}

View File

@ -1,4 +1,5 @@
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
declare class LookupItem<T, I> {
readonly byId: Map<string, T>;
readonly byParent: Map<string, I[]>;
@ -11,9 +12,10 @@ export declare class LookupCollection {
}
export declare class HandbookHelper {
protected databaseServer: DatabaseServer;
protected jsonUtil: JsonUtil;
protected lookupCacheGenerated: boolean;
protected handbookPriceCache: LookupCollection;
constructor(databaseServer: DatabaseServer);
constructor(databaseServer: DatabaseServer, jsonUtil: JsonUtil);
/**
* Create an in-memory cache of all items with associated handbook price in handbookPriceCache class
*/

View File

@ -15,6 +15,7 @@ import { SaveServer } from "@spt-aki/servers/SaveServer";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { ProfileHelper } from "./ProfileHelper";
export declare class InRaidHelper {
protected logger: ILogger;
protected saveServer: SaveServer;
@ -22,6 +23,7 @@ export declare class InRaidHelper {
protected itemHelper: ItemHelper;
protected databaseServer: DatabaseServer;
protected inventoryHelper: InventoryHelper;
protected profileHelper: ProfileHelper;
protected questHelper: QuestHelper;
protected paymentHelper: PaymentHelper;
protected localisationService: LocalisationService;
@ -29,7 +31,7 @@ export declare class InRaidHelper {
protected configServer: ConfigServer;
protected lostOnDeathConfig: ILostOnDeathConfig;
protected inRaidConfig: IInRaidConfig;
constructor(logger: ILogger, saveServer: SaveServer, jsonUtil: JsonUtil, itemHelper: ItemHelper, databaseServer: DatabaseServer, inventoryHelper: InventoryHelper, questHelper: QuestHelper, paymentHelper: PaymentHelper, localisationService: LocalisationService, profileFixerService: ProfileFixerService, configServer: ConfigServer);
constructor(logger: ILogger, saveServer: SaveServer, jsonUtil: JsonUtil, itemHelper: ItemHelper, databaseServer: DatabaseServer, inventoryHelper: InventoryHelper, profileHelper: ProfileHelper, questHelper: QuestHelper, paymentHelper: PaymentHelper, localisationService: LocalisationService, profileFixerService: ProfileFixerService, configServer: ConfigServer);
/**
* Lookup quest item loss from lostOnDeath config
* @returns True if items should be removed from inventory
@ -64,16 +66,36 @@ export declare class InRaidHelper {
* @param sessionID Session id
* @returns Reset profile object
*/
updateProfileBaseStats(profileData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionID: string): IPmcData;
updateProfileBaseStats(profileData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionID: string): void;
/**
* Look for quests not are now status = fail that were not failed pre-raid and run the failQuest() function
* Reset the skill points earned in a raid to 0, ready for next raid
* @param profile Profile to update
*/
protected resetSkillPointsEarnedDuringRaid(profile: IPmcData): void;
/** Check counters are correct in profile */
protected validateBackendCounters(saveProgressRequest: ISaveProgressRequestData, profileData: IPmcData): void;
/**
* Update various serverPMC profile values; quests/limb hp/trader standing with values post-raic
* @param pmcData Server PMC profile
* @param saveProgressRequest Post-raid request data
* @param sessionId Session id
*/
updatePmcProfileDataPostRaid(pmcData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionId: string): void;
/**
* Update scav quest values on server profile with updated values post-raid
* @param scavData Server scav profile
* @param saveProgressRequest Post-raid request data
* @param sessionId Session id
*/
updateScavProfileDataPostRaid(scavData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionId: string): void;
/**
* Look for quests with status = fail that were not failed pre-raid and run the failQuest() function
* @param sessionId Player id
* @param pmcData Player profile
* @param preRaidQuests Quests prior to starting raid
* @param postRaidQuests Quest after raid
* @param postRaidProfile Profile sent by client
*/
protected processFailedQuests(sessionId: string, pmcData: IPmcData, preRaidQuests: IQuestStatus[], postRaidQuests: IQuestStatus[]): void;
protected resetSkillPointsEarnedDuringRaid(profile: IPmcData): void;
protected processFailedQuests(sessionId: string, pmcData: IPmcData, preRaidQuests: IQuestStatus[], postRaidProfile: IPostRaidPmcData): void;
/**
* Take body part effects from client profile and apply to server profile
* @param saveProgressRequest post-raid request

View File

@ -323,7 +323,7 @@ declare class ItemHelper {
* Chose a randomly weighted cartridge that fits
* @param caliber Desired caliber
* @param staticAmmoDist Cartridges and thier weights
* @returns Tpl of cartrdige
* @returns Tpl of cartridge
*/
protected drawAmmoTpl(caliber: string, staticAmmoDist: Record<string, IStaticAmmoDetails[]>): string;
/**

View File

@ -206,16 +206,23 @@ export declare class QuestHelper {
* @param questId Id of the quest to alter the status of
*/
updateQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void;
/**
* Resets a quests values back to its chosen state
* @param pmcData Profile to update
* @param newQuestState New state the quest should be in
* @param questId Id of the quest to alter the status of
*/
resetQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void;
/**
* Give player quest rewards - Skills/exp/trader standing/items/assort unlocks - Returns reward items player earned
* @param pmcData Player profile
* @param profileData Player profile (scav or pmc)
* @param questId questId of quest to get rewards for
* @param state State of the quest to get rewards for
* @param sessionId Session id
* @param questResponse Response to send back to client
* @returns Array of reward objects
*/
applyQuestReward(pmcData: IPmcData, questId: string, state: QuestStatus, sessionId: string, questResponse: IItemEventRouterResponse): Reward[];
applyQuestReward(profileData: IPmcData, questId: string, state: QuestStatus, sessionId: string, questResponse: IItemEventRouterResponse): Reward[];
/**
* WIP - Find hideout craft id and add to unlockedProductionRecipe array in player profile
* also update client response recipeUnlocked array with craft id

View File

@ -25,7 +25,7 @@ export declare class WeightedRandomHelper {
* @param {number[]} weights
* @returns {{item: any, index: number}}
*/
weightedRandom(items: string | any[], weights: string | any[]): {
weightedRandom(items: any[], weights: any[]): {
item: any;
index: number;
};

View File

@ -309,6 +309,8 @@ export interface Productive {
sptIsScavCase?: boolean;
/** Some crafts are always inProgress, but need to be reset, e.g. water collector */
sptIsComplete?: boolean;
/** Is the craft a Continuous, e.g bitcoins/water collector */
sptIsContinuous?: boolean;
}
export interface Production extends Productive {
RecipeId: string;
@ -361,7 +363,7 @@ export interface IQuestStatus {
startTime: number;
status: QuestStatus;
statusTimers?: Record<string, number>;
/** SPT specific property */
/** Property does not exist in live profile data, but is used by ProfileChanges.questsStatus when sent to client*/
completedConditions?: string[];
availableAfter?: number;
}
@ -373,14 +375,6 @@ export interface TraderInfo {
unlocked: boolean;
disabled: boolean;
}
/** This object is sent to the client as part of traderRelations */
export interface TraderData {
salesSum: number;
standing: number;
loyalty: number;
unlocked: boolean;
disabled: boolean;
}
export interface RagfairInfo {
rating: number;
isRatingGrowing: boolean;

View File

@ -0,0 +1,4 @@
export interface IGetRaidTimeRequest {
Side: string;
Location: string;
}

View File

@ -0,0 +1,12 @@
export interface IGetRaidTimeResponse {
RaidTimeMinutes: number;
NewSurviveTimeSeconds: number;
OriginalSurvivalTimeSeconds: number;
ExitChanges: ExtractChange[];
}
export interface ExtractChange {
Name: string;
MinTime?: number;
MaxTime?: number;
Chance?: number;
}

View File

@ -1,4 +1,4 @@
import { Health, IQuestStatus, Productive, Skills, TraderData } from "@spt-aki/models/eft/common/tables/IBotBase";
import { Health, IQuestStatus, Productive, Skills } from "@spt-aki/models/eft/common/tables/IBotBase";
import { Item, Upd } from "@spt-aki/models/eft/common/tables/IItem";
import { IQuest } from "@spt-aki/models/eft/common/tables/IQuest";
import { IPmcDataRepeatableQuest } from "@spt-aki/models/eft/common/tables/IRepeatableQuests";
@ -62,6 +62,14 @@ export interface Improvement {
completed: boolean;
improveCompleteTimestamp: number;
}
/** Related to TraderInfo */
export interface TraderData {
salesSum: number;
standing: number;
loyalty: number;
unlocked: boolean;
disabled: boolean;
}
export interface Product {
_id: string;
_tpl?: string;

View File

@ -54,6 +54,7 @@ export declare enum BaseClasses {
GRENADE_LAUNCHER = "5447bedf4bdc2d87278b4568",
SPECIAL_WEAPON = "5447bee84bdc2dc3278b4569",
SPEC_ITEM = "5447e0e74bdc2d3c308b4567",
SPRING_DRIVEN_CYLINDER = "627a137bf21bc425b06ab944",
KNIFE = "5447e1d04bdc2dff2f8b4567",
AMMO = "5485a8684bdc2da71d8b4567",
AMMO_BOX = "543be5cb4bdc2deb348b4568",

View File

@ -1,4 +1,6 @@
export declare enum ItemAddedResult {
UNKNOWN = -1,
SUCCESS = 1,
NO_SPACE = 2
NO_SPACE = 2,
NO_CONTAINERS = 3
}

View File

@ -25,6 +25,8 @@ export interface IBotConfig extends IBaseConfig {
showTypeInNickname: boolean;
/** What ai brain should a normal scav use per map */
assaultBrainType: Record<string, Record<string, number>>;
/** What ai brain should a player scav use per map */
playerScavBrainType: Record<string, Record<string, number>>;
/** Max number of bots that can be spawned in a raid at any one time */
maxBotCap: Record<string, number>;
/** Chance scav has fake pscav name e.g. Scav name (player name) */

View File

@ -19,6 +19,8 @@ export interface IGameFixes {
fixShotgunDispersion: boolean;
/** Remove items added by mods when the mod no longer exists - can fix dead profiles stuck at game load*/
removeModItemsFromProfile: boolean;
/** Fix issues that cause the game to not start due to inventory item issues */
fixProfileBreakingInventoryItemIssues: boolean;
}
export interface IServerFeatures {
autoInstallModDependencies: boolean;

View File

@ -36,15 +36,8 @@ export interface ILocationConfig extends IBaseConfig {
allowDuplicateItemsInStaticContainers: boolean;
/** Key: map, value: loose loot ids to ignore */
looseLootBlacklist: Record<string, string[]>;
}
export interface IContainerRandomistionSettings {
enabled: boolean;
/** What maps can use the container randomisation feature */
maps: Record<string, boolean>;
/** Some container types don't work when randomised */
containerTypesToNotRandomise: string[];
containerGroupMinSizeMultiplier: number;
containerGroupMaxSizeMultiplier: number;
/** Key: map, value: settings to control how long scav raids are*/
scavRaidTimeSettings: IScavRaidTimeSettings;
}
export interface IFixEmptyBotWavesSettings {
enabled: boolean;
@ -86,3 +79,30 @@ export interface LootMultiplier {
terminal: number;
town: number;
}
export interface IContainerRandomistionSettings {
enabled: boolean;
/** What maps can use the container randomisation feature */
maps: Record<string, boolean>;
/** Some container types don't work when randomised */
containerTypesToNotRandomise: string[];
containerGroupMinSizeMultiplier: number;
containerGroupMaxSizeMultiplier: number;
}
export interface IScavRaidTimeSettings {
settings: IScavRaidTimeConfigSettings;
maps: Record<string, IScavRaidTimeLocationSettings>;
}
export interface IScavRaidTimeConfigSettings {
trainArrivalDelayObservedSeconds: number;
}
export interface IScavRaidTimeLocationSettings {
/** Should loot be reduced by same percent length of raid is reduced by */
reduceLootByPercent: boolean;
minStaticLootPercent: number;
minDynamicLootPercent: number;
/** Chance raid time is reduced */
reducedChancePercent: number;
reductionPercentWeights: Record<string, number>;
/** Should bot waves be removed / spawn times be adjusted */
adjustWaves: boolean;
}

View File

@ -0,0 +1,8 @@
export interface IRaidChanges {
/** What percentage of dynamic loot should the map contain */
dynamicLootPercent: number;
/** What percentage of static loot should the map contain */
staticLootPercent: number;
/** How many seconds into the raid is the player simulated to spawn in at */
simulatedRaidStartSeconds: number;
}

View File

@ -1,6 +1,7 @@
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
import { IHideoutImprovement, Productive, TraderData, TraderInfo } from "@spt-aki/models/eft/common/tables/IBotBase";
import { IHideoutImprovement, Productive, TraderInfo } from "@spt-aki/models/eft/common/tables/IBotBase";
import { TraderData } from "@spt-aki/models/eft/itemEvent/IItemEventRouterBase";
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
@ -48,5 +49,5 @@ export declare class EventOutputHolder {
* Required as continuous productions don't reset and stay at 100% completion but client thinks it hasn't started
* @param productions Productions in a profile
*/
protected resetSptIsCompleteFlaggedCrafts(productions: Record<string, Productive>): void;
protected cleanUpCompleteCraftsInProfile(productions: Record<string, Productive>): void;
}

View File

@ -41,6 +41,11 @@ export declare class ProfileFixerService {
* @param pmcProfile profile to check and fix
*/
checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void;
/**
* Find issues in the scav profile data that may cause issues
* @param scavProfile profile to check and fix
*/
checkForAndFixScavProfileIssues(scavProfile: IPmcData): void;
protected addMissingGunStandContainerImprovements(pmcProfile: IPmcData): void;
protected ensureGunStandLevelsMatch(pmcProfile: IPmcData): void;
protected addHideoutAreaStashes(pmcProfile: IPmcData): void;
@ -67,9 +72,9 @@ export declare class ProfileFixerService {
* Adjust profile quest status and statusTimers object values
* quest.status is numeric e.g. 2
* quest.statusTimers keys are numeric as strings e.g. "2"
* @param pmcProfile profile to update
* @param profile profile to update
*/
protected updateProfileQuestDataValues(pmcProfile: IPmcData): void;
protected updateProfileQuestDataValues(profile: IPmcData): void;
protected addMissingRepeatableQuestsProperty(pmcProfile: IPmcData): void;
/**
* Some profiles have hideout maxed and therefore no improvements
@ -115,6 +120,11 @@ export declare class ProfileFixerService {
* @param pmcProfile Profile to check inventory of
*/
checkForOrphanedModdedItems(sessionId: string, fullProfile: IAkiProfile): void;
/**
* Attempt to fix common item issues that corrupt profiles
* @param pmcProfile Profile to check items of
*/
fixProfileBreakingInventoryItemIssues(pmcProfile: IPmcData): void;
/**
* Add `Improvements` object to hideout if missing - added in eft 13.0.21469
* @param pmcProfile profile to update

View File

@ -0,0 +1,60 @@
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
import { ILocationBase } from "@spt-aki/models/eft/common/ILocationBase";
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
import { ExtractChange, IGetRaidTimeResponse } from "@spt-aki/models/eft/game/IGetRaidTimeResponse";
import { ILocationConfig, IScavRaidTimeLocationSettings, LootMultiplier } from "@spt-aki/models/spt/config/ILocationConfig";
import { IRaidChanges } from "@spt-aki/models/spt/location/IRaidChanges";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
export declare class RaidTimeAdjustmentService {
protected logger: ILogger;
protected databaseServer: DatabaseServer;
protected randomUtil: RandomUtil;
protected weightedRandomHelper: WeightedRandomHelper;
protected applicationContext: ApplicationContext;
protected configServer: ConfigServer;
protected locationConfig: ILocationConfig;
constructor(logger: ILogger, databaseServer: DatabaseServer, randomUtil: RandomUtil, weightedRandomHelper: WeightedRandomHelper, applicationContext: ApplicationContext, configServer: ConfigServer);
/**
* Make alterations to the base map data passed in
* Loot multipliers/waves/wave start times
* @param raidAdjustments Changes to process on map
* @param mapBase Map to adjust
*/
makeAdjustmentsToMap(raidAdjustments: IRaidChanges, mapBase: ILocationBase): void;
/**
* Adjust the loot multiplier values passed in to be a % of their original value
* @param mapLootMultiplers Multiplers to adjust
* @param loosePercent Percent to change values to
*/
protected adjustLootMultipliers(mapLootMultiplers: LootMultiplier, loosePercent: number): void;
/**
* Adjust bot waves to act as if player spawned later
* @param mapBase map to adjust
* @param raidAdjustments Map adjustments
*/
protected adjustWaves(mapBase: ILocationBase, raidAdjustments: IRaidChanges): void;
/**
* Create a randomised adjustment to the raid based on map data in location.json
* @param sessionId Session id
* @param request Raid adjustment request
* @returns Response to send to client
*/
getRaidAdjustments(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse;
/**
* Get raid start time settings for specific map
* @param location Map Location e.g. bigmap
* @returns IScavRaidTimeLocationSettings
*/
protected getMapSettings(location: string): IScavRaidTimeLocationSettings;
/**
* Adjust exit times to handle scavs entering raids part-way through
* @param mapBase Map base file player is on
* @param newRaidTimeMinutes How long raid is in minutes
* @returns List of exit changes to send to client
*/
protected getExitAdjustments(mapBase: ILocationBase, newRaidTimeMinutes: number): ExtractChange[];
}

View File

@ -15,6 +15,13 @@ export declare class HttpResponseUtil {
* @returns
*/
noBody(data: any): any;
/**
* Game client needs server responses in a particular format
* @param data
* @param err
* @param errmsg
* @returns
*/
getBody<T>(data: T, err?: number, errmsg?: any): IGetBodyResponseData<T>;
getUnclearedBody(data: any, err?: number, errmsg?: any): string;
emptyResponse(): IGetBodyResponseData<string>;

View File

@ -111,6 +111,13 @@ export declare class RandomUtil {
getFloat(min: number, max: number): number;
getBool(): boolean;
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
*/
reduceValueByPercent(number: number, percentage: number): number;
/**
* Check if number passes a check out of 100
* @param chancePercent value check needs to be above

View File

@ -8,6 +8,7 @@ import { IGameEmptyCrcRequestData } from "@spt-aki/models/eft/game/IGameEmptyCrc
import { IGameKeepAliveResponse } from "@spt-aki/models/eft/game/IGameKeepAliveResponse";
import { IGameLogoutResponseData } from "@spt-aki/models/eft/game/IGameLogoutResponseData";
import { IGameStartResponse } from "@spt-aki/models/eft/game/IGameStartResponse";
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
import { IReportNicknameRequestData } from "@spt-aki/models/eft/game/IReportNicknameRequestData";
import { IServerDetails } from "@spt-aki/models/eft/game/IServerDetails";
import { IVersionValidateRequestData } from "@spt-aki/models/eft/game/IVersionValidateRequestData";
@ -68,5 +69,10 @@ declare class GameCallbacks implements OnLoad {
*/
getVersion(url: string, info: IEmptyRequestData, sessionID: string): string;
reportNickname(url: string, info: IReportNicknameRequestData, sessionID: string): INullResponseData;
/**
* Handle singleplayer/settings/getRaidTime
* @returns string
*/
getRaidTime(url: string, request: IGetRaidTimeRequest, sessionID: string): any;
}
export { GameCallbacks };

View File

@ -10,11 +10,12 @@ export declare class ApplicationContext {
*
* const activePlayerSessionId = this.applicationContext.getLatestValue(ContextVariableType.SESSION_ID).getValue<string>();
*
* const matchInfo = this.applicationContext.getLatestValue(ContextVariableType.MATCH_INFO).getValue<IStartOfflineRaidRequestData>();
* const matchInfo = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION).getValue<IGetRaidConfigurationRequestData>();
* @param type
* @returns
*/
getLatestValue(type: ContextVariableType): ContextVariable;
getValues(type: ContextVariableType): ContextVariable[];
addValue(type: ContextVariableType, value: any): void;
clearValues(type: ContextVariableType): void;
}

View File

@ -6,5 +6,6 @@ export declare enum ContextVariableType {
/** Timestamp when client first connected */
CLIENT_START_TIMESTAMP = 2,
/** When player is loading into map and loot is requested */
REGISTER_PLAYER_REQUEST = 3
REGISTER_PLAYER_REQUEST = 3,
RAID_ADJUSTMENTS = 4
}

View File

@ -9,6 +9,8 @@ import { ICheckVersionResponse } from "@spt-aki/models/eft/game/ICheckVersionRes
import { ICurrentGroupResponse } from "@spt-aki/models/eft/game/ICurrentGroupResponse";
import { IGameConfigResponse } from "@spt-aki/models/eft/game/IGameConfigResponse";
import { IGameKeepAliveResponse } from "@spt-aki/models/eft/game/IGameKeepAliveResponse";
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
import { IGetRaidTimeResponse } from "@spt-aki/models/eft/game/IGetRaidTimeResponse";
import { IServerDetails } from "@spt-aki/models/eft/game/IServerDetails";
import { IAkiProfile } from "@spt-aki/models/eft/profile/IAkiProfile";
import { ICoreConfig } from "@spt-aki/models/spt/config/ICoreConfig";
@ -26,7 +28,9 @@ import { ItemBaseClassService } from "@spt-aki/services/ItemBaseClassService";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { OpenZoneService } from "@spt-aki/services/OpenZoneService";
import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService";
import { RaidTimeAdjustmentService } from "@spt-aki/services/RaidTimeAdjustmentService";
import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
import { HashUtil } from "@spt-aki/utils/HashUtil";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
@ -35,6 +39,7 @@ export declare class GameController {
protected databaseServer: DatabaseServer;
protected jsonUtil: JsonUtil;
protected timeUtil: TimeUtil;
protected hashUtil: HashUtil;
protected preAkiModLoader: PreAkiModLoader;
protected httpServerHelper: HttpServerHelper;
protected randomUtil: RandomUtil;
@ -47,6 +52,7 @@ export declare class GameController {
protected seasonalEventService: SeasonalEventService;
protected itemBaseClassService: ItemBaseClassService;
protected giftService: GiftService;
protected raidTimeAdjustmentService: RaidTimeAdjustmentService;
protected applicationContext: ApplicationContext;
protected configServer: ConfigServer;
protected httpConfig: IHttpConfig;
@ -55,7 +61,7 @@ export declare class GameController {
protected ragfairConfig: IRagfairConfig;
protected pmcConfig: IPmcConfig;
protected lootConfig: ILootConfig;
constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer);
constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, raidTimeAdjustmentService: RaidTimeAdjustmentService, applicationContext: ApplicationContext, configServer: ConfigServer);
load(): void;
/**
* Handle client/game/start
@ -90,6 +96,10 @@ export declare class GameController {
* Handle client/game/keepalive
*/
getKeepAlive(sessionId: string): IGameKeepAliveResponse;
/**
* Handle singleplayer/settings/getRaidTime
*/
getRaidTime(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse;
/**
* BSG have two values for shotgun dispersion, we make sure both have the same value
*/

View File

@ -101,7 +101,7 @@ export declare class HideoutController {
*/
protected addUpdateInventoryItemToProfile(pmcData: IPmcData, dbHideoutData: IHideoutArea, hideoutStage: Stage): void;
/**
* @param output Objet to send to client
* @param output Object to send to client
* @param sessionID Session/player id
* @param areaType Hideout area that had stash added
* @param hideoutDbData Hideout area that caused addition of stash

View File

@ -95,9 +95,14 @@ export declare class InraidController {
/**
* Does provided profile contain any condition counters
* @param profile Profile to check for condition counters
* @returns
* @returns Profile has condition counters
*/
protected profileHasConditionCounters(profile: IPmcData): boolean;
/**
* Scav quest progress isnt transferred automatically from scav to pmc, we do this manually
* @param scavProfile Scav profile with quest progress post-raid
* @param pmcProfile Server pmc profile to copy scav quest progress into
*/
protected migrateScavQuestProgressToPmcProfile(scavProfile: IPmcData, pmcProfile: IPmcData): void;
/**
* Is the player dead after a raid - dead is anything other than "survived" / "runner"

View File

@ -1,3 +1,4 @@
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
import { LocationGenerator } from "@spt-aki/generators/LocationGenerator";
import { LootGenerator } from "@spt-aki/generators/LootGenerator";
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
@ -13,6 +14,7 @@ import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { RaidTimeAdjustmentService } from "@spt-aki/services/RaidTimeAdjustmentService";
import { HashUtil } from "@spt-aki/utils/HashUtil";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
@ -25,13 +27,15 @@ export declare class LocationController {
protected logger: ILogger;
protected locationGenerator: LocationGenerator;
protected localisationService: LocalisationService;
protected raidTimeAdjustmentService: RaidTimeAdjustmentService;
protected lootGenerator: LootGenerator;
protected databaseServer: DatabaseServer;
protected timeUtil: TimeUtil;
protected configServer: ConfigServer;
protected applicationContext: ApplicationContext;
protected airdropConfig: IAirdropConfig;
protected locationConfig: ILocationConfig;
constructor(jsonUtil: JsonUtil, hashUtil: HashUtil, randomUtil: RandomUtil, weightedRandomHelper: WeightedRandomHelper, logger: ILogger, locationGenerator: LocationGenerator, localisationService: LocalisationService, lootGenerator: LootGenerator, databaseServer: DatabaseServer, timeUtil: TimeUtil, configServer: ConfigServer);
constructor(jsonUtil: JsonUtil, hashUtil: HashUtil, randomUtil: RandomUtil, weightedRandomHelper: WeightedRandomHelper, logger: ILogger, locationGenerator: LocationGenerator, localisationService: LocalisationService, raidTimeAdjustmentService: RaidTimeAdjustmentService, lootGenerator: LootGenerator, databaseServer: DatabaseServer, timeUtil: TimeUtil, configServer: ConfigServer, applicationContext: ApplicationContext);
/**
* Handle client/location/getLocalloot
* Get a location (map) with generated loot data

View File

@ -82,7 +82,7 @@ export declare class QuestController {
* @param pmcData Profile to update
* @param acceptedQuest Quest accepted
* @param sessionID Session id
* @returns client response
* @returns Client response
*/
acceptQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse;
/**

View File

@ -41,7 +41,7 @@ declare class TradeController {
/** Handle RagFairBuyOffer event */
confirmRagfairTrading(pmcData: IPmcData, body: IProcessRagfairTradeRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle SellAllFromSavage event */
sellScavItemsToFence(pmcData: IPmcData, body: ISellScavItemsToFenceRequestData, sessionId: string): IItemEventRouterResponse;
sellScavItemsToFence(pmcData: IPmcData, request: ISellScavItemsToFenceRequestData, sessionId: string): IItemEventRouterResponse;
/**
* Sell all sellable items to a trader from inventory
* WILL DELETE ITEMS FROM INVENTORY + CHILDREN OF ITEMS SOLD

View File

@ -73,12 +73,13 @@ export declare class BotWeaponGenerator {
*/
generateWeaponByTpl(sessionId: string, weaponTpl: string, equipmentSlot: string, botTemplateInventory: Inventory, weaponParentId: string, modChances: ModsChances, botRole: string, isPmc: boolean, botLevel: number): GenerateWeaponResult;
/**
* Insert a cartridge into a weapon
* Insert a cartridge(s) into a weapon
* Handles all chambers - patron_in_weapon, patron_in_weapon_000 etc
* @param weaponWithModsArray Weapon and mods
* @param ammoTpl Cartridge to add to weapon
* @param desiredSlotId name of slot, e.g. patron_in_weapon
* @param chamberSlotIds name of slots to create or add ammo to
*/
protected addCartridgeToChamber(weaponWithModsArray: Item[], ammoTpl: string, desiredSlotId: string): void;
protected addCartridgeToChamber(weaponWithModsArray: Item[], ammoTpl: string, chamberSlotIds: string[]): void;
/**
* Create array with weapon base as only element and
* add additional properties based on weapon type

View File

@ -121,11 +121,11 @@ export declare class LocationGenerator {
generateDynamicLoot(dynamicLootDist: ILooseLoot, staticAmmoDist: Record<string, IStaticAmmoDetails[]>, locationName: string): SpawnpointTemplate[];
/**
* Add forced spawn point loot into loot parameter array
* @param loot array to add forced loot to
* @param forcedSpawnPoints forced loot to add
* @param name of map currently generating forced loot for
* @param lootLocationTemplates array to add forced loot spawn locations to
* @param forcedSpawnPoints forced Forced loot locations that must be added
* @param locationName Name of map currently having force loot created for
*/
protected addForcedLoot(loot: SpawnpointTemplate[], forcedSpawnPoints: SpawnpointsForced[], locationName: string): void;
protected addForcedLoot(lootLocationTemplates: SpawnpointTemplate[], forcedSpawnPoints: SpawnpointsForced[], locationName: string): void;
/**
* Create array of item (with child items) and return
* @param chosenComposedKey Key we want to look up items for

View File

@ -2,15 +2,24 @@ import { IInventoryMagGen } from "@spt-aki/generators/weapongen/IInventoryMagGen
import { InventoryMagGen } from "@spt-aki/generators/weapongen/InventoryMagGen";
import { BotWeaponGeneratorHelper } from "@spt-aki/helpers/BotWeaponGeneratorHelper";
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
export declare class ExternalInventoryMagGen implements IInventoryMagGen {
protected logger: ILogger;
protected itemHelper: ItemHelper;
protected localisationService: LocalisationService;
protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper;
constructor(logger: ILogger, itemHelper: ItemHelper, localisationService: LocalisationService, botWeaponGeneratorHelper: BotWeaponGeneratorHelper);
protected randomUtil: RandomUtil;
constructor(logger: ILogger, itemHelper: ItemHelper, localisationService: LocalisationService, botWeaponGeneratorHelper: BotWeaponGeneratorHelper, randomUtil: RandomUtil);
getPriority(): number;
canHandleInventoryMagGen(inventoryMagGen: InventoryMagGen): boolean;
process(inventoryMagGen: InventoryMagGen): void;
/**
* Get a random compatible external magazine for a weapon, excluses internal magazines from possible pool
* @param weaponTpl Weapon to get mag for
* @returns tpl of magazine
*/
protected getRandomExternalMagazineForInternalMagazineGun(weaponTpl: string, magazineBlacklist: string[]): ITemplateItem;
}

View File

@ -1,4 +1,5 @@
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
declare class LookupItem<T, I> {
readonly byId: Map<string, T>;
readonly byParent: Map<string, I[]>;
@ -11,9 +12,10 @@ export declare class LookupCollection {
}
export declare class HandbookHelper {
protected databaseServer: DatabaseServer;
protected jsonUtil: JsonUtil;
protected lookupCacheGenerated: boolean;
protected handbookPriceCache: LookupCollection;
constructor(databaseServer: DatabaseServer);
constructor(databaseServer: DatabaseServer, jsonUtil: JsonUtil);
/**
* Create an in-memory cache of all items with associated handbook price in handbookPriceCache class
*/

View File

@ -15,6 +15,7 @@ import { SaveServer } from "@spt-aki/servers/SaveServer";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { ProfileHelper } from "./ProfileHelper";
export declare class InRaidHelper {
protected logger: ILogger;
protected saveServer: SaveServer;
@ -22,6 +23,7 @@ export declare class InRaidHelper {
protected itemHelper: ItemHelper;
protected databaseServer: DatabaseServer;
protected inventoryHelper: InventoryHelper;
protected profileHelper: ProfileHelper;
protected questHelper: QuestHelper;
protected paymentHelper: PaymentHelper;
protected localisationService: LocalisationService;
@ -29,7 +31,7 @@ export declare class InRaidHelper {
protected configServer: ConfigServer;
protected lostOnDeathConfig: ILostOnDeathConfig;
protected inRaidConfig: IInRaidConfig;
constructor(logger: ILogger, saveServer: SaveServer, jsonUtil: JsonUtil, itemHelper: ItemHelper, databaseServer: DatabaseServer, inventoryHelper: InventoryHelper, questHelper: QuestHelper, paymentHelper: PaymentHelper, localisationService: LocalisationService, profileFixerService: ProfileFixerService, configServer: ConfigServer);
constructor(logger: ILogger, saveServer: SaveServer, jsonUtil: JsonUtil, itemHelper: ItemHelper, databaseServer: DatabaseServer, inventoryHelper: InventoryHelper, profileHelper: ProfileHelper, questHelper: QuestHelper, paymentHelper: PaymentHelper, localisationService: LocalisationService, profileFixerService: ProfileFixerService, configServer: ConfigServer);
/**
* Lookup quest item loss from lostOnDeath config
* @returns True if items should be removed from inventory
@ -64,16 +66,36 @@ export declare class InRaidHelper {
* @param sessionID Session id
* @returns Reset profile object
*/
updateProfileBaseStats(profileData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionID: string): IPmcData;
updateProfileBaseStats(profileData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionID: string): void;
/**
* Look for quests not are now status = fail that were not failed pre-raid and run the failQuest() function
* Reset the skill points earned in a raid to 0, ready for next raid
* @param profile Profile to update
*/
protected resetSkillPointsEarnedDuringRaid(profile: IPmcData): void;
/** Check counters are correct in profile */
protected validateBackendCounters(saveProgressRequest: ISaveProgressRequestData, profileData: IPmcData): void;
/**
* Update various serverPMC profile values; quests/limb hp/trader standing with values post-raic
* @param pmcData Server PMC profile
* @param saveProgressRequest Post-raid request data
* @param sessionId Session id
*/
updatePmcProfileDataPostRaid(pmcData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionId: string): void;
/**
* Update scav quest values on server profile with updated values post-raid
* @param scavData Server scav profile
* @param saveProgressRequest Post-raid request data
* @param sessionId Session id
*/
updateScavProfileDataPostRaid(scavData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionId: string): void;
/**
* Look for quests with status = fail that were not failed pre-raid and run the failQuest() function
* @param sessionId Player id
* @param pmcData Player profile
* @param preRaidQuests Quests prior to starting raid
* @param postRaidQuests Quest after raid
* @param postRaidProfile Profile sent by client
*/
protected processFailedQuests(sessionId: string, pmcData: IPmcData, preRaidQuests: IQuestStatus[], postRaidQuests: IQuestStatus[]): void;
protected resetSkillPointsEarnedDuringRaid(profile: IPmcData): void;
protected processFailedQuests(sessionId: string, pmcData: IPmcData, preRaidQuests: IQuestStatus[], postRaidProfile: IPostRaidPmcData): void;
/**
* Take body part effects from client profile and apply to server profile
* @param saveProgressRequest post-raid request

View File

@ -323,7 +323,7 @@ declare class ItemHelper {
* Chose a randomly weighted cartridge that fits
* @param caliber Desired caliber
* @param staticAmmoDist Cartridges and thier weights
* @returns Tpl of cartrdige
* @returns Tpl of cartridge
*/
protected drawAmmoTpl(caliber: string, staticAmmoDist: Record<string, IStaticAmmoDetails[]>): string;
/**

View File

@ -206,16 +206,23 @@ export declare class QuestHelper {
* @param questId Id of the quest to alter the status of
*/
updateQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void;
/**
* Resets a quests values back to its chosen state
* @param pmcData Profile to update
* @param newQuestState New state the quest should be in
* @param questId Id of the quest to alter the status of
*/
resetQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void;
/**
* Give player quest rewards - Skills/exp/trader standing/items/assort unlocks - Returns reward items player earned
* @param pmcData Player profile
* @param profileData Player profile (scav or pmc)
* @param questId questId of quest to get rewards for
* @param state State of the quest to get rewards for
* @param sessionId Session id
* @param questResponse Response to send back to client
* @returns Array of reward objects
*/
applyQuestReward(pmcData: IPmcData, questId: string, state: QuestStatus, sessionId: string, questResponse: IItemEventRouterResponse): Reward[];
applyQuestReward(profileData: IPmcData, questId: string, state: QuestStatus, sessionId: string, questResponse: IItemEventRouterResponse): Reward[];
/**
* WIP - Find hideout craft id and add to unlockedProductionRecipe array in player profile
* also update client response recipeUnlocked array with craft id

View File

@ -25,7 +25,7 @@ export declare class WeightedRandomHelper {
* @param {number[]} weights
* @returns {{item: any, index: number}}
*/
weightedRandom(items: string | any[], weights: string | any[]): {
weightedRandom(items: any[], weights: any[]): {
item: any;
index: number;
};

View File

@ -309,6 +309,8 @@ export interface Productive {
sptIsScavCase?: boolean;
/** Some crafts are always inProgress, but need to be reset, e.g. water collector */
sptIsComplete?: boolean;
/** Is the craft a Continuous, e.g bitcoins/water collector */
sptIsContinuous?: boolean;
}
export interface Production extends Productive {
RecipeId: string;
@ -361,7 +363,7 @@ export interface IQuestStatus {
startTime: number;
status: QuestStatus;
statusTimers?: Record<string, number>;
/** SPT specific property */
/** Property does not exist in live profile data, but is used by ProfileChanges.questsStatus when sent to client*/
completedConditions?: string[];
availableAfter?: number;
}
@ -373,14 +375,6 @@ export interface TraderInfo {
unlocked: boolean;
disabled: boolean;
}
/** This object is sent to the client as part of traderRelations */
export interface TraderData {
salesSum: number;
standing: number;
loyalty: number;
unlocked: boolean;
disabled: boolean;
}
export interface RagfairInfo {
rating: number;
isRatingGrowing: boolean;

View File

@ -0,0 +1,4 @@
export interface IGetRaidTimeRequest {
Side: string;
Location: string;
}

View File

@ -0,0 +1,12 @@
export interface IGetRaidTimeResponse {
RaidTimeMinutes: number;
NewSurviveTimeSeconds: number;
OriginalSurvivalTimeSeconds: number;
ExitChanges: ExtractChange[];
}
export interface ExtractChange {
Name: string;
MinTime?: number;
MaxTime?: number;
Chance?: number;
}

View File

@ -1,4 +1,4 @@
import { Health, IQuestStatus, Productive, Skills, TraderData } from "@spt-aki/models/eft/common/tables/IBotBase";
import { Health, IQuestStatus, Productive, Skills } from "@spt-aki/models/eft/common/tables/IBotBase";
import { Item, Upd } from "@spt-aki/models/eft/common/tables/IItem";
import { IQuest } from "@spt-aki/models/eft/common/tables/IQuest";
import { IPmcDataRepeatableQuest } from "@spt-aki/models/eft/common/tables/IRepeatableQuests";
@ -62,6 +62,14 @@ export interface Improvement {
completed: boolean;
improveCompleteTimestamp: number;
}
/** Related to TraderInfo */
export interface TraderData {
salesSum: number;
standing: number;
loyalty: number;
unlocked: boolean;
disabled: boolean;
}
export interface Product {
_id: string;
_tpl?: string;

View File

@ -54,6 +54,7 @@ export declare enum BaseClasses {
GRENADE_LAUNCHER = "5447bedf4bdc2d87278b4568",
SPECIAL_WEAPON = "5447bee84bdc2dc3278b4569",
SPEC_ITEM = "5447e0e74bdc2d3c308b4567",
SPRING_DRIVEN_CYLINDER = "627a137bf21bc425b06ab944",
KNIFE = "5447e1d04bdc2dff2f8b4567",
AMMO = "5485a8684bdc2da71d8b4567",
AMMO_BOX = "543be5cb4bdc2deb348b4568",

View File

@ -1,4 +1,6 @@
export declare enum ItemAddedResult {
UNKNOWN = -1,
SUCCESS = 1,
NO_SPACE = 2
NO_SPACE = 2,
NO_CONTAINERS = 3
}

View File

@ -25,6 +25,8 @@ export interface IBotConfig extends IBaseConfig {
showTypeInNickname: boolean;
/** What ai brain should a normal scav use per map */
assaultBrainType: Record<string, Record<string, number>>;
/** What ai brain should a player scav use per map */
playerScavBrainType: Record<string, Record<string, number>>;
/** Max number of bots that can be spawned in a raid at any one time */
maxBotCap: Record<string, number>;
/** Chance scav has fake pscav name e.g. Scav name (player name) */

View File

@ -19,6 +19,8 @@ export interface IGameFixes {
fixShotgunDispersion: boolean;
/** Remove items added by mods when the mod no longer exists - can fix dead profiles stuck at game load*/
removeModItemsFromProfile: boolean;
/** Fix issues that cause the game to not start due to inventory item issues */
fixProfileBreakingInventoryItemIssues: boolean;
}
export interface IServerFeatures {
autoInstallModDependencies: boolean;

View File

@ -36,15 +36,8 @@ export interface ILocationConfig extends IBaseConfig {
allowDuplicateItemsInStaticContainers: boolean;
/** Key: map, value: loose loot ids to ignore */
looseLootBlacklist: Record<string, string[]>;
}
export interface IContainerRandomistionSettings {
enabled: boolean;
/** What maps can use the container randomisation feature */
maps: Record<string, boolean>;
/** Some container types don't work when randomised */
containerTypesToNotRandomise: string[];
containerGroupMinSizeMultiplier: number;
containerGroupMaxSizeMultiplier: number;
/** Key: map, value: settings to control how long scav raids are*/
scavRaidTimeSettings: IScavRaidTimeSettings;
}
export interface IFixEmptyBotWavesSettings {
enabled: boolean;
@ -86,3 +79,30 @@ export interface LootMultiplier {
terminal: number;
town: number;
}
export interface IContainerRandomistionSettings {
enabled: boolean;
/** What maps can use the container randomisation feature */
maps: Record<string, boolean>;
/** Some container types don't work when randomised */
containerTypesToNotRandomise: string[];
containerGroupMinSizeMultiplier: number;
containerGroupMaxSizeMultiplier: number;
}
export interface IScavRaidTimeSettings {
settings: IScavRaidTimeConfigSettings;
maps: Record<string, IScavRaidTimeLocationSettings>;
}
export interface IScavRaidTimeConfigSettings {
trainArrivalDelayObservedSeconds: number;
}
export interface IScavRaidTimeLocationSettings {
/** Should loot be reduced by same percent length of raid is reduced by */
reduceLootByPercent: boolean;
minStaticLootPercent: number;
minDynamicLootPercent: number;
/** Chance raid time is reduced */
reducedChancePercent: number;
reductionPercentWeights: Record<string, number>;
/** Should bot waves be removed / spawn times be adjusted */
adjustWaves: boolean;
}

View File

@ -0,0 +1,8 @@
export interface IRaidChanges {
/** What percentage of dynamic loot should the map contain */
dynamicLootPercent: number;
/** What percentage of static loot should the map contain */
staticLootPercent: number;
/** How many seconds into the raid is the player simulated to spawn in at */
simulatedRaidStartSeconds: number;
}

View File

@ -1,6 +1,7 @@
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
import { IHideoutImprovement, Productive, TraderData, TraderInfo } from "@spt-aki/models/eft/common/tables/IBotBase";
import { IHideoutImprovement, Productive, TraderInfo } from "@spt-aki/models/eft/common/tables/IBotBase";
import { TraderData } from "@spt-aki/models/eft/itemEvent/IItemEventRouterBase";
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
@ -48,5 +49,5 @@ export declare class EventOutputHolder {
* Required as continuous productions don't reset and stay at 100% completion but client thinks it hasn't started
* @param productions Productions in a profile
*/
protected resetSptIsCompleteFlaggedCrafts(productions: Record<string, Productive>): void;
protected cleanUpCompleteCraftsInProfile(productions: Record<string, Productive>): void;
}

View File

@ -41,6 +41,11 @@ export declare class ProfileFixerService {
* @param pmcProfile profile to check and fix
*/
checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void;
/**
* Find issues in the scav profile data that may cause issues
* @param scavProfile profile to check and fix
*/
checkForAndFixScavProfileIssues(scavProfile: IPmcData): void;
protected addMissingGunStandContainerImprovements(pmcProfile: IPmcData): void;
protected ensureGunStandLevelsMatch(pmcProfile: IPmcData): void;
protected addHideoutAreaStashes(pmcProfile: IPmcData): void;
@ -67,9 +72,9 @@ export declare class ProfileFixerService {
* Adjust profile quest status and statusTimers object values
* quest.status is numeric e.g. 2
* quest.statusTimers keys are numeric as strings e.g. "2"
* @param pmcProfile profile to update
* @param profile profile to update
*/
protected updateProfileQuestDataValues(pmcProfile: IPmcData): void;
protected updateProfileQuestDataValues(profile: IPmcData): void;
protected addMissingRepeatableQuestsProperty(pmcProfile: IPmcData): void;
/**
* Some profiles have hideout maxed and therefore no improvements
@ -115,6 +120,11 @@ export declare class ProfileFixerService {
* @param pmcProfile Profile to check inventory of
*/
checkForOrphanedModdedItems(sessionId: string, fullProfile: IAkiProfile): void;
/**
* Attempt to fix common item issues that corrupt profiles
* @param pmcProfile Profile to check items of
*/
fixProfileBreakingInventoryItemIssues(pmcProfile: IPmcData): void;
/**
* Add `Improvements` object to hideout if missing - added in eft 13.0.21469
* @param pmcProfile profile to update

View File

@ -0,0 +1,60 @@
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
import { ILocationBase } from "@spt-aki/models/eft/common/ILocationBase";
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
import { ExtractChange, IGetRaidTimeResponse } from "@spt-aki/models/eft/game/IGetRaidTimeResponse";
import { ILocationConfig, IScavRaidTimeLocationSettings, LootMultiplier } from "@spt-aki/models/spt/config/ILocationConfig";
import { IRaidChanges } from "@spt-aki/models/spt/location/IRaidChanges";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
export declare class RaidTimeAdjustmentService {
protected logger: ILogger;
protected databaseServer: DatabaseServer;
protected randomUtil: RandomUtil;
protected weightedRandomHelper: WeightedRandomHelper;
protected applicationContext: ApplicationContext;
protected configServer: ConfigServer;
protected locationConfig: ILocationConfig;
constructor(logger: ILogger, databaseServer: DatabaseServer, randomUtil: RandomUtil, weightedRandomHelper: WeightedRandomHelper, applicationContext: ApplicationContext, configServer: ConfigServer);
/**
* Make alterations to the base map data passed in
* Loot multipliers/waves/wave start times
* @param raidAdjustments Changes to process on map
* @param mapBase Map to adjust
*/
makeAdjustmentsToMap(raidAdjustments: IRaidChanges, mapBase: ILocationBase): void;
/**
* Adjust the loot multiplier values passed in to be a % of their original value
* @param mapLootMultiplers Multiplers to adjust
* @param loosePercent Percent to change values to
*/
protected adjustLootMultipliers(mapLootMultiplers: LootMultiplier, loosePercent: number): void;
/**
* Adjust bot waves to act as if player spawned later
* @param mapBase map to adjust
* @param raidAdjustments Map adjustments
*/
protected adjustWaves(mapBase: ILocationBase, raidAdjustments: IRaidChanges): void;
/**
* Create a randomised adjustment to the raid based on map data in location.json
* @param sessionId Session id
* @param request Raid adjustment request
* @returns Response to send to client
*/
getRaidAdjustments(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse;
/**
* Get raid start time settings for specific map
* @param location Map Location e.g. bigmap
* @returns IScavRaidTimeLocationSettings
*/
protected getMapSettings(location: string): IScavRaidTimeLocationSettings;
/**
* Adjust exit times to handle scavs entering raids part-way through
* @param mapBase Map base file player is on
* @param newRaidTimeMinutes How long raid is in minutes
* @returns List of exit changes to send to client
*/
protected getExitAdjustments(mapBase: ILocationBase, newRaidTimeMinutes: number): ExtractChange[];
}

View File

@ -15,6 +15,13 @@ export declare class HttpResponseUtil {
* @returns
*/
noBody(data: any): any;
/**
* Game client needs server responses in a particular format
* @param data
* @param err
* @param errmsg
* @returns
*/
getBody<T>(data: T, err?: number, errmsg?: any): IGetBodyResponseData<T>;
getUnclearedBody(data: any, err?: number, errmsg?: any): string;
emptyResponse(): IGetBodyResponseData<string>;

View File

@ -111,6 +111,13 @@ export declare class RandomUtil {
getFloat(min: number, max: number): number;
getBool(): boolean;
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
*/
reduceValueByPercent(number: number, percentage: number): number;
/**
* Check if number passes a check out of 100
* @param chancePercent value check needs to be above

View File

@ -8,6 +8,7 @@ import { IGameEmptyCrcRequestData } from "@spt-aki/models/eft/game/IGameEmptyCrc
import { IGameKeepAliveResponse } from "@spt-aki/models/eft/game/IGameKeepAliveResponse";
import { IGameLogoutResponseData } from "@spt-aki/models/eft/game/IGameLogoutResponseData";
import { IGameStartResponse } from "@spt-aki/models/eft/game/IGameStartResponse";
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
import { IReportNicknameRequestData } from "@spt-aki/models/eft/game/IReportNicknameRequestData";
import { IServerDetails } from "@spt-aki/models/eft/game/IServerDetails";
import { IVersionValidateRequestData } from "@spt-aki/models/eft/game/IVersionValidateRequestData";
@ -68,5 +69,10 @@ declare class GameCallbacks implements OnLoad {
*/
getVersion(url: string, info: IEmptyRequestData, sessionID: string): string;
reportNickname(url: string, info: IReportNicknameRequestData, sessionID: string): INullResponseData;
/**
* Handle singleplayer/settings/getRaidTime
* @returns string
*/
getRaidTime(url: string, request: IGetRaidTimeRequest, sessionID: string): any;
}
export { GameCallbacks };

View File

@ -10,11 +10,12 @@ export declare class ApplicationContext {
*
* const activePlayerSessionId = this.applicationContext.getLatestValue(ContextVariableType.SESSION_ID).getValue<string>();
*
* const matchInfo = this.applicationContext.getLatestValue(ContextVariableType.MATCH_INFO).getValue<IStartOfflineRaidRequestData>();
* const matchInfo = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION).getValue<IGetRaidConfigurationRequestData>();
* @param type
* @returns
*/
getLatestValue(type: ContextVariableType): ContextVariable;
getValues(type: ContextVariableType): ContextVariable[];
addValue(type: ContextVariableType, value: any): void;
clearValues(type: ContextVariableType): void;
}

View File

@ -6,5 +6,6 @@ export declare enum ContextVariableType {
/** Timestamp when client first connected */
CLIENT_START_TIMESTAMP = 2,
/** When player is loading into map and loot is requested */
REGISTER_PLAYER_REQUEST = 3
REGISTER_PLAYER_REQUEST = 3,
RAID_ADJUSTMENTS = 4
}

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