0
0
mirror of https://github.com/sp-tarkov/server.git synced 2025-02-13 07:50:45 -05:00

Removed all null references in favor of undefined (!354)

Co-authored-by: clodan <clodan@clodan.com>
Reviewed-on: SPT/Server#354
Co-authored-by: Alex <clodan@noreply.dev.sp-tarkov.com>
Co-committed-by: Alex <clodan@noreply.dev.sp-tarkov.com>
This commit is contained in:
Alex 2024-05-27 20:06:07 +00:00 committed by chomp
parent d5496dcc34
commit 173a726f33
57 changed files with 357 additions and 354 deletions

View File

@ -91,12 +91,12 @@ export class ProfileCallbacks
if (output === "taken")
{
return this.httpResponse.getBody(null, 255, "The nickname is already in use");
return this.httpResponse.getBody(undefined, 255, "The nickname is already in use");
}
if (output === "tooshort")
{
return this.httpResponse.getBody(null, 1, "The nickname is too short");
return this.httpResponse.getBody(undefined, 1, "The nickname is too short");
}
return this.httpResponse.getBody({ status: 0, nicknamechangedate: this.timeUtil.getTimestamp() });
@ -115,12 +115,12 @@ export class ProfileCallbacks
if (output === "taken")
{
return this.httpResponse.getBody(null, 255, "225 - ");
return this.httpResponse.getBody(undefined, 255, "225 - ");
}
if (output === "tooshort")
{
return this.httpResponse.getBody(null, 256, "256 - ");
return this.httpResponse.getBody(undefined, 256, "256 - ");
}
return this.httpResponse.getBody({ status: "ok" });

View File

@ -529,7 +529,7 @@ export class HideoutController
const request: IAddItemDirectRequest = {
itemWithModsToAdd: [itemToReturn],
foundInRaid: !!itemToReturn.upd?.SpawnedInSession,
callback: null,
callback: undefined,
useSortingTable: false,
};
@ -824,7 +824,7 @@ export class HideoutController
let prodId: string;
for (const [productionId, production] of productionDict)
{
// Skip null production objects
// Skip undefined production objects
if (!production)
{
continue;
@ -981,7 +981,7 @@ export class HideoutController
itemsWithModsToAdd: [toolItem],
foundInRaid: toolItem[0].upd?.SpawnedInSession ?? false,
useSortingTable: false,
callback: null,
callback: undefined,
};
this.inventoryHelper.addItemsToStash(sessionID, addToolsRequest, pmcData, output);
@ -996,7 +996,7 @@ export class HideoutController
itemsWithModsToAdd: itemAndChildrenToSendToPlayer,
foundInRaid: true,
useSortingTable: false,
callback: null,
callback: undefined,
};
this.inventoryHelper.addItemsToStash(sessionID, addItemsRequest, pmcData, output);
if (output.warnings.length > 0)
@ -1118,7 +1118,7 @@ export class HideoutController
const addItemsRequest: IAddItemsDirectRequest = {
itemsWithModsToAdd: scavCaseRewards,
foundInRaid: true,
callback: null,
callback: undefined,
useSortingTable: false,
};
@ -1320,7 +1320,7 @@ export class HideoutController
}
// Null out production data so client gets informed when response send back
pmcData.Hideout.Production[request.recipeId] = null;
pmcData.Hideout.Production[request.recipeId] = undefined;
// TODO - handle timestamp somehow?

View File

@ -628,14 +628,14 @@ export class InsuranceController
*
* @param traderId The ID of the trader who insured the item.
* @param insuredItem Optional. The item to roll for. Only used for logging.
* @returns true if the insured item should be removed from inventory, false otherwise, or null on error.
* @returns true if the insured item should be removed from inventory, false otherwise, or undefined on error.
*/
protected rollForDelete(traderId: string, insuredItem?: Item): boolean | null
protected rollForDelete(traderId: string, insuredItem?: Item): boolean | undefined
{
const trader = this.traderHelper.getTraderById(traderId);
if (!trader)
{
return null;
return undefined;
}
const maxRoll = 9999;

View File

@ -345,7 +345,7 @@ export class InventoryController
const sourceItem = inventoryItems.from.find((item) => item._id === body.item);
const destinationItem = inventoryItems.to.find((item) => item._id === body.with);
if (sourceItem === null)
if (!sourceItem)
{
const errorMessage = `Unable to transfer stack, cannot find source: ${body.item}`;
this.logger.error(errorMessage);
@ -355,7 +355,7 @@ export class InventoryController
return output;
}
if (destinationItem === null)
if (!destinationItem)
{
const errorMessage = `Unable to transfer stack, cannot find destination: ${body.with} `;
this.logger.error(errorMessage);
@ -939,7 +939,7 @@ export class InventoryController
const addItemsRequest: IAddItemsDirectRequest = {
itemsWithModsToAdd: rewards,
foundInRaid: foundInRaid,
callback: null,
callback: undefined,
useSortingTable: true,
};
this.inventoryHelper.addItemsToStash(sessionID, addItemsRequest, pmcData, output);

View File

@ -92,9 +92,9 @@ export class MatchController
location: "TODO get location",
raidMode: "Online",
mode: "deathmatch",
shortId: null,
shortId: undefined,
// eslint-disable-next-line @typescript-eslint/naming-convention
additional_info: null,
additional_info: undefined,
});
return output;
@ -268,7 +268,7 @@ export class MatchController
*/
protected extractWasViaCar(extractName: string): boolean
{
// exit name is null on death
// exit name is undefined on death
if (!extractName)
{
return false;

View File

@ -167,7 +167,7 @@ export class ProfileController
pmcData.Inventory.items = this.itemHelper.replaceIDs(
pmcData.Inventory.items,
pmcData,
null,
undefined,
pmcData.Inventory.fastPanel,
);
pmcData.Inventory.hideoutAreaStashes = {};
@ -419,10 +419,10 @@ export class ProfileController
const response: GetProfileStatusResponseData = {
maxPveCountExceeded: false,
profiles: [
{ profileid: account.scavId, profileToken: null, status: "Free", sid: "", ip: "", port: 0 },
{ profileid: account.scavId, profileToken: undefined, status: "Free", sid: "", ip: "", port: 0 },
{
profileid: account.id,
profileToken: null,
profileToken: undefined,
status: "Free",
sid: "",
ip: "",

View File

@ -602,7 +602,7 @@ export class QuestController
protected getQuestsWithDifferentStatuses(
preQuestStatusus: IQuestStatus[],
postQuestStatuses: IQuestStatus[],
): IQuestStatus[]
): IQuestStatus[] | undefined
{
const result: IQuestStatus[] = [];
@ -618,7 +618,7 @@ export class QuestController
if (result.length === 0)
{
return null;
return undefined;
}
return result;

View File

@ -620,10 +620,10 @@ export class RagfairController
protected getItemsToListOnFleaFromInventory(
pmcData: IPmcData,
itemIdsFromFleaOfferRequest: string[],
): { items: Item[] | null, errorMessage: string | null }
): { items: Item[] | undefined, errorMessage: string | undefined }
{
const itemsToReturn = [];
let errorMessage: string | null = null;
let errorMessage: string | undefined = undefined;
// Count how many items are being sold and multiply the requested amount accordingly
for (const itemId of itemIdsFromFleaOfferRequest)
@ -636,7 +636,7 @@ export class RagfairController
});
this.logger.error(errorMessage);
return { items: null, errorMessage };
return { items: undefined, errorMessage };
}
item = this.itemHelper.fixItemStackCount(item);
@ -648,7 +648,7 @@ export class RagfairController
errorMessage = this.localisationService.getText("ragfair-unable_to_find_requested_items_in_inventory");
this.logger.error(errorMessage);
return { items: null, errorMessage };
return { items: undefined, errorMessage };
}
return { items: itemsToReturn, errorMessage };

View File

@ -147,7 +147,7 @@ export class RepeatableQuestController
// Add daily quests
for (let i = 0; i < this.getQuestCount(repeatableConfig, pmcData); i++)
{
let quest = null;
let quest: IRepeatableQuest | undefined = undefined;
let lifeline = 0;
while (!quest && questTypePool.types.length > 0)
{
@ -535,7 +535,7 @@ export class RepeatableQuestController
repeatableConfig: IRepeatableQuestConfig,
): IRepeatableQuest
{
let newRepeatableQuest: IRepeatableQuest = null;
let newRepeatableQuest: IRepeatableQuest = undefined;
let attemptsToGenerateQuest = 0;
while (!newRepeatableQuest && questTypePool.types.length > 0)
{

View File

@ -23,7 +23,7 @@ export class WeatherController
/** Handle client/weather */
public generate(): IWeatherData
{
let result: IWeatherData = { acceleration: 0, time: "", date: "", weather: null, season: 1 }; // defaults, hydrated below
let result: IWeatherData = { acceleration: 0, time: "", date: "", weather: undefined, season: 1 }; // defaults, hydrated below
result = this.weatherGenerator.calculateGameTime(result);
result.weather = this.weatherGenerator.generateWeather();

View File

@ -223,7 +223,7 @@ export class BotEquipmentModGenerator
armorItem: ITemplateItem,
): IFilterPlateModsForSlotByLevelResult
{
const result: IFilterPlateModsForSlotByLevelResult = { result: Result.UNKNOWN_FAILURE, plateModTpls: null };
const result: IFilterPlateModsForSlotByLevelResult = { result: Result.UNKNOWN_FAILURE, plateModTpls: undefined };
// Not pmc or not a plate slot, return original mod pool array
if (!this.itemHelper.isRemovablePlateSlot(modSlot))
@ -796,7 +796,7 @@ export class BotEquipmentModGenerator
{
// Nothing in mod pool + item not required
this.logger.debug(`Mod pool for slot: ${request.modSlot} on item: ${request.parentTemplate._name} was empty, skipping mod`);
return null;
return undefined;
}
// Filter out non-whitelisted scopes, use full modpool if filtered pool would have no elements
@ -844,7 +844,7 @@ export class BotEquipmentModGenerator
if (chosenModResult.slotBlocked && !parentSlot._required)
{
// Don't bother trying to fit mod, slot is completely blocked
return null;
return undefined;
}
// Log if mod chosen was incompatible
@ -864,7 +864,7 @@ export class BotEquipmentModGenerator
// Compatible item not found + not required
if (!chosenModResult.found && parentSlot !== undefined && !parentSlot._required)
{
return null;
return undefined;
}
if (!chosenModResult.found && parentSlot !== undefined)
@ -876,7 +876,7 @@ export class BotEquipmentModGenerator
);
}
return null;
return undefined;
}
return this.itemHelper.getItem(chosenModResult.chosenTpl);
@ -1141,7 +1141,7 @@ export class BotEquipmentModGenerator
}
// No mod found
return null;
return undefined;
}
/**
@ -1336,7 +1336,7 @@ export class BotEquipmentModGenerator
itemModPool = modPool[parentTemplate._id];
}
let exhaustableModPool = null;
let exhaustableModPool = undefined;
let modSlot = "cartridges";
const camoraFirstSlot = "camora_000";
if (modSlot in itemModPool)

View File

@ -176,7 +176,7 @@ export class BotGenerator
// Remove hideout data if bot is not a PMC or pscav
if (!(botGenerationDetails.isPmc || botGenerationDetails.isPlayerScav))
{
bot.Hideout = null;
bot.Hideout = undefined;
}
bot.Info.Experience = botLevel.exp;
@ -436,7 +436,7 @@ export class BotGenerator
const skill = skills[skillKey];
if (!skill)
{
return null;
return undefined;
}
// All skills have id and progress props
@ -451,7 +451,7 @@ export class BotGenerator
return skillToAdd;
})
.filter((x) => x !== null);
.filter((x) => x !== undefined);
}
/**

View File

@ -170,7 +170,7 @@ export class BotLootGenerator
healingItemCount,
botInventory,
botRole,
null,
undefined,
0,
isPmc,
containersIdFull,
@ -183,7 +183,7 @@ export class BotLootGenerator
drugItemCount,
botInventory,
botRole,
null,
undefined,
0,
isPmc,
containersIdFull,
@ -196,7 +196,7 @@ export class BotLootGenerator
foodItemCount,
botInventory,
botRole,
null,
undefined,
0,
isPmc,
containersIdFull,
@ -209,7 +209,7 @@ export class BotLootGenerator
drinkItemCount,
botInventory,
botRole,
null,
undefined,
0,
isPmc,
containersIdFull,
@ -222,7 +222,7 @@ export class BotLootGenerator
currencyItemCount,
botInventory,
botRole,
null,
undefined,
0,
isPmc,
containersIdFull,
@ -248,7 +248,7 @@ export class BotLootGenerator
grenadeCount,
botInventory,
botRole,
null,
undefined,
0,
isPmc,
containersIdFull,
@ -327,7 +327,7 @@ export class BotLootGenerator
50,
botInventory,
botRole,
null,
undefined,
-1,
isPmc,
containersIdFull,
@ -372,7 +372,7 @@ export class BotLootGenerator
1,
botInventory,
botRole,
null,
undefined,
0,
true,
);
@ -385,7 +385,7 @@ export class BotLootGenerator
10,
botInventory,
botRole,
null,
undefined,
0,
true,
);
@ -421,7 +421,7 @@ export class BotLootGenerator
totalItemCount: number,
inventoryToAddItemsTo: PmcInventory,
botRole: string,
itemSpawnLimits: IItemSpawnLimitSettings = null,
itemSpawnLimits: IItemSpawnLimitSettings = undefined,
totalValueLimitRub = 0,
isPmc = false,
containersIdFull = new Set<string>(),
@ -628,7 +628,7 @@ export class BotLootGenerator
// Must add soft inserts/plates
else if (this.itemHelper.itemRequiresSoftInserts(itemToAddTemplate._id))
{
this.itemHelper.addChildSlotItems(itemToAddChildrenTo, itemToAddTemplate, null, false);
this.itemHelper.addChildSlotItems(itemToAddChildrenTo, itemToAddTemplate, undefined, false);
}
}

View File

@ -199,7 +199,7 @@ export class FenceBaseAssortGenerator
protected isAmmoAbovePenetrationLimit(rootItemDb: ITemplateItem): boolean
{
const ammoPenetrationPower = this.getAmmoPenetrationPower(rootItemDb);
if (ammoPenetrationPower === null)
if (ammoPenetrationPower === undefined)
{
this.logger.warning(this.localisationService.getText("fence-unable_to_get_ammo_penetration_value", rootItemDb._id));
@ -212,9 +212,9 @@ export class FenceBaseAssortGenerator
/**
* Get the penetration power value of an ammo, works with ammo boxes and raw ammos
* @param rootItemDb Ammo box or ammo item from items.db
* @returns Penetration power of passed in item, null if it doesnt have a power
* @returns Penetration power of passed in item, undefined if it doesnt have a power
*/
protected getAmmoPenetrationPower(rootItemDb: ITemplateItem): number
protected getAmmoPenetrationPower(rootItemDb: ITemplateItem): number | undefined
{
if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO_BOX))
{
@ -227,7 +227,7 @@ export class FenceBaseAssortGenerator
{
this.logger.warning(this.localisationService.getText("fence-ammo_not_found_in_db", cartridgeTplInBox));
return null;
return undefined;
}
return ammoItemDb[1]._props.PenetrationPower;
@ -240,7 +240,7 @@ export class FenceBaseAssortGenerator
}
// Not an ammobox or ammo
return null;
return undefined;
}
/**

View File

@ -896,7 +896,7 @@ export class LocationGenerator
magazineItem,
itemTemplate, // Magazine template
staticAmmoDist,
null,
undefined,
this.locationConfig.minFillLooseMagazinePercent / 100,
);
}
@ -1108,7 +1108,7 @@ export class LocationGenerator
magazineWithCartridges,
itemTemplate,
staticAmmoDist,
null,
undefined,
this.locationConfig.minFillStaticMagazinePercent / 100,
);

View File

@ -90,7 +90,7 @@ export class PlayerScavGenerator
this.botLootCacheService.clearCache();
// Add scav metadata
scavData.savage = null;
scavData.savage = undefined;
scavData.aid = pmcDataClone.aid;
scavData.TradersInfo = pmcDataClone.TradersInfo;
scavData.Info.Settings = {} as Settings;
@ -311,7 +311,7 @@ export class PlayerScavGenerator
protected getScavLevel(scavProfile: IPmcData): number
{
// Info can be null on initial account creation
// Info can be undefined on initial account creation
if (!scavProfile.Info?.Level)
{
return 1;
@ -322,7 +322,7 @@ export class PlayerScavGenerator
protected getScavExperience(scavProfile: IPmcData): number
{
// Info can be null on initial account creation
// Info can be undefined on initial account creation
if (!scavProfile.Info?.Experience)
{
return 0;

View File

@ -185,17 +185,17 @@ export class RagfairOfferGenerator
};
}
const isPlayerOffer = this.ragfairServerHelper.isPlayer(userID);
const isPlayerOffer = this.profileHelper.isPlayer(userID);
if (isPlayerOffer)
{
const playerProfile = this.profileHelper.getPmcProfile(userID);
const playerProfile = this.profileHelper.getPmcProfile(userID)!;
return {
id: playerProfile._id,
memberType: MemberCategory.DEFAULT,
nickname: playerProfile.Info.Nickname,
rating: playerProfile.RagfairInfo.rating,
isRatingGrowing: playerProfile.RagfairInfo.isRatingGrowing,
avatar: null,
avatar: undefined,
aid: playerProfile.aid,
};
}
@ -209,7 +209,7 @@ export class RagfairOfferGenerator
this.ragfairConfig.dynamic.rating.min,
this.ragfairConfig.dynamic.rating.max),
isRatingGrowing: this.randomUtil.getBool(),
avatar: null,
avatar: undefined,
aid: this.hashUtil.generateAccountId(),
};
}
@ -271,7 +271,7 @@ export class RagfairOfferGenerator
*/
protected getTraderId(userId: string): string
{
if (this.ragfairServerHelper.isPlayer(userId))
if (this.profileHelper.isPlayer(userId))
{
return this.saveServer.getProfile(userId).characters.pmc._id;
}
@ -286,7 +286,7 @@ export class RagfairOfferGenerator
*/
protected getRating(userId: string): number
{
if (this.ragfairServerHelper.isPlayer(userId))
if (this.profileHelper.isPlayer(userId))
{
// Player offer
return this.saveServer.getProfile(userId).characters.pmc.RagfairInfo.rating;
@ -309,7 +309,7 @@ export class RagfairOfferGenerator
*/
protected getRatingGrowing(userID: string): boolean
{
if (this.ragfairServerHelper.isPlayer(userID))
if (this.profileHelper.isPlayer(userID))
{
// player offer
return this.saveServer.getProfile(userID).characters.pmc.RagfairInfo.isRatingGrowing;
@ -334,18 +334,18 @@ export class RagfairOfferGenerator
*/
protected getOfferEndTime(userID: string, time: number): number
{
if (this.ragfairServerHelper.isPlayer(userID))
if (this.profileHelper.isPlayer(userID))
{
// Player offer = current time + offerDurationTimeInHour;
const offerDurationTimeHours
= this.databaseServer.getTables().globals.config.RagFair.offerDurationTimeInHour;
= this.databaseServer.getTables().globals!.config.RagFair.offerDurationTimeInHour;
return this.timeUtil.getTimestamp() + Math.round(offerDurationTimeHours * TimeUtil.ONE_HOUR_AS_SECONDS);
}
if (this.ragfairServerHelper.isTrader(userID))
{
// Trader offer
return this.databaseServer.getTables().traders[userID].base.nextResupply;
return this.databaseServer.getTables().traders![userID].base.nextResupply;
}
// Generated fake-player offer
@ -362,14 +362,14 @@ export class RagfairOfferGenerator
* Create multiple offers for items by using a unique list of items we've generated previously
* @param expiredOffers optional, expired offers to regenerate
*/
public async generateDynamicOffers(expiredOffers: Item[][] = null): Promise<void>
public async generateDynamicOffers(expiredOffers?: Item[][]): Promise<void>
{
const replacingExpiredOffers = expiredOffers?.length > 0;
const replacingExpiredOffers = (expiredOffers?.length ?? 0) > 0;
const config = this.ragfairConfig.dynamic;
// get assort items from param if they exist, otherwise grab freshly generated assorts
const assortItemsToProcess: Item[][] = replacingExpiredOffers
? expiredOffers
? expiredOffers!
: this.ragfairAssortGenerator.getAssortItems();
// Store all functions to create an offer for every item and pass into Promise.all to run async
@ -658,7 +658,7 @@ export class RagfairOfferGenerator
// Add any missing properties to first item in array
this.addMissingConditions(itemWithMods[0]);
if (!(this.ragfairServerHelper.isPlayer(userID) || this.ragfairServerHelper.isTrader(userID)))
if (!(this.profileHelper.isPlayer(userID) || this.ragfairServerHelper.isTrader(userID)))
{
const parentId = this.getDynamicConditionIdForTpl(itemDetails._id);
if (!parentId)

View File

@ -153,7 +153,7 @@ export class RepeatableQuestGenerator
dist: number,
kill: number,
weaponRequirement: number,
): number
): number | undefined
{
return Math.sqrt(Math.sqrt(target) + bodyPart + dist + weaponRequirement) * kill;
}
@ -167,7 +167,7 @@ export class RepeatableQuestGenerator
// also if only bosses are left we need to leave otherwise it's a guaranteed boss elimination
// -> then it would not be a quest with low probability anymore
questTypePool.types = questTypePool.types.filter((t) => t !== "Elimination");
return null;
return undefined;
}
const targetKey = targetsConfig.draw()[0];
@ -208,7 +208,7 @@ export class RepeatableQuestGenerator
}
// draw the target body part and calculate the difficulty factor
let bodyPartsToClient = null;
let bodyPartsToClient = undefined;
let bodyPartDifficulty = 0;
if (eliminationConfig.bodyPartProb > Math.random())
{
@ -231,7 +231,7 @@ export class RepeatableQuestGenerator
}
// Draw a distance condition
let distance = null;
let distance = undefined;
let distanceDifficulty = 0;
let isDistanceRequirementAllowed = !eliminationConfig.distLocationBlacklist.includes(locationKey);
@ -555,7 +555,7 @@ export class RepeatableQuestGenerator
),
);
return null;
return undefined;
}
// Draw items to ask player to retrieve
@ -698,7 +698,7 @@ export class RepeatableQuestGenerator
{
// there are no more locations left for exploration; delete it as a possible quest type
questTypePool.types = questTypePool.types.filter((t) => t !== "Exploration");
return null;
return undefined;
}
// If location drawn is factory, it's possible to either get factory4_day and factory4_night or only one

View File

@ -391,7 +391,7 @@ export class RepeatableQuestRewardGenerator
* @param {integer} index All rewards will be appended to a list, for unknown reasons the client wants the index
* @returns {object} Object of "Reward"-item-type
*/
protected generateRewardItem(tpl: string, value: number, index: number, preset: Item[] = null): IQuestReward
protected generateRewardItem(tpl: string, value: number, index: number, preset?: Item[]): IQuestReward
{
const id = this.objectId.generate();
const rewardItem: IQuestReward = { target: id, value: value, type: QuestRewardType.ITEM, index: index };

View File

@ -150,13 +150,13 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
protected getRandomExternalMagazineForInternalMagazineGun(
weaponTpl: string,
magazineBlacklist: string[],
): ITemplateItem
): ITemplateItem | undefined
{
// The mag Slot data for the weapon
const magSlot = this.itemHelper.getItem(weaponTpl)[1]._props.Slots.find((x) => x._name === "mod_magazine");
if (!magSlot)
{
return null;
return undefined;
}
// All possible mags that fit into the weapon excluding blacklisted
@ -165,14 +165,14 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
);
if (!magazinePool)
{
return null;
return undefined;
}
// Non-internal magazines that fit into the weapon
const externalMagazineOnlyPool = magazinePool.filter((x) => x._props.ReloadMagType !== "InternalMagazine");
if (!externalMagazineOnlyPool || externalMagazineOnlyPool?.length === 0)
{
return null;
return undefined;
}
// Randomly chosen external magazine

View File

@ -194,7 +194,7 @@ export class BotGeneratorHelper
* Get the chance for the weapon attachment or helmet equipment to be set as activated
* @param botRole role of bot with weapon/helmet
* @param setting the setting of the weapon attachment/helmet equipment to be activated
* @param defaultValue default value for the chance of activation if the botrole or bot equipment role is null
* @param defaultValue default value for the chance of activation if the botrole or bot equipment role is undefined
* @returns Percent chance to be active
*/
protected getBotEquipmentSettingFromConfig(

View File

@ -152,12 +152,15 @@ export class BotHelper
* @param botEquipConfig bot equipment json
* @returns RandomisationDetails
*/
public getBotRandomizationDetails(botLevel: number, botEquipConfig: EquipmentFilters): RandomisationDetails
public getBotRandomizationDetails(
botLevel: number,
botEquipConfig: EquipmentFilters,
): RandomisationDetails | undefined
{
// No randomisation details found, skip
if (!botEquipConfig || Object.keys(botEquipConfig).length === 0 || !botEquipConfig.randomisation)
{
return null;
return undefined;
}
return botEquipConfig.randomisation.find((x) => botLevel >= x.levelRange.min && botLevel <= x.levelRange.max);

View File

@ -2,17 +2,8 @@ import { injectable } from "tsyringe";
export class FindSlotResult
{
success: boolean;
x: any;
y: any;
rotation: boolean;
constructor(success = false, x = null, y = null, rotation = false)
{
this.success = success;
this.x = x;
this.y = y;
this.rotation = rotation;
}
constructor(public success = false, public x?: number, public y?: number, public rotation = false)
{}
}
@injectable()

View File

@ -155,7 +155,7 @@ export class ProfileSptCommand implements ISptCommand
_id: this.hashUtil.generate(),
Type: ProfileChangeEventType.PROFILE_LEVEL,
value: exp,
entity: null,
entity: undefined,
};
return event;
}

View File

@ -56,25 +56,28 @@ export class HandbookHelper
// Add handbook overrides found in items.json config into db
for (const itemTpl in this.itemConfig.handbookPriceOverride)
{
let itemToUpdate = this.databaseServer
.getTables()
.templates.handbook.Items.find((item) => item.Id === itemTpl);
let itemToUpdate = this.databaseServer.getTables()
.templates!
.handbook
.Items.find((item) => item.Id === itemTpl);
if (!itemToUpdate)
{
this.databaseServer.getTables().templates.handbook.Items.push({
this.databaseServer.getTables().templates!.handbook.Items.push({
Id: itemTpl,
ParentId: this.databaseServer.getTables().templates.items[itemTpl]._parent,
ParentId: this.databaseServer.getTables().templates!.items[itemTpl]._parent,
Price: this.itemConfig.handbookPriceOverride[itemTpl],
});
itemToUpdate = this.databaseServer
.getTables()
.templates.handbook.Items.find((item) => item.Id === itemTpl);
.templates!
.handbook
.Items.find((item) => item.Id === itemTpl);
}
itemToUpdate.Price = this.itemConfig.handbookPriceOverride[itemTpl];
}
const handbookDbClone = this.cloner.clone(this.databaseServer.getTables().templates.handbook);
const handbookDbClone = this.cloner.clone(this.databaseServer.getTables().templates!.handbook);
for (const handbookItem of handbookDbClone.Items)
{
this.handbookPriceCache.items.byId.set(handbookItem.Id, handbookItem.Price);
@ -87,7 +90,7 @@ export class HandbookHelper
for (const handbookCategory of handbookDbClone.Categories)
{
this.handbookPriceCache.categories.byId.set(handbookCategory.Id, handbookCategory.ParentId || null);
this.handbookPriceCache.categories.byId.set(handbookCategory.Id, handbookCategory.ParentId || undefined);
if (handbookCategory.ParentId)
{
if (!this.handbookPriceCache.categories.byParent.has(handbookCategory.ParentId))
@ -118,7 +121,7 @@ export class HandbookHelper
return this.handbookPriceCache.items.byId.get(tpl);
}
const handbookItem = this.databaseServer.getTables().templates.handbook.Items.find((x) => x.Id === tpl);
const handbookItem = this.databaseServer.getTables().templates!.handbook.Items.find((x) => x.Id === tpl);
if (!handbookItem)
{
const newValue = 0;

View File

@ -38,7 +38,7 @@ export class HealthHelper
if (!profile.vitality)
{
// Occurs on newly created profiles
profile.vitality = { health: null, effects: null };
profile.vitality = { health: undefined!, effects: undefined! };
}
profile.vitality.health = {
Hydration: 0,
@ -87,9 +87,9 @@ export class HealthHelper
const profileHealth = profile.vitality.health;
const profileEffects = profile.vitality.effects;
profileHealth.Hydration = request.Hydration;
profileHealth.Energy = request.Energy;
profileHealth.Temperature = request.Temperature;
profileHealth.Hydration = request.Hydration!;
profileHealth.Energy = request.Energy!;
profileHealth.Temperature = request.Temperature!;
// Transfer properties from request to profile
for (const bodyPart in postRaidBodyParts)

View File

@ -266,13 +266,13 @@ export class HideoutHelper
const craft = pmcData.Hideout.Production[prodId];
if (!craft)
{
// Craft value is null, get rid of it (could be from cancelling craft that needs cleaning up)
// Craft value is undefined, get rid of it (could be from cancelling craft that needs cleaning up)
delete pmcData.Hideout.Production[prodId];
continue;
}
if (craft.Progress === undefined || craft.Progress === null)
if (craft.Progress === undefined)
{
this.logger.warning(this.localisationService.getText("hideout-craft_has_undefined_progress_value_defaulting", prodId));
craft.Progress = 0;
@ -692,7 +692,7 @@ export class HideoutHelper
// How many units of filter are left
let resourceValue = waterFilterItemInSlot.upd?.Resource
? waterFilterItemInSlot.upd.Resource.Value
: null;
: undefined;
if (!resourceValue)
{
// Missing, is new filter, add default and subtract usage
@ -853,7 +853,7 @@ export class HideoutHelper
{
let resourceValue = airFilterArea.slots[i].item[0].upd?.Resource
? airFilterArea.slots[i].item[0].upd.Resource.Value
: null;
: undefined;
if (!resourceValue)
{
resourceValue = 300 - filterDrainRate;
@ -891,12 +891,13 @@ export class HideoutHelper
}
}
protected updateBitcoinFarm(pmcData: IPmcData, btcFarmCGs: number, isGeneratorOn: boolean): Production
protected updateBitcoinFarm(pmcData: IPmcData, btcFarmCGs: number, isGeneratorOn: boolean): Production | undefined
{
const btcProd = pmcData.Hideout.Production[HideoutHelper.bitcoinFarm];
const bitcoinProdData = this.databaseServer
.getTables()
.hideout.production.find((production) => production._id === HideoutHelper.bitcoinProductionId);
.hideout!
.production.find((production) => production._id === HideoutHelper.bitcoinProductionId);
const coinSlotCount = this.getBTCSlots(pmcData);
// Full on bitcoins, halt progress
@ -973,7 +974,7 @@ export class HideoutHelper
return btcProd;
}
return null;
return undefined;
}
/**
@ -1003,7 +1004,7 @@ export class HideoutHelper
protected getTimeElapsedSinceLastServerTick(
pmcData: IPmcData,
isGeneratorOn: boolean,
recipe: IHideoutProduction = null,
recipe?: IHideoutProduction,
): number
{
// Reduce time elapsed (and progress) when generator is off
@ -1017,7 +1018,7 @@ export class HideoutHelper
if (!isGeneratorOn)
{
timeElapsed *= this.databaseServer.getTables().hideout.settings.generatorSpeedWithoutFuel;
timeElapsed *= this.databaseServer.getTables().hideout!.settings.generatorSpeedWithoutFuel;
}
return timeElapsed;
@ -1169,7 +1170,7 @@ export class HideoutHelper
itemsWithModsToAdd: itemsToAdd,
foundInRaid: true,
useSortingTable: false,
callback: null,
callback: undefined,
};
// Add FiR coins to player inventory

View File

@ -184,7 +184,7 @@ export class ItemHelper
* @param {string} tpl the template id / tpl
* @returns boolean; true for items that may be in player possession and not quest items
*/
public isValidItem(tpl: string, invalidBaseTypes: string[] = null): boolean
public isValidItem(tpl: string, invalidBaseTypes?: string[]): boolean
{
const baseTypes = invalidBaseTypes || this.defaultInvalidBaseTypes;
const itemDetails = this.getItem(tpl);
@ -496,12 +496,12 @@ export class ItemHelper
if (item.upd)
{
const medkit = item.upd.MedKit ? item.upd.MedKit : null;
const repairable = item.upd.Repairable ? item.upd.Repairable : null;
const foodDrink = item.upd.FoodDrink ? item.upd.FoodDrink : null;
const key = item.upd.Key ? item.upd.Key : null;
const resource = item.upd.Resource ? item.upd.Resource : null;
const repairKit = item.upd.RepairKit ? item.upd.RepairKit : null;
const medkit = item.upd.MedKit ? item.upd.MedKit : undefined;
const repairable = item.upd.Repairable ? item.upd.Repairable : undefined;
const foodDrink = item.upd.FoodDrink ? item.upd.FoodDrink : undefined;
const key = item.upd.Key ? item.upd.Key : undefined;
const resource = item.upd.Resource ? item.upd.Resource : undefined;
const repairKit = item.upd.RepairKit ? item.upd.RepairKit : undefined;
const itemDetails = this.getItem(item._tpl)[1];
@ -725,7 +725,7 @@ export class ItemHelper
*/
public splitStack(itemToSplit: Item): Item[]
{
if (!(itemToSplit?.upd?.StackObjectsCount != null))
if (itemToSplit?.upd?.StackObjectsCount === undefined)
{
return [itemToSplit];
}
@ -834,9 +834,9 @@ export class ItemHelper
*/
public replaceIDs(
originalItems: Item[],
pmcData: IPmcData | null = null,
insuredItems: InsuredItem[] | null = null,
fastPanel = null,
pmcData?: IPmcData,
insuredItems?: InsuredItem[],
fastPanel?: any,
): Item[]
{
let items = this.cloner.clone(originalItems); // Deep-clone the items to avoid mutation.
@ -844,7 +844,7 @@ export class ItemHelper
for (const item of items)
{
if (pmcData !== null)
if (pmcData)
{
// Insured items should not be renamed. Only works for PMCs.
if (insuredItems?.find((insuredItem) => insuredItem.itemId === item._id))
@ -871,7 +871,7 @@ export class ItemHelper
serialisedInventory = serialisedInventory.replace(new RegExp(oldId, "g"), newId);
// Also replace in quick slot if the old ID exists.
if (fastPanel !== null)
if (fastPanel)
{
for (const itemSlot in fastPanel)
{
@ -1031,14 +1031,14 @@ export class ItemHelper
*
* @param item The item to be checked
* @param parent The parent of the item to be checked
* @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed.
* @returns True if the item is actually moddable, false if it is not, and undefined if the check cannot be performed.
*/
public isRaidModdable(item: Item, parent: Item): boolean | null
public isRaidModdable(item: Item, parent: Item): boolean | undefined
{
// This check requires the item to have the slotId property populated.
if (!item.slotId)
{
return null;
return undefined;
}
const itemTemplate = this.getItem(item._tpl);
@ -1077,9 +1077,9 @@ export class ItemHelper
*
* @param itemId - The unique identifier of the item for which to find the main parent.
* @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup.
* @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists.
* @returns The Item object representing the top-most parent of the given item, or `undefined` if no such parent exists.
*/
public getAttachmentMainParent(itemId: string, itemsMap: Map<string, Item>): Item | null
public getAttachmentMainParent(itemId: string, itemsMap: Map<string, Item>): Item | undefined
{
let currentItem = itemsMap.get(itemId);
while (currentItem && this.isAttachmentAttached(currentItem))
@ -1087,7 +1087,7 @@ export class ItemHelper
currentItem = itemsMap.get(currentItem.parentId);
if (!currentItem)
{
return null;
return undefined;
}
}
return currentItem;
@ -1123,9 +1123,9 @@ export class ItemHelper
*
* @param itemId - The unique identifier of the item for which to find the equipment parent.
* @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup.
* @returns The Item object representing the equipment parent of the given item, or `null` if no such parent exists.
* @returns The Item object representing the equipment parent of the given item, or `undefined` if no such parent exists.
*/
public getEquipmentParent(itemId: string, itemsMap: Map<string, Item>): Item | null
public getEquipmentParent(itemId: string, itemsMap: Map<string, Item>): Item | undefined
{
let currentItem = itemsMap.get(itemId);
const equipmentSlots = Object.values(EquipmentSlots).map((value) => value as string);
@ -1135,7 +1135,7 @@ export class ItemHelper
currentItem = itemsMap.get(currentItem.parentId);
if (!currentItem)
{
return null;
return undefined;
}
}
return currentItem;
@ -1197,14 +1197,14 @@ export class ItemHelper
* @param item Db item template to look up Cartridge filter values from
* @returns Caliber of cartridge
*/
public getRandomCompatibleCaliberTemplateId(item: ITemplateItem): string | null
public getRandomCompatibleCaliberTemplateId(item: ITemplateItem): string | undefined
{
const cartridges = item?._props?.Cartridges[0]?._props?.filters[0]?.Filter;
if (!cartridges)
{
this.logger.warning(`Failed to find cartridge for item: ${item?._id} ${item?._name}`);
return null;
return undefined;
}
return this.randomUtil.getArrayValue(cartridges);
@ -1467,8 +1467,8 @@ export class ItemHelper
caliber: string,
staticAmmoDist: Record<string, IStaticAmmoDetails[]>,
fallbackCartridgeTpl: string,
cartridgeWhitelist: string[] = null,
): string
cartridgeWhitelist?: string[],
): string | undefined
{
const ammos = staticAmmoDist[caliber];
if (!ammos && fallbackCartridgeTpl)
@ -1581,7 +1581,7 @@ export class ItemHelper
public addChildSlotItems(
itemToAdd: Item[],
itemToAddTemplate: ITemplateItem,
modSpawnChanceDict: Record<string, number> = null,
modSpawnChanceDict?: Record<string, number>,
requiredOnly = false,
): Item[]
{
@ -1641,16 +1641,16 @@ export class ItemHelper
* Get a compatible tpl from the array provided where it is not found in the provided incompatible mod tpls parameter
* @param possibleTpls Tpls to randomly choose from
* @param incompatibleModTpls Incompatible tpls to not allow
* @returns Chosen tpl or null
* @returns Chosen tpl or undefined
*/
public getCompatibleTplFromArray(possibleTpls: string[], incompatibleModTpls: Set<string>): string
public getCompatibleTplFromArray(possibleTpls: string[], incompatibleModTpls: Set<string>): string | undefined
{
if (possibleTpls.length === 0)
{
return null;
return undefined;
}
let chosenTpl = null;
let chosenTpl: string | undefined = undefined;
let count = 0;
while (!chosenTpl)
{
@ -1662,7 +1662,7 @@ export class ItemHelper
count++;
if (count >= possibleTpls.length)
{
return null;
return undefined;
}
continue;
}
@ -1818,7 +1818,7 @@ export class ItemHelper
* @param warningMessageWhenMissing text to write to log when upd object was not found
* @returns True when upd object was added
*/
public addUpdObjectToItem(item: Item, warningMessageWhenMissing: string = null): boolean
public addUpdObjectToItem(item: Item, warningMessageWhenMissing?: string): boolean
{
if (!item.upd)
{

View File

@ -138,11 +138,11 @@ export class PresetHelper
* @param templateId Item id to get preset for
* @returns Null if no default preset, otherwise IPreset
*/
public getDefaultPreset(templateId: string): IPreset
public getDefaultPreset(templateId: string): IPreset | undefined
{
if (!this.hasPreset(templateId))
{
return null;
return undefined;
}
const allPresets = this.getPresets(templateId);

View File

@ -218,7 +218,7 @@ export class ProfileHelper
public getExperience(level: number): number
{
let playerLevel = level;
const expTable = this.databaseServer.getTables().globals.config.exp.level.exp_table;
const expTable = this.databaseServer.getTables().globals!.config.exp.level.exp_table;
let exp = 0;
if (playerLevel >= expTable.length)
@ -241,7 +241,7 @@ export class ProfileHelper
*/
public getMaxLevel(): number
{
return this.databaseServer.getTables().globals.config.exp.level.exp_table.length - 1;
return this.databaseServer.getTables().globals!.config.exp.level.exp_table.length - 1;
}
public getDefaultSptDataObject(): any
@ -254,14 +254,11 @@ export class ProfileHelper
* @param sessionID Profile id to get
* @returns ISptProfile object
*/
public getFullProfile(sessionID: string): ISptProfile
public getFullProfile(sessionID: string): ISptProfile | undefined
{
if (this.saveServer.getProfile(sessionID) === undefined)
{
return undefined;
}
return this.saveServer.getProfile(sessionID);
return this.saveServer.profileExists(sessionID)
? this.saveServer.getProfile(sessionID)
: undefined;
}
/**
@ -269,10 +266,10 @@ export class ProfileHelper
* @param sessionID Profile id to return
* @returns IPmcData object
*/
public getPmcProfile(sessionID: string): IPmcData
public getPmcProfile(sessionID: string): IPmcData | undefined
{
const fullProfile = this.getFullProfile(sessionID);
if (fullProfile === undefined || fullProfile.characters.pmc === undefined)
if (!fullProfile?.characters?.pmc)
{
return undefined;
}
@ -280,6 +277,16 @@ export class ProfileHelper
return this.saveServer.getProfile(sessionID).characters.pmc;
}
/**
* Is this user id the logged in player
* @param userId Id to test
* @returns True is the current player
*/
public isPlayer(userId: string): boolean
{
return this.saveServer.profileExists(userId);
}
/**
* Get a full profiles scav-specific sub-profile
* @param sessionID Profiles id
@ -299,7 +306,7 @@ export class ProfileHelper
return {
Eft: {
CarriedQuestItems: [],
DamageHistory: { LethalDamagePart: "Head", LethalDamage: undefined, BodyParts: <any>[] },
DamageHistory: { LethalDamagePart: "Head", LethalDamage: undefined!, BodyParts: <any>[] },
DroppedItems: [],
ExperienceBonusMult: 0,
FoundInRaidItems: [],

View File

@ -6,7 +6,7 @@ export class QuestConditionHelper
{
public getQuestConditions(
q: IQuestCondition[],
furtherFilter: (a: IQuestCondition) => IQuestCondition[] = null,
furtherFilter?: (a: IQuestCondition) => IQuestCondition[],
): IQuestCondition[]
{
return this.filterConditions(q, "Quest", furtherFilter);
@ -14,7 +14,7 @@ export class QuestConditionHelper
public getLevelConditions(
q: IQuestCondition[],
furtherFilter: (a: IQuestCondition) => IQuestCondition[] = null,
furtherFilter?: (a: IQuestCondition) => IQuestCondition[],
): IQuestCondition[]
{
return this.filterConditions(q, "Level", furtherFilter);
@ -22,7 +22,7 @@ export class QuestConditionHelper
public getLoyaltyConditions(
q: IQuestCondition[],
furtherFilter: (a: IQuestCondition) => IQuestCondition[] = null,
furtherFilter?: (a: IQuestCondition) => IQuestCondition[],
): IQuestCondition[]
{
return this.filterConditions(q, "TraderLoyalty", furtherFilter);
@ -30,7 +30,7 @@ export class QuestConditionHelper
public getStandingConditions(
q: IQuestCondition[],
furtherFilter: (a: IQuestCondition) => IQuestCondition[] = null,
furtherFilter?: (a: IQuestCondition) => IQuestCondition[],
): IQuestCondition[]
{
return this.filterConditions(q, "TraderStanding", furtherFilter);
@ -39,7 +39,7 @@ export class QuestConditionHelper
protected filterConditions(
q: IQuestCondition[],
questType: string,
furtherFilter: (a: IQuestCondition) => IQuestCondition[] = null,
furtherFilter?: (a: IQuestCondition) => IQuestCondition[],
): IQuestCondition[]
{
const filteredQuests = q.filter((c) =>

View File

@ -374,7 +374,7 @@ export class QuestHelper
const itemDbData = this.itemHelper.getItem(originalRewardRootItem._tpl)[1];
// Hydrate reward with only 'required' mods - necessary for things like helmets otherwise you end up with nvgs/visors etc
questReward.items = this.itemHelper.addChildSlotItems(questReward.items, itemDbData, null, true);
questReward.items = this.itemHelper.addChildSlotItems(questReward.items, itemDbData, undefined, true);
}
/**
@ -716,7 +716,7 @@ export class QuestHelper
pmcData: IPmcData,
failRequest: IFailQuestRequestData,
sessionID: string,
output: IItemEventRouterResponse = null,
output?: IItemEventRouterResponse,
): void
{
let updatedOutput = output;
@ -751,7 +751,7 @@ export class QuestHelper
{
this.mailSendService.sendLocalisedNpcMessageToPlayer(
sessionID,
this.traderHelper.getTraderById(quest?.traderId ?? matchingRepeatableQuest?.traderId), // Can be null when repeatable quest has been moved to inactiveQuests
this.traderHelper.getTraderById(quest?.traderId ?? matchingRepeatableQuest?.traderId), // Can be undefined when repeatable quest has been moved to inactiveQuests
MessageType.QUEST_FAIL,
quest.failMessageText,
questRewards,

View File

@ -151,7 +151,7 @@ export class RagfairHelper
public mergeStackable(items: Item[]): Item[]
{
const list = [];
let rootItem = null;
let rootItem = undefined;
for (let item of items)
{

View File

@ -510,7 +510,7 @@ export class RagfairOfferHelper
itemsToSend,
this.timeUtil.getHoursAsSeconds(
this.questHelper.getMailItemRedeemTimeHoursForProfile(this.profileHelper.getPmcProfile(sessionID))),
null,
undefined,
ragfairDetails,
);
@ -755,7 +755,7 @@ export class RagfairOfferHelper
if (Number.isNaN(offer.requirementsCost))
{
// don't include offers with null or NaN in it
// don't include offers with undefined or NaN in it
return false;
}

View File

@ -147,20 +147,6 @@ export class RagfairServerHelper
return traderId in this.databaseServer.getTables().traders;
}
/**
* Is this user id the logged in player
* @param userId Id to test
* @returns True is the current player
*/
public isPlayer(userId: string): boolean
{
if (this.profileHelper.getPmcProfile(userId) !== undefined)
{
return true;
}
return false;
}
/**
* Send items back to player
* @param sessionID Player to send items to

View File

@ -292,7 +292,7 @@ export class TraderAssortHelper
items: this.ragfairAssortGenerator.getAssortItems().flat(),
barter_scheme: {},
loyal_level_items: {},
nextResupply: null,
nextResupply: undefined,
};
}
}

View File

@ -116,9 +116,9 @@ export class ModLoadOrder
// Additional info to help debug
this.logger.debug(this.localisationService.getText("modloader-checking_mod", mod));
this.logger.debug(`${this.localisationService.getText("modloader-checked")}:`);
this.logger.debug(JSON.stringify(this.loadOrder, null, "\t"));
this.logger.debug(JSON.stringify(this.loadOrder, undefined, "\t"));
this.logger.debug(`${this.localisationService.getText("modloader-visited")}:`);
this.logger.debug(JSON.stringify(visited, null, "\t"));
this.logger.debug(JSON.stringify(visited, undefined, "\t"));
throw new Error(this.localisationService.getText("modloader-cyclic_dependency"));
}

View File

@ -136,7 +136,7 @@ export class PreSptModLoader implements IModLoader
this.logger.info(this.localisationService.getText("modloader-mod_order_missing"));
// Write file with empty order array to disk
this.vfs.writeFile(this.modOrderPath, this.jsonUtil.serializeAdvanced({ order: [] }, null, 4));
this.vfs.writeFile(this.modOrderPath, this.jsonUtil.serializeAdvanced({ order: [] }, undefined, 4));
}
else
{

View File

@ -1,4 +1,4 @@
export interface IGameModeRequestData
{
sessionMode: string | null
sessionMode: string | undefined
}

View File

@ -2,5 +2,5 @@ export interface INullResponseData
{
err: number
errmsg: any
data: null
data: undefined
}

View File

@ -14,11 +14,11 @@ export class ExhaustableArray<T> implements IExhaustableArray<T>
this.pool = this.cloner.clone(itemPool);
}
public getRandomValue(): T
public getRandomValue(): T | undefined
{
if (!this.pool?.length)
{
return null;
return undefined;
}
const index = this.randomUtil.getInt(0, this.pool.length - 1);
@ -27,11 +27,11 @@ export class ExhaustableArray<T> implements IExhaustableArray<T>
return toReturn;
}
public getFirstValue(): T
public getFirstValue(): T | undefined
{
if (!this.pool?.length)
{
return null;
return undefined;
}
const toReturn = this.cloner.clone(this.pool[0]);
@ -52,7 +52,7 @@ export class ExhaustableArray<T> implements IExhaustableArray<T>
export interface IExhaustableArray<T>
{
getRandomValue(): T
getFirstValue(): T
getRandomValue(): T | undefined
getFirstValue(): T | undefined
hasValues(): boolean
}

View File

@ -144,7 +144,7 @@ export class EventOutputHolder
*/
protected getProductionsFromProfileAndFlagComplete(
productions: Record<string, Productive>,
): Record<string, Productive>
): Record<string, Productive> | undefined
{
for (const productionKey in productions)
{
@ -182,8 +182,8 @@ export class EventOutputHolder
}
}
// Return null if there's no crafts to send to client to match live behaviour
return Object.keys(productions).length > 0 ? productions : null;
// Return undefined if there's no crafts to send to client to match live behaviour
return Object.keys(productions).length > 0 ? productions : undefined;
}
/**

View File

@ -15,7 +15,7 @@ export class HealthSaveLoadRouter extends SaveLoadRouter
if (!profile.vitality)
{
// Occurs on newly created profiles
profile.vitality = { health: null, effects: null };
profile.vitality = { health: undefined!, effects: undefined! };
}
profile.vitality.health = {
Hydration: 0,

View File

@ -13,7 +13,7 @@ export class ProfileSaveLoadRouter extends SaveLoadRouter
public override handleLoad(profile: ISptProfile): ISptProfile
{
if (profile.characters === null)
if (!profile.characters)
{
profile.characters = { pmc: {} as IPmcData, scav: {} as IPmcData };
}

View File

@ -46,7 +46,7 @@ export class SaveServer
*/
public removeBeforeSaveCallback(id: string): void
{
this.onBeforeSaveCallbacks[id] = null;
this.onBeforeSaveCallbacks[id] = undefined;
}
/**
@ -102,12 +102,12 @@ export class SaveServer
throw new Error("session id provided was empty, did you restart the server while the game was running?");
}
if (this.profiles === null)
if (!this.profiles)
{
throw new Error(`no profiles found in saveServer with id: ${sessionId}`);
}
if (this.profiles[sessionId] === null)
if (!this.profiles[sessionId])
{
throw new Error(`no profile found for sessionId: ${sessionId}`);
}
@ -115,6 +115,11 @@ export class SaveServer
return this.profiles[sessionId];
}
public profileExists(id: string): boolean
{
return !!this.profiles[id];
}
/**
* Get all profiles from memory
* @returns Dictionary of ISptProfile
@ -131,7 +136,7 @@ export class SaveServer
*/
public deleteProfileById(sessionID: string): boolean
{
if (this.profiles[sessionID] != null)
if (this.profiles[sessionID])
{
delete this.profiles[sessionID];
return true;
@ -146,7 +151,7 @@ export class SaveServer
*/
public createProfile(profileInfo: Info): void
{
if (this.profiles[profileInfo.id] != null)
if (this.profiles[profileInfo.id])
{
throw new Error(`profile already exists for sessionId: ${profileInfo.id}`);
}

View File

@ -34,8 +34,8 @@ export class SptHttpListener implements IHttpListener
{
case "GET":
{
const response = await this.getResponse(sessionId, req, null);
this.sendResponse(sessionId, req, resp, null, response);
const response = await this.getResponse(sessionId, req, undefined);
this.sendResponse(sessionId, req, resp, undefined, response);
break;
}
// these are handled almost identically.
@ -152,12 +152,12 @@ export class SptHttpListener implements IHttpListener
{
this.logger.error(this.localisationService.getText("unhandled_response", req.url));
this.logger.info(info);
output = <string>(<unknown> this.httpResponse.getBody(null, 404, `UNHANDLED RESPONSE: ${req.url}`));
output = <string>(<unknown> this.httpResponse.getBody(undefined, 404, `UNHANDLED RESPONSE: ${req.url}`));
}
return output;
}
protected getBodyInfo(body: Buffer, requestUrl = null): any
protected getBodyInfo(body: Buffer, requestUrl = undefined): any
{
const text = body ? body.toString() : "{}";
const info = text ? this.jsonUtil.deserialize<any>(text, requestUrl) : {};

View File

@ -20,7 +20,7 @@ export class SptWebSocketConnectionHandler implements IWebSocketConnectionHandle
protected webSockets: Map<string, WebSocket> = new Map<string, WebSocket>();
protected defaultNotification: IWsNotificationEvent = { type: NotificationEventType.PING, eventId: "ping" };
protected websocketPingHandler = null;
protected websocketPingHandler: NodeJS.Timeout | undefined;
constructor(
@inject("WinstonLogger") protected logger: ILogger,
@inject("ProfileHelper") protected profileHelper: ProfileHelper,

View File

@ -152,13 +152,13 @@ export class BotEquipmentFilterService
* @param botEquipmentRole equipment role of bot to look up
* @returns Dictionary of weapon type and their whitelisted scope types
*/
public getBotWeaponSightWhitelist(botEquipmentRole: string): Record<string, string[]>
public getBotWeaponSightWhitelist(botEquipmentRole: string): Record<string, string[]> | undefined
{
const botEquipmentSettings = this.botEquipmentConfig[botEquipmentRole];
if (!botEquipmentSettings)
{
return null;
return undefined;
}
return botEquipmentSettings.weaponSightWhitelist;
@ -170,7 +170,7 @@ export class BotEquipmentFilterService
* @param playerLevel Level of the player
* @returns EquipmentBlacklistDetails object
*/
public getBotEquipmentBlacklist(botRole: string, playerLevel: number): EquipmentFilterDetails
public getBotEquipmentBlacklist(botRole: string, playerLevel: number): EquipmentFilterDetails | undefined
{
const blacklistDetailsForBot = this.botEquipmentConfig[botRole];
@ -181,7 +181,7 @@ export class BotEquipmentFilterService
|| !blacklistDetailsForBot.blacklist
)
{
return null;
return undefined;
}
return blacklistDetailsForBot.blacklist.find(
@ -195,14 +195,14 @@ export class BotEquipmentFilterService
* @param playerLevel Players level
* @returns EquipmentFilterDetails object
*/
protected getBotEquipmentWhitelist(botRole: string, playerLevel: number): EquipmentFilterDetails
protected getBotEquipmentWhitelist(botRole: string, playerLevel: number): EquipmentFilterDetails | undefined
{
const botEquipmentConfig = this.botEquipmentConfig[botRole];
// No equipment blacklist found, skip
if (!botEquipmentConfig || Object.keys(botEquipmentConfig).length === 0 || !botEquipmentConfig.whitelist)
{
return null;
return undefined;
}
return botEquipmentConfig.whitelist.find(
@ -216,7 +216,7 @@ export class BotEquipmentFilterService
* @param botLevel Level of bot
* @returns Weighting adjustments for bot items
*/
protected getBotWeightingAdjustments(botRole: string, botLevel: number): WeightingAdjustmentDetails
protected getBotWeightingAdjustments(botRole: string, botLevel: number): WeightingAdjustmentDetails | undefined
{
const botEquipmentConfig = this.botEquipmentConfig[botRole];
@ -227,7 +227,7 @@ export class BotEquipmentFilterService
|| !botEquipmentConfig.weightingAdjustmentsByBotLevel
)
{
return null;
return undefined;
}
return botEquipmentConfig.weightingAdjustmentsByBotLevel.find(
@ -244,7 +244,7 @@ export class BotEquipmentFilterService
protected getBotWeightingAdjustmentsByPlayerLevel(
botRole: string,
playerlevel: number,
): WeightingAdjustmentDetails
): WeightingAdjustmentDetails | undefined
{
const botEquipmentConfig = this.botEquipmentConfig[botRole];
@ -255,7 +255,7 @@ export class BotEquipmentFilterService
|| !botEquipmentConfig.weightingAdjustmentsByPlayerLevel
)
{
return null;
return undefined;
}
return botEquipmentConfig.weightingAdjustmentsByPlayerLevel.find(

View File

@ -532,7 +532,7 @@ export class BotLootCacheService
}
/**
* If lootcache is null, init with empty property arrays
* If lootcache is undefined, init with empty property arrays
* @param botRole Bot role to hydrate
*/
protected initCacheForBotRole(botRole: string): void

View File

@ -38,10 +38,10 @@ export class FenceService
protected nextPartialRefreshTimestamp: number;
/** Main assorts you see at all rep levels */
protected fenceAssort: ITraderAssort = undefined;
protected fenceAssort?: ITraderAssort = undefined;
/** Assorts shown on a separate tab when you max out fence rep */
protected fenceDiscountAssort: ITraderAssort = undefined;
protected fenceDiscountAssort?: ITraderAssort = undefined;
/** Desired baseline counts - Hydrated on initial assort generation as part of generateFenceAssorts() */
protected desiredAssortCounts: IFenceAssortGenerationValues;
@ -96,7 +96,7 @@ export class FenceService
* Get main fence assort
* @return ITraderAssort
*/
public getMainFenceAssort(): ITraderAssort
public getMainFenceAssort(): ITraderAssort | undefined
{
return this.fenceAssort;
}
@ -105,7 +105,7 @@ export class FenceService
* Get discount fence assort
* @return ITraderAssort
*/
public getDiscountFenceAssort(): ITraderAssort
public getDiscountFenceAssort(): ITraderAssort | undefined
{
return this.fenceDiscountAssort;
}
@ -135,23 +135,23 @@ export class FenceService
// Clone assorts so we can adjust prices before sending to client
const assort = this.cloner.clone(this.fenceAssort);
this.adjustAssortItemPricesByConfigMultiplier(assort, 1, this.traderConfig.fence.presetPriceMult);
this.adjustAssortItemPricesByConfigMultiplier(assort!, 1, this.traderConfig.fence.presetPriceMult);
// merge normal fence assorts + discount assorts if player standing is large enough
if (pmcProfile.TradersInfo[Traders.FENCE].standing >= 6)
{
const discountAssort = this.cloner.clone(this.fenceDiscountAssort);
this.adjustAssortItemPricesByConfigMultiplier(
discountAssort,
discountAssort!,
this.traderConfig.fence.discountOptions.itemPriceMult,
this.traderConfig.fence.discountOptions.presetPriceMult,
);
const mergedAssorts = this.mergeAssorts(assort, discountAssort);
const mergedAssorts = this.mergeAssorts(assort!, discountAssort!);
return mergedAssorts;
}
return assort;
return assort!;
}
/**
@ -184,7 +184,7 @@ export class FenceService
createAssort.sptItems.push(clonedItems);
createAssort.loyal_level_items[root._id] = 1;
this.updateFenceAssorts(createAssort, this.fenceAssort);
this.updateFenceAssorts(createAssort, this.fenceAssort!);
}
/**
@ -213,7 +213,7 @@ export class FenceService
{
if (this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.AMMO))
{
total += this.handbookHelper.getTemplatePrice(item._tpl) * (item.upd.StackObjectsCount ?? 1);
total += this.handbookHelper.getTemplatePrice(item._tpl) * (item.upd?.StackObjectsCount ?? 1);
}
}
@ -310,7 +310,7 @@ export class FenceService
*/
public getRawFenceAssorts(): ITraderAssort
{
return this.mergeAssorts(this.cloner.clone(this.fenceAssort), this.cloner.clone(this.fenceDiscountAssort));
return this.mergeAssorts(this.cloner.clone(this.fenceAssort!), this.cloner.clone(this.fenceDiscountAssort!));
}
/**
@ -333,49 +333,49 @@ export class FenceService
);
// Simulate players buying items
this.deleteRandomAssorts(itemCountToReplace, this.fenceAssort);
this.deleteRandomAssorts(discountItemCountToReplace, this.fenceDiscountAssort);
this.deleteRandomAssorts(itemCountToReplace, this.fenceAssort!);
this.deleteRandomAssorts(discountItemCountToReplace, this.fenceDiscountAssort!);
const normalItemCountsToGenerate = this.getItemCountsToGenerate(
this.fenceAssort.items,
this.fenceAssort!.items,
this.desiredAssortCounts.normal,
);
const newItems = this.createAssorts(normalItemCountsToGenerate, 1);
// Push newly generated assorts into existing data
this.updateFenceAssorts(newItems, this.fenceAssort);
this.updateFenceAssorts(newItems, this.fenceAssort!);
const discountItemCountsToGenerate = this.getItemCountsToGenerate(
this.fenceDiscountAssort.items,
this.fenceDiscountAssort!.items,
this.desiredAssortCounts.discount,
);
const newDiscountItems = this.createAssorts(discountItemCountsToGenerate, 2);
// Push newly generated discount assorts into existing data
this.updateFenceAssorts(newDiscountItems, this.fenceDiscountAssort);
this.updateFenceAssorts(newDiscountItems, this.fenceDiscountAssort!);
// Add new barter items to fence barter scheme
for (const barterItemKey in newItems.barter_scheme)
{
this.fenceAssort.barter_scheme[barterItemKey] = newItems.barter_scheme[barterItemKey];
this.fenceAssort!.barter_scheme[barterItemKey] = newItems.barter_scheme[barterItemKey];
}
// Add loyalty items to fence assorts loyalty object
for (const loyaltyItemKey in newItems.loyal_level_items)
{
this.fenceAssort.loyal_level_items[loyaltyItemKey] = newItems.loyal_level_items[loyaltyItemKey];
this.fenceAssort!.loyal_level_items[loyaltyItemKey] = newItems.loyal_level_items[loyaltyItemKey];
}
// Add new barter items to fence assorts discounted barter scheme
for (const barterItemKey in newDiscountItems.barter_scheme)
{
this.fenceDiscountAssort.barter_scheme[barterItemKey] = newDiscountItems.barter_scheme[barterItemKey];
this.fenceDiscountAssort!.barter_scheme[barterItemKey] = newDiscountItems.barter_scheme[barterItemKey];
}
// Add loyalty items to fence discount assorts loyalty object
for (const loyaltyItemKey in newDiscountItems.loyal_level_items)
{
this.fenceDiscountAssort.loyal_level_items[loyaltyItemKey]
this.fenceDiscountAssort!.loyal_level_items[loyaltyItemKey]
= newDiscountItems.loyal_level_items[loyaltyItemKey];
}
@ -428,13 +428,13 @@ export class FenceService
)
{
// Guard against a missing stack count
if (!existingRootItem.upd.StackObjectsCount)
if (existingRootItem.upd?.StackObjectsCount === undefined)
{
existingRootItem.upd.StackObjectsCount = 1;
existingRootItem.upd!.StackObjectsCount = 1;
}
// Merge new items count into existing, dont add new loyalty/barter data as it already exists
existingRootItem.upd.StackObjectsCount += newRootItem?.upd?.StackObjectsCount ?? 1;
existingRootItem.upd!.StackObjectsCount += newRootItem?.upd?.StackObjectsCount ?? 1;
continue;
}
@ -547,7 +547,7 @@ export class FenceService
}
// Reduce stack to at smallest, 1
rootItemToAdjust.upd.StackObjectsCount -= Math.max(1, itemCountToRemove);
rootItemToAdjust.upd!.StackObjectsCount! -= Math.max(1, itemCountToRemove);
return;
}
@ -694,7 +694,7 @@ export class FenceService
{
const result: ICreateFenceAssortsResult = { sptItems: [], barter_scheme: {}, loyal_level_items: {} };
const baseFenceAssortClone = this.cloner.clone(this.databaseServer.getTables().traders[Traders.FENCE].assort);
const baseFenceAssortClone = this.cloner.clone(this.databaseServer.getTables().traders![Traders.FENCE].assort!);
const itemTypeLimitCounts = this.initItemLimitCounter(this.traderConfig.fence.itemTypeLimits);
if (itemCounts.item > 0)
@ -750,7 +750,7 @@ export class FenceService
if (!chosenBaseAssortRoot)
{
this.logger.error(
this.localisationService.getText("fence-unable_to_find_assort_by_id", chosenBaseAssortRoot._id),
this.localisationService.getText("fence-unable_to_find_assort_by_id"),
);
continue;
@ -760,7 +760,7 @@ export class FenceService
);
const itemDbDetails = this.itemHelper.getItem(chosenBaseAssortRoot._tpl)[1];
const itemLimitCount = this.getMatchingItemLimit(itemTypeLimits, itemDbDetails._id);
const itemLimitCount = this.getMatchingItemLimit(itemTypeLimits, itemDbDetails._id)!;
if (itemLimitCount?.current >= itemLimitCount?.max)
{
// Skip adding item as assort as limit reached, decrement i counter so we still get another item
@ -798,23 +798,23 @@ export class FenceService
const rootItemBeingAdded = desiredAssortItemAndChildrenClone[0];
// Set stack size based on possible overrides, e.g. ammos, otherwise set to 1
rootItemBeingAdded.upd.StackObjectsCount = this.getSingleItemStackCount(itemDbDetails);
rootItemBeingAdded.upd!.StackObjectsCount = this.getSingleItemStackCount(itemDbDetails);
// Only randomise upd values for single
const isSingleStack = rootItemBeingAdded.upd.StackObjectsCount === 1;
const isSingleStack = (rootItemBeingAdded.upd?.StackObjectsCount ?? 0) === 1;
if (isSingleStack)
{
this.randomiseItemUpdProperties(itemDbDetails, rootItemBeingAdded);
}
// Skip items already in the assort if it exists in the prevent duplicate list
const existingItemThatMatches = this.getMatchingItem(rootItemBeingAdded, itemDbDetails, assorts.sptItems);
const existingItemThatMatches = this.getMatchingItem(rootItemBeingAdded, itemDbDetails, assorts.sptItems)!;
const shouldBeStacked = this.itemShouldBeForceStacked(existingItemThatMatches, itemDbDetails);
if (shouldBeStacked && existingItemThatMatches)
{
// Decrement loop counter so another items gets added
i--;
existingItemThatMatches.upd.StackObjectsCount++;
existingItemThatMatches.upd!.StackObjectsCount!++;
continue;
}
@ -853,7 +853,7 @@ export class FenceService
rootItemBeingAdded: Item,
itemDbDetails: ITemplateItem,
itemsWithChildren: Item[][],
): Item
): Item | undefined
{
// Get matching root items
const matchingItems = itemsWithChildren
@ -864,7 +864,7 @@ export class FenceService
if (matchingItems.length === 0)
{
// Nothing matches by tpl and is root item, exit early
return null;
return undefined;
}
const isMedical = this.itemHelper.isOfBaseclasses(rootItemBeingAdded._tpl, [
@ -875,7 +875,7 @@ export class FenceService
= this.itemHelper.isOfBaseclasses(rootItemBeingAdded._tpl, [
BaseClasses.ARMORED_EQUIPMENT,
BaseClasses.SEARCHABLE_ITEM,
]) && itemDbDetails._props.Slots.length > 0;
]) && (itemDbDetails._props.Slots?.length ?? 0) > 0;
// Only one match and its not medical or armored gear
if (matchingItems.length === 1 && !(isMedical || isGearAndHasSlots))
@ -886,25 +886,25 @@ export class FenceService
// Items have sub properties that need to be checked against
for (const item of matchingItems)
{
if (isMedical && rootItemBeingAdded.upd.MedKit?.HpResource === item.upd.MedKit?.HpResource)
if (isMedical && rootItemBeingAdded.upd!.MedKit?.HpResource === item.upd!.MedKit?.HpResource)
{
// e.g. bandages with multiple use
// Both null === both max resoruce left
// Both undefined === both max resoruce left
return item;
}
// Armors/helmets etc
if (
isGearAndHasSlots
&& rootItemBeingAdded.upd.Repairable?.Durability === item.upd.Repairable?.Durability
&& rootItemBeingAdded.upd.Repairable?.MaxDurability === item.upd.Repairable?.MaxDurability
&& rootItemBeingAdded.upd!.Repairable?.Durability === item.upd!.Repairable?.Durability
&& rootItemBeingAdded.upd!.Repairable?.MaxDurability === item.upd!.Repairable?.MaxDurability
)
{
return item;
}
}
return null;
return undefined;
}
/**
@ -951,7 +951,7 @@ export class FenceService
// Healing items
if (itemRoot.upd?.MedKit)
{
const itemTotalMax = itemTemplate._props.MaxHpResource;
const itemTotalMax = itemTemplate._props.MaxHpResource!;
const current = itemRoot.upd.MedKit.HpResource;
// Current and max match, no adjustment necessary
@ -981,7 +981,7 @@ export class FenceService
protected getMatchingItemLimit(
itemTypeLimits: Record<string, { current: number, max: number }>,
itemTpl: string,
): { current: number, max: number }
): { current: number, max: number } | undefined
{
for (const baseTypeKey in itemTypeLimits)
{
@ -1143,20 +1143,20 @@ export class FenceService
protected randomiseArmorModDurability(armor: Item[], itemDbDetails: ITemplateItem): void
{
// Armor has no mods, make no changes
const hasMods = itemDbDetails._props.Slots.length > 0;
const hasMods = (itemDbDetails._props.Slots?.length ?? 0) > 0;
if (!hasMods)
{
return;
}
// Check for and adjust soft insert durability values
const requiredSlots = itemDbDetails._props.Slots.filter((slot) => slot._required);
const hasRequiredSlots = requiredSlots.length > 0;
const requiredSlots = itemDbDetails._props.Slots?.filter((slot) => slot._required);
const hasRequiredSlots = (requiredSlots?.length ?? 0) > 0;
if (hasRequiredSlots)
{
for (const requiredSlot of requiredSlots)
for (const requiredSlot of requiredSlots!)
{
const modItemDbDetails = this.itemHelper.getItem(requiredSlot._props.filters[0].Plate)[1];
const modItemDbDetails = this.itemHelper.getItem(requiredSlot._props.filters[0].Plate!)[1];
const durabilityValues = this.getRandomisedArmorDurabilityValues(
modItemDbDetails,
this.traderConfig.fence.armorMaxDurabilityPercentMinMax,
@ -1170,42 +1170,42 @@ export class FenceService
// Find items mod to apply dura changes to
const modItemToAdjust = armor.find(
(mod) => mod.slotId.toLowerCase() === requiredSlot._name.toLowerCase(),
);
(mod) => mod.slotId!.toLowerCase() === requiredSlot._name.toLowerCase(),
)!;
this.itemHelper.addUpdObjectToItem(modItemToAdjust);
if (!modItemToAdjust.upd.Repairable)
if (!modItemToAdjust.upd!.Repairable)
{
modItemToAdjust.upd.Repairable = {
Durability: modItemDbDetails._props.MaxDurability,
MaxDurability: modItemDbDetails._props.MaxDurability,
modItemToAdjust.upd!.Repairable = {
Durability: modItemDbDetails._props.MaxDurability!,
MaxDurability: modItemDbDetails._props.MaxDurability!,
};
}
modItemToAdjust.upd.Repairable.Durability = durabilityValues.Durability;
modItemToAdjust.upd.Repairable.MaxDurability = durabilityValues.MaxDurability;
modItemToAdjust.upd!.Repairable.Durability = durabilityValues.Durability;
modItemToAdjust.upd!.Repairable.MaxDurability = durabilityValues.MaxDurability;
// 25% chance to add shots to visor when its below max durability
if (
this.randomUtil.getChance100(25)
&& modItemToAdjust.parentId === BaseClasses.ARMORED_EQUIPMENT
&& modItemToAdjust.slotId === "mod_equipment_000"
&& modItemToAdjust.upd.Repairable.Durability < modItemDbDetails._props.MaxDurability
&& modItemToAdjust.upd!.Repairable.Durability < modItemDbDetails._props.MaxDurability!
)
{
// Is damaged
modItemToAdjust.upd.FaceShield = { Hits: this.randomUtil.getInt(1, 3) };
modItemToAdjust.upd!.FaceShield = { Hits: this.randomUtil.getInt(1, 3) };
}
}
}
// Check for and adjust plate durability values
const plateSlots = itemDbDetails._props.Slots.filter((slot) =>
const plateSlots = itemDbDetails._props.Slots?.filter((slot) =>
this.itemHelper.isRemovablePlateSlot(slot._name),
);
if (plateSlots.length > 0)
if ((plateSlots?.length ?? 0) > 0)
{
for (const plateSlot of plateSlots)
for (const plateSlot of plateSlots!)
{
// Chance to not add plate
if (!this.randomUtil.getChance100(this.traderConfig.fence.chancePlateExistsInArmorPercent))
@ -1226,19 +1226,19 @@ export class FenceService
);
// Find items mod to apply dura changes to
const modItemToAdjust = armor.find((mod) => mod.slotId.toLowerCase() === plateSlot._name.toLowerCase());
this.itemHelper.addUpdObjectToItem(modItemToAdjust);
const modItemToAdjust = armor.find((mod) => mod.slotId!.toLowerCase() === plateSlot._name.toLowerCase());
this.itemHelper.addUpdObjectToItem(modItemToAdjust!);
if (!modItemToAdjust.upd.Repairable)
if (!modItemToAdjust?.upd?.Repairable)
{
modItemToAdjust.upd.Repairable = {
Durability: modItemDbDetails._props.MaxDurability,
MaxDurability: modItemDbDetails._props.MaxDurability,
modItemToAdjust!.upd!.Repairable = {
Durability: modItemDbDetails._props.MaxDurability!,
MaxDurability: modItemDbDetails._props.MaxDurability!,
};
}
modItemToAdjust.upd.Repairable.Durability = durabilityValues.Durability;
modItemToAdjust.upd.Repairable.MaxDurability = durabilityValues.MaxDurability;
modItemToAdjust!.upd!.Repairable.Durability = durabilityValues.Durability;
modItemToAdjust!.upd!.Repairable.MaxDurability = durabilityValues.MaxDurability;
}
}
}
@ -1261,7 +1261,7 @@ export class FenceService
// No override, use stack max size from item db
return itemDbDetails._props.StackMaxSize === 1
? 1
: this.randomUtil.getInt(itemDbDetails._props.StackMinRandom, itemDbDetails._props.StackMaxRandom);
: this.randomUtil.getInt(itemDbDetails._props.StackMinRandom!, itemDbDetails._props.StackMaxRandom!);
}
// Check for override in config, use values if exists
@ -1326,7 +1326,7 @@ export class FenceService
protected presetModItemWillBeRemoved(weaponMod: Item, itemsBeingDeleted: string[]): boolean
{
const slotIdsThatCanFail = this.traderConfig.fence.presetSlotsToRemoveChancePercent;
const removalChance = slotIdsThatCanFail[weaponMod.slotId];
const removalChance = slotIdsThatCanFail[weaponMod.slotId!];
if (!removalChance)
{
return false;
@ -1355,9 +1355,9 @@ export class FenceService
}
// Randomise hp resource of med items
if ("MaxHpResource" in itemDetails._props && itemDetails._props.MaxHpResource > 0)
if ("MaxHpResource" in itemDetails._props && (itemDetails._props.MaxHpResource ?? 0) > 0)
{
itemToAdjust.upd.MedKit = { HpResource: this.randomUtil.getInt(1, itemDetails._props.MaxHpResource) };
itemToAdjust.upd!.MedKit = { HpResource: this.randomUtil.getInt(1, itemDetails._props.MaxHpResource!) };
}
// Randomise armor durability
@ -1365,14 +1365,14 @@ export class FenceService
(itemDetails._parent === BaseClasses.ARMORED_EQUIPMENT
|| itemDetails._parent === BaseClasses.FACECOVER
|| itemDetails._parent === BaseClasses.ARMOR_PLATE)
&& itemDetails._props.MaxDurability > 0
&& (itemDetails._props.MaxDurability ?? 0) > 0
)
{
const values = this.getRandomisedArmorDurabilityValues(
itemDetails,
this.traderConfig.fence.armorMaxDurabilityPercentMinMax,
);
itemToAdjust.upd.Repairable = { Durability: values.Durability, MaxDurability: values.MaxDurability };
itemToAdjust.upd!.Repairable = { Durability: values.Durability, MaxDurability: values.MaxDurability };
return;
}
@ -1381,25 +1381,25 @@ export class FenceService
if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.WEAPON))
{
const weaponDurabilityLimits = this.traderConfig.fence.weaponDurabilityPercentMinMax;
const maxDuraMin = (weaponDurabilityLimits.max.min / 100) * itemDetails._props.MaxDurability;
const maxDuraMax = (weaponDurabilityLimits.max.max / 100) * itemDetails._props.MaxDurability;
const maxDuraMin = (weaponDurabilityLimits.max.min / 100) * itemDetails._props.MaxDurability!;
const maxDuraMax = (weaponDurabilityLimits.max.max / 100) * itemDetails._props.MaxDurability!;
const chosenMaxDurability = this.randomUtil.getInt(maxDuraMin, maxDuraMax);
const currentDuraMin = (weaponDurabilityLimits.current.min / 100) * itemDetails._props.MaxDurability;
const currentDuraMax = (weaponDurabilityLimits.current.max / 100) * itemDetails._props.MaxDurability;
const currentDuraMin = (weaponDurabilityLimits.current.min / 100) * itemDetails._props.MaxDurability!;
const currentDuraMax = (weaponDurabilityLimits.current.max / 100) * itemDetails._props.MaxDurability!;
const currentDurability = Math.min(
this.randomUtil.getInt(currentDuraMin, currentDuraMax),
chosenMaxDurability,
);
itemToAdjust.upd.Repairable = { Durability: currentDurability, MaxDurability: chosenMaxDurability };
itemToAdjust.upd!.Repairable = { Durability: currentDurability, MaxDurability: chosenMaxDurability };
return;
}
if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.REPAIR_KITS))
{
itemToAdjust.upd.RepairKit = { Resource: this.randomUtil.getInt(1, itemDetails._props.MaxRepairResource) };
itemToAdjust.upd!.RepairKit = { Resource: this.randomUtil.getInt(1, itemDetails._props.MaxRepairResource!) };
return;
}
@ -1407,23 +1407,23 @@ export class FenceService
// Mechanical key + has limited uses
if (
this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.KEY_MECHANICAL)
&& itemDetails._props.MaximumNumberOfUsage > 1
&& (itemDetails._props.MaximumNumberOfUsage ?? 0) > 1
)
{
itemToAdjust.upd.Key = {
NumberOfUsages: this.randomUtil.getInt(0, itemDetails._props.MaximumNumberOfUsage - 1),
itemToAdjust.upd!.Key = {
NumberOfUsages: this.randomUtil.getInt(0, itemDetails._props.MaximumNumberOfUsage! - 1),
};
return;
}
// Randomise items that use resources (e.g. fuel)
if (itemDetails._props.MaxResource > 0)
if ((itemDetails._props.MaxResource ?? 0) > 0)
{
const resourceMax = itemDetails._props.MaxResource;
const resourceCurrent = this.randomUtil.getInt(1, itemDetails._props.MaxResource);
const resourceMax = itemDetails._props.MaxResource!;
const resourceCurrent = this.randomUtil.getInt(1, itemDetails._props.MaxResource!);
itemToAdjust.upd.Resource = { Value: resourceMax - resourceCurrent, UnitsConsumed: resourceCurrent };
itemToAdjust.upd!.Resource = { Value: resourceMax - resourceCurrent, UnitsConsumed: resourceCurrent };
}
}
@ -1438,12 +1438,12 @@ export class FenceService
equipmentDurabilityLimits: IItemDurabilityCurrentMax,
): Repairable
{
const maxDuraMin = (equipmentDurabilityLimits.max.min / 100) * itemDetails._props.MaxDurability;
const maxDuraMax = (equipmentDurabilityLimits.max.max / 100) * itemDetails._props.MaxDurability;
const maxDuraMin = (equipmentDurabilityLimits.max.min / 100) * itemDetails._props.MaxDurability!;
const maxDuraMax = (equipmentDurabilityLimits.max.max / 100) * itemDetails._props.MaxDurability!;
const chosenMaxDurability = this.randomUtil.getInt(maxDuraMin, maxDuraMax);
const currentDuraMin = (equipmentDurabilityLimits.current.min / 100) * itemDetails._props.MaxDurability;
const currentDuraMax = (equipmentDurabilityLimits.current.max / 100) * itemDetails._props.MaxDurability;
const currentDuraMin = (equipmentDurabilityLimits.current.min / 100) * itemDetails._props.MaxDurability!;
const currentDuraMax = (equipmentDurabilityLimits.current.max / 100) * itemDetails._props.MaxDurability!;
const chosenCurrentDurability = Math.min(
this.randomUtil.getInt(currentDuraMin, currentDuraMax),
chosenMaxDurability,
@ -1486,7 +1486,7 @@ export class FenceService
*/
protected getFenceRefreshTime(): number
{
const fence = this.traderConfig.updateTime.find((x) => x.traderId === Traders.FENCE).seconds;
const fence = this.traderConfig.updateTime.find((x) => x.traderId === Traders.FENCE)!.seconds;
return this.randomUtil.getInt(fence.min, fence.max);
}
@ -1498,7 +1498,7 @@ export class FenceService
*/
public getFenceInfo(pmcData: IPmcData): IFenceLevel
{
const fenceSettings = this.databaseServer.getTables().globals.config.FenceSettings;
const fenceSettings = this.databaseServer.getTables().globals!.config.FenceSettings;
const pmcFenceInfo = pmcData.TradersInfo[fenceSettings.FenceId];
if (!pmcFenceInfo)
@ -1532,11 +1532,11 @@ export class FenceService
public amendOrRemoveFenceOffer(assortId: string, buyCount: number): void
{
let isNormalAssort = true;
let fenceAssortItem = this.fenceAssort.items.find((item) => item._id === assortId);
let fenceAssortItem = this.fenceAssort!.items.find((item) => item._id === assortId);
if (!fenceAssortItem)
{
// Not in main assorts, check secondary section
fenceAssortItem = this.fenceDiscountAssort.items.find((item) => item._id === assortId);
fenceAssortItem = this.fenceDiscountAssort!.items.find((item) => item._id === assortId);
if (!fenceAssortItem)
{
this.logger.error(this.localisationService.getText("fence-unable_to_find_offer_by_id", assortId));
@ -1547,15 +1547,15 @@ export class FenceService
}
// Player wants to buy whole stack, delete stack
if (fenceAssortItem.upd.StackObjectsCount === buyCount)
if (fenceAssortItem.upd!.StackObjectsCount === buyCount)
{
this.deleteOffer(assortId, isNormalAssort ? this.fenceAssort.items : this.fenceDiscountAssort.items);
this.deleteOffer(assortId, isNormalAssort ? this.fenceAssort!.items : this.fenceDiscountAssort!.items);
return;
}
// Adjust stack size
fenceAssortItem.upd.StackObjectsCount -= buyCount;
fenceAssortItem.upd!.StackObjectsCount! -= buyCount;
}
protected deleteOffer(assortId: string, assorts: Item[]): void
@ -1569,8 +1569,8 @@ export class FenceService
// No offer found in main assort, check discount items
if (indexToRemove === -1)
{
indexToRemove = this.fenceDiscountAssort.items.findIndex((item) => item._id === itemToRemove._id);
this.fenceDiscountAssort.items.splice(indexToRemove, 1);
indexToRemove = this.fenceDiscountAssort!.items.findIndex((item) => item._id === itemToRemove._id);
this.fenceDiscountAssort!.items.splice(indexToRemove, 1);
if (indexToRemove === -1)
{

View File

@ -518,9 +518,9 @@ export class ProfileFixerService
for (const traderId in pmcProfile.TradersInfo)
{
const trader = pmcProfile.TradersInfo[traderId];
if (trader && trader.salesSum === null)
if (trader?.salesSum === undefined)
{
this.logger.warning(`trader ${traderId} has a null salesSum value, resetting to 0`);
this.logger.warning(`trader ${traderId} has a undefined salesSum value, resetting to 0`);
trader.salesSum = 0;
}
}
@ -1096,7 +1096,7 @@ export class ProfileFixerService
{
for (const item of magazineBuild.Items)
{
// Magazine builds can have null items in them, skip those
// Magazine builds can have undefined items in them, skip those
if (!item)
{
continue;
@ -1187,10 +1187,10 @@ export class ProfileFixerService
item.upd.Tag.Name = item.upd.Tag.Name.replace(regxp, "");
}
// Check items with StackObjectsCount (null)
if (item.upd.StackObjectsCount === null)
// Check items with StackObjectsCount (undefined)
if (item.upd?.StackObjectsCount === undefined)
{
this.logger.warning(`Fixed item: ${item._id}s null StackObjectsCount value, now set to 1`);
this.logger.warning(`Fixed item: ${item._id}s undefined StackObjectsCount value, now set to 1`);
item.upd.StackObjectsCount = 1;
}
}
@ -1449,15 +1449,15 @@ export class ProfileFixerService
/**
* If someone has run a mod from pre-3.8.0, it results in an invalid `nextResupply` value
* Resolve this by setting the nextResupply to 0 if it's null
* Resolve this by setting the nextResupply to 0 if it's undefined
*/
protected fixNullTraderNextResupply(pmcProfile: IPmcData): void
{
for (const [traderId, trader] of Object.entries(pmcProfile.TradersInfo))
{
if (trader && trader.nextResupply === null)
if (trader?.nextResupply === undefined)
{
this.logger.warning(`trader ${traderId} has a null nextResupply value, resetting to 0`);
this.logger.warning(`trader ${traderId} has a undefined nextResupply value, resetting to 0`);
trader.nextResupply = 0;
}
}

View File

@ -42,6 +42,7 @@ export class RagfairOfferService
this.ragfairOfferHandler = new RagfairOfferHolder(
this.ragfairConfig.dynamic.offerItemCount.max,
ragfairServerHelper,
profileHelper,
);
}
@ -221,7 +222,7 @@ export class RagfairOfferService
{
const staleOfferUserId = staleOffer.user.id;
const isTrader = this.ragfairServerHelper.isTrader(staleOfferUserId);
const isPlayer = this.ragfairServerHelper.isPlayer(staleOfferUserId.replace(/^pmc/, ""));
const isPlayer = this.profileHelper.isPlayer(staleOfferUserId.replace(/^pmc/, ""));
// Skip trader offers, managed by RagfairServer.update()
if (isTrader)

View File

@ -61,7 +61,7 @@ export class HttpResponseUtil
public nullResponse(): INullResponseData
{
return this.clearString(this.getUnclearedBody(null, 0, undefined));
return this.clearString(this.getUnclearedBody(undefined, 0, undefined));
}
public emptyArrayResponse(): IGetBodyResponseData<any[]>

View File

@ -31,7 +31,7 @@ export class JsonUtil
{
if (prettify)
{
return JSON.stringify(data, null, "\t");
return JSON.stringify(data, undefined, "\t");
}
return JSON.stringify(data);
@ -60,7 +60,11 @@ export class JsonUtil
* @param options Stringify options or a replacer.
* @returns The string converted from the JavaScript value
*/
public serializeJsonC(data: any, filename?: string | null, options?: IStringifyOptions | Reviver): string | undefined
public serializeJsonC(
data: any,
filename?: string | undefined,
options?: IStringifyOptions | Reviver,
): string | undefined
{
try
{
@ -74,13 +78,13 @@ export class JsonUtil
}
}
public serializeJson5(data: any, filename?: string | null, prettify = false): string | undefined
public serializeJson5(data: any, filename?: string | undefined, prettify = false): string | undefined
{
try
{
if (prettify)
{
return stringify(data, null, "\t");
return stringify(data, undefined, "\t");
}
return stringify(data);

View File

@ -1,3 +1,4 @@
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
import { RagfairServerHelper } from "@spt/helpers/RagfairServerHelper";
import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer";
@ -10,6 +11,7 @@ export class RagfairOfferHolder
constructor(
protected maxOffersPerTemplate: number,
protected ragfairServerHelper: RagfairServerHelper,
protected profileHelper: ProfileHelper,
)
{
this.offersById = new Map();
@ -69,7 +71,7 @@ export class RagfairOfferHolder
// If its an NPC PMC offer AND we have already reached the maximum amount of possible offers
// for this template, just dont add in more
if (
!(this.ragfairServerHelper.isTrader(trader) || this.ragfairServerHelper.isPlayer(trader))
!(this.ragfairServerHelper.isTrader(trader) || this.profileHelper.isPlayer(trader))
&& (this.getOffersByTemplate(itemTpl)?.length ?? 0) >= this.maxOffersPerTemplate
)
{

View File

@ -37,9 +37,9 @@ export class RecursiveCloner implements ICloner
{
// If the value of the original property is null, ensure the cloned value is also null
// This fixes an issue where null arrays were incorrectly being converted to empty objects
if (obj[propOf1] === null)
if (obj[propOf1] === null || obj[propOf1] === undefined)
{
newObj[propOf1.toString()] = null;
newObj[propOf1.toString()] = undefined;
continue;
}

View File

@ -163,7 +163,7 @@ export abstract class AbstractWinstonLogger implements ILogger
{
command = {
uuid: crypto.randomUUID(),
cmd: async () => await tmpLogger.log("custom", JSON.stringify(data, null, 4)),
cmd: async () => await tmpLogger.log("custom", JSON.stringify(data, undefined, 4)),
};
}