Project Code Format

Ran the `npm run format` command to bring the entire project in-line with the formatting rules.
This commit is contained in:
Refringe 2024-05-17 15:32:41 -04:00
parent 5def42416b
commit cb169a18b9
No known key found for this signature in database
GPG Key ID: 7715B85B4A6306ED
158 changed files with 1999 additions and 1691 deletions

View File

@ -23,7 +23,7 @@ export class ErrorHandler
this.logger.error(`\nStacktrace:\n${err.stack}`);
}
this.readLine.question("Press Enter to close the window", _ans => this.readLine.close());
this.readLine.question("Press Enter to close the window", (_ans) => this.readLine.close());
this.readLine.on("close", () => process.exit(1));
}
}

View File

@ -2,7 +2,6 @@ import { inject, injectable } from "tsyringe";
import { AchievementController } from "@spt-aki/controllers/AchievementController";
import { ProfileController } from "@spt-aki/controllers/ProfileController";
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
import { IAchievement } from "@spt-aki/models/eft/common/tables/IAchievement";
import { IGetBodyResponseData } from "@spt-aki/models/eft/httpResponse/IGetBodyResponseData";
import { ICompletedAchievementsResponse } from "@spt-aki/models/eft/profile/ICompletedAchievementsResponse";
import { IGetAchievementsResponse } from "@spt-aki/models/eft/profile/IGetAchievementsResponse";

View File

@ -48,7 +48,11 @@ export class BotCallbacks
* Handle singleplayer/settings/bot/difficulties
* @returns dictionary of every bot and its diffiulty settings
*/
public getAllBotDifficulties(url: string, info: IEmptyRequestData, sessionID: string): Record<string, Difficulties>
public getAllBotDifficulties(
url: string,
info: IEmptyRequestData,
sessionID: string,
): Record<string, Difficulties>
{
return this.httpResponse.noBody(this.botController.getAllBotDifficulties());
}

View File

@ -46,7 +46,11 @@ export class CustomizationCallbacks
/**
* Handle CustomizationWear event
*/
public wearClothing(pmcData: IPmcData, body: IWearClothingRequestData, sessionID: string): IItemEventRouterResponse
public wearClothing(
pmcData: IPmcData,
body: IWearClothingRequestData,
sessionID: string,
): IItemEventRouterResponse
{
return this.customizationController.wearClothing(pmcData, body, sessionID);
}

View File

@ -88,7 +88,11 @@ export class DataCallbacks
* Handle client/account/customization
* @returns string[]
*/
public getTemplateCharacter(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData<string[]>
public getTemplateCharacter(
url: string,
info: IEmptyRequestData,
sessionID: string,
): IGetBodyResponseData<string[]>
{
return this.httpResponse.getBody(this.databaseServer.getTables().templates.character);
}

View File

@ -47,8 +47,7 @@ export class DialogueCallbacks implements OnUpdate
@inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil,
@inject("DialogueController") protected dialogueController: DialogueController,
)
{
}
{}
/**
* Handle client/friend/list
@ -276,11 +275,7 @@ export class DialogueCallbacks implements OnUpdate
return this.httpResponse.emptyArrayResponse();
}
public createGroupMail(
url: string,
info: ICreateGroupMailRequest,
sessionID: string,
): IGetBodyResponseData<any[]>
public createGroupMail(url: string, info: ICreateGroupMailRequest, sessionID: string): IGetBodyResponseData<any[]>
{
throw new Error("Method not implemented.");
}
@ -294,11 +289,7 @@ export class DialogueCallbacks implements OnUpdate
throw new Error("Method not implemented.");
}
public addUserToMail(
url: string,
info: IAddUserGroupMailRequest,
sessionID: string,
): IGetBodyResponseData<any[]>
public addUserToMail(url: string, info: IAddUserGroupMailRequest, sessionID: string): IGetBodyResponseData<any[]>
{
throw new Error("Method not implemented.");
}

View File

@ -56,7 +56,11 @@ export class GameCallbacks implements OnLoad
* Handle client/game/start
* @returns IGameStartResponse
*/
public gameStart(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData<IGameStartResponse>
public gameStart(
url: string,
info: IEmptyRequestData,
sessionID: string,
): IGetBodyResponseData<IGameStartResponse>
{
const today = new Date().toUTCString();
const startTimeStampMS = Date.parse(today);

View File

@ -102,7 +102,11 @@ export class InventoryCallbacks
return this.inventoryController.foldItem(pmcData, body, sessionID);
}
public toggleItem(pmcData: IPmcData, body: IInventoryToggleRequestData, sessionID: string): IItemEventRouterResponse
public toggleItem(
pmcData: IPmcData,
body: IInventoryToggleRequestData,
sessionID: string,
): IItemEventRouterResponse
{
return this.inventoryController.toggleItem(pmcData, body, sessionID);
}

View File

@ -101,22 +101,14 @@ export class MatchCallbacks
/** Handle client/match/group/invite/decline */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public declineGroupInvite(
url: string,
info: IRequestIdRequest,
sessionId: string,
): IGetBodyResponseData<boolean>
public declineGroupInvite(url: string, info: IRequestIdRequest, sessionId: string): IGetBodyResponseData<boolean>
{
return this.httpResponse.getBody(true);
}
/** Handle client/match/group/invite/cancel */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public cancelGroupInvite(
url: string,
info: IRequestIdRequest,
sessionID: string,
): IGetBodyResponseData<boolean>
public cancelGroupInvite(url: string, info: IRequestIdRequest, sessionID: string): IGetBodyResponseData<boolean>
{
return this.httpResponse.getBody(true);
}
@ -246,21 +238,13 @@ export class MatchCallbacks
}
/** Handle client/match/group/raid/ready */
public raidReady(
url: string,
info: IEmptyRequestData,
sessionId: string,
): IGetBodyResponseData<boolean>
public raidReady(url: string, info: IEmptyRequestData, sessionId: string): IGetBodyResponseData<boolean>
{
return this.httpResponse.getBody(true);
}
/** Handle client/match/group/raid/not-ready */
public notRaidReady(
url: string,
info: IEmptyRequestData,
sessionId: string,
): IGetBodyResponseData<boolean>
public notRaidReady(url: string, info: IEmptyRequestData, sessionId: string): IGetBodyResponseData<boolean>
{
return this.httpResponse.getBody(true);
}

View File

@ -36,9 +36,10 @@ export class NotifierCallbacks
* Take our array of JSON message objects and cast them to JSON strings, so that they can then
* be sent to client as NEWLINE separated strings... yup.
*/
this.notifierController.notifyAsync(tmpSessionID).then((messages: any) =>
messages.map((message: any) => this.jsonUtil.serialize(message)).join("\n"),
).then(text => this.httpServerHelper.sendTextJson(resp, text));
this.notifierController
.notifyAsync(tmpSessionID)
.then((messages: any) => messages.map((message: any) => this.jsonUtil.serialize(message)).join("\n"))
.then((text) => this.httpServerHelper.sendTextJson(resp, text));
}
/** Handle push/notifier/get */

View File

@ -17,7 +17,11 @@ export class WishlistCallbacks
}
/** Handle RemoveFromWishList event */
public removeFromWishlist(pmcData: IPmcData, body: IWishlistActionData, sessionID: string): IItemEventRouterResponse
public removeFromWishlist(
pmcData: IPmcData,
body: IWishlistActionData,
sessionID: string,
): IItemEventRouterResponse
{
return this.wishlistController.removeFromWishList(pmcData, body, sessionID);
}

View File

@ -5,6 +5,7 @@ import { BotGenerator } from "@spt-aki/generators/BotGenerator";
import { BotDifficultyHelper } from "@spt-aki/helpers/BotDifficultyHelper";
import { BotHelper } from "@spt-aki/helpers/BotHelper";
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
import { MinMax } from "@spt-aki/models/common/MinMax";
import { Condition, IGenerateBotsRequestData } from "@spt-aki/models/eft/bot/IGenerateBotsRequestData";
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
import { IBotBase } from "@spt-aki/models/eft/common/tables/IBotBase";
@ -25,7 +26,6 @@ import { MatchBotDetailsCacheService } from "@spt-aki/services/MatchBotDetailsCa
import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
import { MinMax } from "@spt-aki/models/common/MinMax";
@injectable()
export class BotController
@ -94,9 +94,9 @@ export class BotController
{
let difficulty = diffLevel.toLowerCase();
const raidConfig = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION)?.getValue<
IGetRaidConfigurationRequestData
>();
const raidConfig = this.applicationContext
.getLatestValue(ContextVariableType.RAID_CONFIGURATION)
?.getValue<IGetRaidConfigurationRequestData>();
if (!(raidConfig || ignoreRaidSettings))
{
this.logger.error(
@ -109,9 +109,8 @@ export class BotController
const botDifficultyDropDownValue = raidConfig?.wavesSettings.botDifficulty.toLowerCase() ?? "asonline";
if (botDifficultyDropDownValue !== "asonline")
{
difficulty = this.botDifficultyHelper.convertBotDifficultyDropdownToBotDifficulty(
botDifficultyDropDownValue,
);
difficulty
= this.botDifficultyHelper.convertBotDifficultyDropdownToBotDifficulty(botDifficultyDropDownValue);
}
let difficultySettings: Difficulty;
@ -147,7 +146,7 @@ export class BotController
const result = {};
const botDb = this.databaseServer.getTables().bots.types;
const botTypes = Object.keys(WildSpawnTypeNumber).filter(v => Number.isNaN(Number(v)));
const botTypes = Object.keys(WildSpawnTypeNumber).filter((v) => Number.isNaN(Number(v)));
for (let botType of botTypes)
{
const enumType = botType.toLowerCase();
@ -228,12 +227,13 @@ export class BotController
allPmcsHaveSameNameAsPlayer,
pmcLevelRangeForMap,
this.botConfig.presetBatch[condition.Role],
false);
false,
);
conditionPromises.push(this.generateWithBotDetails(condition, botGenerationDetails, sessionId));
}
await Promise.all(conditionPromises).then(p => Promise.all(p));
await Promise.all(conditionPromises).then((p) => Promise.all(p));
return [];
}
@ -254,8 +254,8 @@ export class BotController
allPmcsHaveSameNameAsPlayer: boolean,
pmcLevelRangeForMap: MinMax,
botCountToGenerate: number,
generateAsPmc: boolean): BotGenerationDetails
generateAsPmc: boolean,
): BotGenerationDetails
{
return {
isPmc: generateAsPmc,
@ -357,14 +357,17 @@ export class BotController
* @param request Bot generation request object
* @returns Single IBotBase object
*/
protected async returnSingleBotFromCache(sessionId: string, request: IGenerateBotsRequestData): Promise<IBotBase[]>
protected async returnSingleBotFromCache(
sessionId: string,
request: IGenerateBotsRequestData,
): Promise<IBotBase[]>
{
const pmcProfile = this.profileHelper.getPmcProfile(sessionId);
const requestedBot = request.conditions[0];
const raidSettings = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION)?.getValue<
IGetRaidConfigurationRequestData
>();
const raidSettings = this.applicationContext
.getLatestValue(ContextVariableType.RAID_CONFIGURATION)
?.getValue<IGetRaidConfigurationRequestData>();
const pmcLevelRangeForMap
= this.pmcConfig.locationSpecificPmcLevelOverride[raidSettings.location.toLowerCase()];
@ -372,7 +375,7 @@ export class BotController
const condition: Condition = {
Role: requestedBot.Role,
Limit: 5,
Difficulty: requestedBot.Difficulty
Difficulty: requestedBot.Difficulty,
};
const botGenerationDetails = this.getBotGenerationDetailsForWave(
condition,
@ -380,7 +383,8 @@ export class BotController
false,
pmcLevelRangeForMap,
this.botConfig.presetBatch[requestedBot.Role],
false);
false,
);
// Event bots need special actions to occur, set data up for them
const isEventBot = requestedBot.Role.toLowerCase().includes("event");
@ -475,9 +479,9 @@ export class BotController
public getBotCap(): number
{
const defaultMapCapId = "default";
const raidConfig = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION).getValue<
IGetRaidConfigurationRequestData
>();
const raidConfig = this.applicationContext
.getLatestValue(ContextVariableType.RAID_CONFIGURATION)
.getValue<IGetRaidConfigurationRequestData>();
if (!raidConfig)
{

View File

@ -42,11 +42,11 @@ export class BuildController
const defaultEquipmentPresetsClone = this.cloner.clone(
this.databaseServer.getTables().templates.defaultEquipmentPresets,
);
const playerSecureContainer = profile.characters.pmc.Inventory.items?.find(x =>
x.slotId === secureContainerSlotId,
const playerSecureContainer = profile.characters.pmc.Inventory.items?.find(
(x) => x.slotId === secureContainerSlotId,
);
const firstDefaultItemsSecureContainer = defaultEquipmentPresetsClone[0]?.Items?.find(x =>
x.slotId === secureContainerSlotId,
const firstDefaultItemsSecureContainer = defaultEquipmentPresetsClone[0]?.Items?.find(
(x) => x.slotId === secureContainerSlotId,
);
if (playerSecureContainer && playerSecureContainer?._tpl !== firstDefaultItemsSecureContainer?._tpl)
{
@ -54,7 +54,7 @@ export class BuildController
for (const defaultPreset of defaultEquipmentPresetsClone)
{
// Find presets secure container
const secureContainer = defaultPreset.Items.find(item => item.slotId === secureContainerSlotId);
const secureContainer = defaultPreset.Items.find((item) => item.slotId === secureContainerSlotId);
if (secureContainer)
{
secureContainer._tpl = playerSecureContainer._tpl;
@ -83,15 +83,13 @@ export class BuildController
const newBuild: IWeaponBuild = { Id: body.Id, Name: body.Name, Root: body.Root, Items: body.Items };
const savedWeaponBuilds = this.saveServer.getProfile(sessionId).userbuilds.weaponBuilds;
const existingBuild = savedWeaponBuilds.find(x => x.Id === body.Id);
const existingBuild = savedWeaponBuilds.find((x) => x.Id === body.Id);
if (existingBuild)
{
// exists, replace
this.saveServer.getProfile(sessionId).userbuilds.weaponBuilds.splice(
savedWeaponBuilds.indexOf(existingBuild),
1,
newBuild,
);
this.saveServer
.getProfile(sessionId)
.userbuilds.weaponBuilds.splice(savedWeaponBuilds.indexOf(existingBuild), 1, newBuild);
}
else
{
@ -106,8 +104,8 @@ export class BuildController
const buildType = "equipmentBuilds";
const pmcData = this.profileHelper.getPmcProfile(sessionID);
const existingSavedEquipmentBuilds: IEquipmentBuild[] = this.saveServer.getProfile(sessionID)
.userbuilds[buildType];
const existingSavedEquipmentBuilds: IEquipmentBuild[]
= this.saveServer.getProfile(sessionID).userbuilds[buildType];
// Replace duplicate ID's. The first item is the base item.
// Root ID and the base item ID need to match.
@ -121,17 +119,15 @@ export class BuildController
Items: request.Items,
};
const existingBuild = existingSavedEquipmentBuilds.find(build =>
build.Name === request.Name || build.Id === request.Id,
const existingBuild = existingSavedEquipmentBuilds.find(
(build) => build.Name === request.Name || build.Id === request.Id,
);
if (existingBuild)
{
// Already exists, replace
this.saveServer.getProfile(sessionID).userbuilds[buildType].splice(
existingSavedEquipmentBuilds.indexOf(existingBuild),
1,
newBuild,
);
this.saveServer
.getProfile(sessionID)
.userbuilds[buildType].splice(existingSavedEquipmentBuilds.indexOf(existingBuild), 1, newBuild);
}
else
{
@ -154,7 +150,7 @@ export class BuildController
const magazineBuilds = profile.userbuilds.magazineBuilds;
// Check for id in weapon array first
const matchingWeaponBuild = weaponBuilds.find(weaponBuild => weaponBuild.Id === idToRemove);
const matchingWeaponBuild = weaponBuilds.find((weaponBuild) => weaponBuild.Id === idToRemove);
if (matchingWeaponBuild)
{
weaponBuilds.splice(weaponBuilds.indexOf(matchingWeaponBuild), 1);
@ -163,7 +159,7 @@ export class BuildController
}
// Id not found in weapons, try equipment
const matchingEquipmentBuild = equipmentBuilds.find(equipmentBuild => equipmentBuild.Id === idToRemove);
const matchingEquipmentBuild = equipmentBuilds.find((equipmentBuild) => equipmentBuild.Id === idToRemove);
if (matchingEquipmentBuild)
{
equipmentBuilds.splice(equipmentBuilds.indexOf(matchingEquipmentBuild), 1);
@ -172,7 +168,7 @@ export class BuildController
}
// Id not found in weapons/equipment, try mags
const matchingMagazineBuild = magazineBuilds.find(magBuild => magBuild.Id === idToRemove);
const matchingMagazineBuild = magazineBuilds.find((magBuild) => magBuild.Id === idToRemove);
if (matchingMagazineBuild)
{
magazineBuilds.splice(magazineBuilds.indexOf(matchingMagazineBuild), 1);
@ -207,7 +203,7 @@ export class BuildController
profile.userbuilds.magazineBuilds = [];
}
const existingArrayId = profile.userbuilds.magazineBuilds.findIndex(item => item.Name === request.Name);
const existingArrayId = profile.userbuilds.magazineBuilds.findIndex((item) => item.Name === request.Name);
if (existingArrayId === -1)
{

View File

@ -42,10 +42,10 @@ export class CustomizationController
const suits = this.databaseServer.getTables().traders[traderID].suits;
// Get an inner join of clothing from templates.customization and Ragman's suits array
const matchingSuits = suits.filter(x => x.suiteId in templates);
const matchingSuits = suits.filter((x) => x.suiteId in templates);
// Return all suits that have a side array containing the players side (usec/bear)
return matchingSuits.filter(x => templates[x.suiteId]._props.Side.includes(pmcData.Info.Side));
return matchingSuits.filter((x) => templates[x.suiteId]._props.Side.includes(pmcData.Info.Side));
}
/**
@ -132,7 +132,7 @@ export class CustomizationController
protected getTraderClothingOffer(sessionId: string, offerId: string): ISuit
{
return this.getAllTraderSuits(sessionId).find(x => x._id === offerId);
return this.getAllTraderSuits(sessionId).find((x) => x._id === offerId);
}
/**
@ -180,7 +180,7 @@ export class CustomizationController
output: IItemEventRouterResponse,
): void
{
const relatedItem = pmcData.Inventory.items.find(x => x._id === clothingItem.id);
const relatedItem = pmcData.Inventory.items.find((x) => x._id === clothingItem.id);
if (!relatedItem)
{
this.logger.error(

View File

@ -1,6 +1,8 @@
import { inject, injectAll, injectable } from "tsyringe";
import { IDialogueChatBot } from "@spt-aki/helpers/Dialogue/IDialogueChatBot";
import { DialogueHelper } from "@spt-aki/helpers/DialogueHelper";
import { IFriendRequestData } from "@spt-aki/models/eft/dialog/IFriendRequestData";
import { IFriendRequestSendResponse } from "@spt-aki/models/eft/dialog/IFriendRequestSendResponse";
import { IGetAllAttachmentsResponse } from "@spt-aki/models/eft/dialog/IGetAllAttachmentsResponse";
import { IGetFriendListDataResponse } from "@spt-aki/models/eft/dialog/IGetFriendListDataResponse";
import { IGetMailDialogViewRequestData } from "@spt-aki/models/eft/dialog/IGetMailDialogViewRequestData";
@ -15,8 +17,6 @@ import { ConfigServer } from "@spt-aki/servers/ConfigServer";
import { SaveServer } from "@spt-aki/servers/SaveServer";
import { MailSendService } from "@spt-aki/services/MailSendService";
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
import { IFriendRequestData } from "@spt-aki/models/eft/dialog/IFriendRequestData";
import { IFriendRequestSendResponse } from "@spt-aki/models/eft/dialog/IFriendRequestSendResponse";
@injectable()
export class DialogueController
@ -35,21 +35,21 @@ export class DialogueController
// if give command is disabled or commando commands are disabled
if (!coreConfigs.features?.chatbotFeatures?.commandoEnabled)
{
const sptCommando = this.dialogueChatBots.find(c =>
c.getChatBot()._id.toLocaleLowerCase() === "sptcommando",
const sptCommando = this.dialogueChatBots.find(
(c) => c.getChatBot()._id.toLocaleLowerCase() === "sptcommando",
);
this.dialogueChatBots.splice(this.dialogueChatBots.indexOf(sptCommando), 1);
}
if (!coreConfigs.features?.chatbotFeatures?.sptFriendEnabled)
{
const sptFriend = this.dialogueChatBots.find(c => c.getChatBot()._id.toLocaleLowerCase() === "sptFriend");
const sptFriend = this.dialogueChatBots.find((c) => c.getChatBot()._id.toLocaleLowerCase() === "sptFriend");
this.dialogueChatBots.splice(this.dialogueChatBots.indexOf(sptFriend), 1);
}
}
public registerChatBot(chatBot: IDialogueChatBot): void
{
if (this.dialogueChatBots.some(cb => cb.getChatBot()._id === chatBot.getChatBot()._id))
if (this.dialogueChatBots.some((cb) => cb.getChatBot()._id === chatBot.getChatBot()._id))
{
throw new Error(`The chat bot ${chatBot.getChatBot()._id} being registered already exists!`);
}
@ -74,7 +74,7 @@ export class DialogueController
public getFriendList(sessionID: string): IGetFriendListDataResponse
{
// Force a fake friend called SPT into friend list
return { Friends: this.dialogueChatBots.map(v => v.getChatBot()), Ignore: [], InIgnoreList: [] };
return { Friends: this.dialogueChatBots.map((v) => v.getChatBot()), Ignore: [], InIgnoreList: [] };
}
/**
@ -133,7 +133,7 @@ export class DialogueController
// User to user messages are special in that they need the player to exist in them, add if they don't
if (
messageType === MessageType.USER_MESSAGE
&& !dialog.Users?.find(userDialog => userDialog._id === profile.characters.pmc.sessionId)
&& !dialog.Users?.find((userDialog) => userDialog._id === profile.characters.pmc.sessionId)
)
{
if (!dialog.Users)
@ -209,7 +209,7 @@ export class DialogueController
if (request.type === MessageType.USER_MESSAGE)
{
profile.dialogues[request.dialogId].Users = [];
const chatBot = this.dialogueChatBots.find(cb => cb.getChatBot()._id === request.dialogId);
const chatBot = this.dialogueChatBots.find((cb) => cb.getChatBot()._id === request.dialogId);
if (chatBot)
{
profile.dialogues[request.dialogId].Users.push(chatBot.getChatBot());
@ -233,7 +233,7 @@ export class DialogueController
{
result.push(...dialogUsers);
if (!result.find(userDialog => userDialog._id === fullProfile.info.id))
if (!result.find((userDialog) => userDialog._id === fullProfile.info.id))
{
// Player doesnt exist, add them in before returning
const pmcProfile = fullProfile.characters.pmc;
@ -281,7 +281,7 @@ export class DialogueController
*/
protected messagesHaveUncollectedRewards(messages: Message[]): boolean
{
return messages.some(message => message.items?.data?.length > 0);
return messages.some((message) => message.items?.data?.length > 0);
}
/**
@ -378,10 +378,11 @@ export class DialogueController
{
this.mailSendService.sendPlayerMessageToNpc(sessionId, request.dialogId, request.text);
return this.dialogueChatBots.find(cb => cb.getChatBot()._id === request.dialogId)?.handleMessage(
sessionId,
request,
) ?? request.dialogId;
return (
this.dialogueChatBots
.find((cb) => cb.getChatBot()._id === request.dialogId)
?.handleMessage(sessionId, request) ?? request.dialogId
);
}
/**
@ -394,7 +395,7 @@ export class DialogueController
{
const timeNow = this.timeUtil.getTimestamp();
const dialogs = this.dialogueHelper.getDialogsForProfile(sessionId);
return dialogs[dialogueId].messages.filter(message => timeNow < message.dt + message.maxStorageTime);
return dialogs[dialogueId].messages.filter((message) => timeNow < message.dt + message.maxStorageTime);
}
/**
@ -404,7 +405,7 @@ export class DialogueController
*/
protected getMessagesWithAttachments(messages: Message[]): Message[]
{
return messages.filter(message => message.items?.data?.length > 0);
return messages.filter((message) => message.items?.data?.length > 0);
}
/**
@ -453,12 +454,8 @@ export class DialogueController
}
/** Handle client/friend/request/send */
public sendFriendRequest(
sessionID: string,
request: IFriendRequestData
): IFriendRequestSendResponse
public sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse
{
return { status: 0, requestId: "12345", retryAfter: 600 }
return { status: 0, requestId: "12345", retryAfter: 600 };
}
}

View File

@ -359,8 +359,8 @@ export class GameController
for (const positionToAdd of positionsToAdd)
{
// Exists already, add new items to existing positions pool
const existingLootPosition = mapLooseLoot.spawnpoints.find(x =>
x.template.Id === positionToAdd.template.Id,
const existingLootPosition = mapLooseLoot.spawnpoints.find(
(x) => x.template.Id === positionToAdd.template.Id,
);
if (existingLootPosition)
{
@ -390,7 +390,7 @@ export class GameController
const mapLootAdjustmentsDict = adjustments[mapId];
for (const lootKey in mapLootAdjustmentsDict)
{
const lootPostionToAdjust = mapLooseLootData.spawnpoints.find(x => x.template.Id === lootKey);
const lootPostionToAdjust = mapLooseLootData.spawnpoints.find((x) => x.template.Id === lootKey);
if (!lootPostionToAdjust)
{
this.logger.warning(`Unable to adjust loot position: ${lootKey} on map: ${mapId}`);
@ -423,7 +423,7 @@ export class GameController
for (const botToLimit of this.locationConfig.botTypeLimits[mapId])
{
const index = map.base.MinMaxBots.findIndex(x => x.WildSpawnType === botToLimit.type);
const index = map.base.MinMaxBots.findIndex((x) => x.WildSpawnType === botToLimit.type);
if (index !== -1)
{
// Existing bot type found in MinMaxBots array, edit
@ -452,8 +452,8 @@ export class GameController
{
const profile = this.profileHelper.getPmcProfile(sessionID);
const gameTime
= profile.Stats?.Eft.OverallCounters.Items?.find(counter =>
counter.Key.includes("LifeTime") && counter.Key.includes("Pmc"),
= profile.Stats?.Eft.OverallCounters.Items?.find(
(counter) => counter.Key.includes("LifeTime") && counter.Key.includes("Pmc"),
)?.Value ?? 0;
const config: IGameConfigResponse = {
@ -598,12 +598,13 @@ export class GameController
let hpRegenPerHour = 456.6;
// Set new values, whatever is smallest
energyRegenPerHour += pmcProfile.Bonuses.filter(bonus => bonus.type === BonusType.ENERGY_REGENERATION)
.reduce((sum, curr) => sum + curr.value, 0);
hydrationRegenPerHour += pmcProfile.Bonuses.filter(bonus =>
bonus.type === BonusType.HYDRATION_REGENERATION,
energyRegenPerHour += pmcProfile.Bonuses.filter(
(bonus) => bonus.type === BonusType.ENERGY_REGENERATION,
).reduce((sum, curr) => sum + curr.value, 0);
hpRegenPerHour += pmcProfile.Bonuses.filter(bonus => bonus.type === BonusType.HEALTH_REGENERATION).reduce(
hydrationRegenPerHour += pmcProfile.Bonuses.filter(
(bonus) => bonus.type === BonusType.HYDRATION_REGENERATION,
).reduce((sum, curr) => sum + curr.value, 0);
hpRegenPerHour += pmcProfile.Bonuses.filter((bonus) => bonus.type === BonusType.HEALTH_REGENERATION).reduce(
(sum, curr) => sum + curr.value,
0,
);
@ -738,13 +739,13 @@ export class GameController
const currentTimeStamp = this.timeUtil.getTimestamp();
// One day post-profile creation
if (currentTimeStamp > (timeStampProfileCreated + oneDaySeconds))
if (currentTimeStamp > timeStampProfileCreated + oneDaySeconds)
{
this.giftService.sendPraporStartingGift(pmcProfile.sessionId, 1);
}
// Two day post-profile creation
if (currentTimeStamp > (timeStampProfileCreated + oneDaySeconds * 2))
if (currentTimeStamp > timeStampProfileCreated + oneDaySeconds * 2)
{
this.giftService.sendPraporStartingGift(pmcProfile.sessionId, 2);
}
@ -841,8 +842,11 @@ export class GameController
{
const modDetails = activeMods[modKey];
if (
fullProfile.aki.mods.some(x =>
x.author === modDetails.author && x.name === modDetails.name && x.version === modDetails.version,
fullProfile.aki.mods.some(
(x) =>
x.author === modDetails.author
&& x.name === modDetails.name
&& x.version === modDetails.version,
)
)
{
@ -957,8 +961,8 @@ export class GameController
protected adjustLabsRaiderSpawnRate(): void
{
const labsBase = this.databaseServer.getTables().locations.laboratory.base;
const nonTriggerLabsBossSpawns = labsBase.BossLocationSpawn.filter(x =>
x.TriggerId === "" && x.TriggerName === "",
const nonTriggerLabsBossSpawns = labsBase.BossLocationSpawn.filter(
(x) => x.TriggerId === "" && x.TriggerName === "",
);
if (nonTriggerLabsBossSpawns)
{

View File

@ -60,12 +60,16 @@ export class HealthController
* @param sessionID Player id
* @returns IItemEventRouterResponse
*/
public offraidHeal(pmcData: IPmcData, request: IOffraidHealRequestData, sessionID: string): IItemEventRouterResponse
public offraidHeal(
pmcData: IPmcData,
request: IOffraidHealRequestData,
sessionID: string,
): IItemEventRouterResponse
{
const output = this.eventOutputHolder.getOutput(sessionID);
// Update medkit used (hpresource)
const healingItemToUse = pmcData.Inventory.items.find(item => item._id === request.item);
const healingItemToUse = pmcData.Inventory.items.find((item) => item._id === request.item);
if (!healingItemToUse)
{
const errorMessage = this.localisationService.getText(
@ -113,7 +117,7 @@ export class HealthController
const output = this.eventOutputHolder.getOutput(sessionID);
let resourceLeft = 0;
const itemToConsume = pmcData.Inventory.items.find(x => x._id === request.item);
const itemToConsume = pmcData.Inventory.items.find((x) => x._id === request.item);
if (!itemToConsume)
{
// Item not found, very bad

View File

@ -11,7 +11,6 @@ import {
HideoutArea,
ITaskConditionCounter,
Product,
Production,
ScavCase,
} from "@spt-aki/models/eft/common/tables/IBotBase";
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
@ -105,7 +104,7 @@ export class HideoutController
{
const items = request.items.map((reqItem) =>
{
const item = pmcData.Inventory.items.find(invItem => invItem._id === reqItem.id);
const item = pmcData.Inventory.items.find((invItem) => invItem._id === reqItem.id);
return { inventoryItem: item, requestedItem: reqItem };
});
@ -138,7 +137,7 @@ export class HideoutController
}
// Construction time management
const profileHideoutArea = pmcData.Hideout.Areas.find(area => area.type === request.areaType);
const profileHideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType);
if (!profileHideoutArea)
{
this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType));
@ -147,9 +146,9 @@ export class HideoutController
return;
}
const hideoutDataDb = this.databaseServer.getTables().hideout.areas.find(area =>
area.type === request.areaType,
);
const hideoutDataDb = this.databaseServer
.getTables()
.hideout.areas.find((area) => area.type === request.areaType);
if (!hideoutDataDb)
{
this.logger.error(
@ -191,7 +190,7 @@ export class HideoutController
{
const db = this.databaseServer.getTables();
const profileHideoutArea = pmcData.Hideout.Areas.find(area => area.type === request.areaType);
const profileHideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType);
if (!profileHideoutArea)
{
this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType));
@ -205,7 +204,7 @@ export class HideoutController
profileHideoutArea.completeTime = 0;
profileHideoutArea.constructing = false;
const hideoutData = db.hideout.areas.find(area => area.type === profileHideoutArea.type);
const hideoutData = db.hideout.areas.find((area) => area.type === profileHideoutArea.type);
if (!hideoutData)
{
this.logger.error(
@ -263,11 +262,11 @@ export class HideoutController
*/
protected checkAndUpgradeWall(pmcData: IPmcData): void
{
const medStation = pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.MEDSTATION);
const waterCollector = pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.WATER_COLLECTOR);
const medStation = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.MEDSTATION);
const waterCollector = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.WATER_COLLECTOR);
if (medStation?.level >= 1 && waterCollector?.level >= 1)
{
const wall = pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.EMERGENCY_WALL);
const wall = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.EMERGENCY_WALL);
if (wall?.level === 0)
{
wall.level = 3;
@ -309,9 +308,9 @@ export class HideoutController
}
// Some areas like gun stand have a child area linked to it, it needs to do the same as above
const childDbArea = this.databaseServer.getTables().hideout.areas.find(x =>
x.parentArea === dbHideoutArea._id,
);
const childDbArea = this.databaseServer
.getTables()
.hideout.areas.find((x) => x.parentArea === dbHideoutArea._id);
if (childDbArea)
{
// Add key/value to `hideoutAreaStashes` dictionary - used to link hideout area to inventory stash by its id
@ -321,8 +320,8 @@ export class HideoutController
}
// Set child area level to same as parent area
pmcData.Hideout.Areas.find(x => x.type === childDbArea.type).level = pmcData.Hideout.Areas.find(x =>
x.type === profileParentHideoutArea.type,
pmcData.Hideout.Areas.find((x) => x.type === childDbArea.type).level = pmcData.Hideout.Areas.find(
(x) => x.type === profileParentHideoutArea.type,
).level;
// Add/upgrade stash item in player inventory
@ -340,9 +339,13 @@ export class HideoutController
* @param dbHideoutData Hideout area from db being upgraded
* @param hideoutStage Stage area upgraded to
*/
protected addUpdateInventoryItemToProfile(pmcData: IPmcData, dbHideoutData: IHideoutArea, hideoutStage: Stage): void
protected addUpdateInventoryItemToProfile(
pmcData: IPmcData,
dbHideoutData: IHideoutArea,
hideoutStage: Stage,
): void
{
const existingInventoryItem = pmcData.Inventory.items.find(x => x._id === dbHideoutData._id);
const existingInventoryItem = pmcData.Inventory.items.find((x) => x._id === dbHideoutData._id);
if (existingInventoryItem)
{
// Update existing items container tpl to point to new id (tpl)
@ -399,11 +402,11 @@ export class HideoutController
const itemsToAdd = Object.entries(addItemToHideoutRequest.items).map((kvp) =>
{
const item = pmcData.Inventory.items.find(invItem => invItem._id === kvp[1].id);
const item = pmcData.Inventory.items.find((invItem) => invItem._id === kvp[1].id);
return { inventoryItem: item, requestedItem: kvp[1], slot: kvp[0] };
});
const hideoutArea = pmcData.Hideout.Areas.find(area => area.type === addItemToHideoutRequest.areaType);
const hideoutArea = pmcData.Hideout.Areas.find((area) => area.type === addItemToHideoutRequest.areaType);
if (!hideoutArea)
{
this.logger.error(
@ -430,12 +433,14 @@ export class HideoutController
// Add item to area.slots
const destinationLocationIndex = Number(item.slot);
const hideoutSlotIndex = hideoutArea.slots.findIndex(x => x.locationIndex === destinationLocationIndex);
hideoutArea.slots[hideoutSlotIndex].item = [{
const hideoutSlotIndex = hideoutArea.slots.findIndex((x) => x.locationIndex === destinationLocationIndex);
hideoutArea.slots[hideoutSlotIndex].item = [
{
_id: item.inventoryItem._id,
_tpl: item.inventoryItem._tpl,
upd: item.inventoryItem.upd,
}];
},
];
this.inventoryHelper.removeItem(pmcData, item.inventoryItem._id, sessionID, output);
}
@ -462,7 +467,7 @@ export class HideoutController
{
const output = this.eventOutputHolder.getOutput(sessionID);
const hideoutArea = pmcData.Hideout.Areas.find(area => area.type === request.areaType);
const hideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType);
if (!hideoutArea)
{
this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType));
@ -519,7 +524,7 @@ export class HideoutController
const slotIndexToRemove = removeResourceRequest.slots[0];
// Assume only one item in slot
const itemToReturn = hideoutArea.slots.find(slot => slot.locationIndex === slotIndexToRemove).item[0];
const itemToReturn = hideoutArea.slots.find((slot) => slot.locationIndex === slotIndexToRemove).item[0];
const request: IAddItemDirectRequest = {
itemWithModsToAdd: [itemToReturn],
@ -536,7 +541,7 @@ export class HideoutController
}
// Remove items from slot, locationIndex remains
const hideoutSlotIndex = hideoutArea.slots.findIndex(slot => slot.locationIndex === slotIndexToRemove);
const hideoutSlotIndex = hideoutArea.slots.findIndex((slot) => slot.locationIndex === slotIndexToRemove);
hideoutArea.slots[hideoutSlotIndex].item = undefined;
return output;
@ -561,7 +566,7 @@ export class HideoutController
// Force a production update (occur before area is toggled as it could be generator and doing it after generator enabled would cause incorrect calculaton of production progress)
this.hideoutHelper.updatePlayerHideout(sessionID);
const hideoutArea = pmcData.Hideout.Areas.find(area => area.type === request.areaType);
const hideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType);
if (!hideoutArea)
{
this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType));
@ -591,20 +596,20 @@ export class HideoutController
this.hideoutHelper.registerProduction(pmcData, body, sessionID);
// Find the recipe of the production
const recipe = this.databaseServer.getTables().hideout.production.find(p => p._id === body.recipeId);
const recipe = this.databaseServer.getTables().hideout.production.find((p) => p._id === body.recipeId);
// Find the actual amount of items we need to remove because body can send weird data
const recipeRequirementsClone = this.cloner.clone(
recipe.requirements.filter(i => i.type === "Item" || i.type === "Tool"),
recipe.requirements.filter((i) => i.type === "Item" || i.type === "Tool"),
);
const output = this.eventOutputHolder.getOutput(sessionID);
const itemsToDelete = body.items.concat(body.tools);
for (const itemToDelete of itemsToDelete)
{
const itemToCheck = pmcData.Inventory.items.find(i => i._id === itemToDelete.id);
const requirement = recipeRequirementsClone.find(requirement =>
requirement.templateId === itemToCheck._tpl,
const itemToCheck = pmcData.Inventory.items.find((i) => i._id === itemToDelete.id);
const requirement = recipeRequirementsClone.find(
(requirement) => requirement.templateId === itemToCheck._tpl,
);
// Handle tools not having a `count`, but always only requiring 1
@ -644,7 +649,7 @@ export class HideoutController
for (const requestedItem of body.items)
{
const inventoryItem = pmcData.Inventory.items.find(item => item._id === requestedItem.id);
const inventoryItem = pmcData.Inventory.items.find((item) => item._id === requestedItem.id);
if (!inventoryItem)
{
this.logger.error(
@ -666,7 +671,7 @@ export class HideoutController
}
}
const recipe = this.databaseServer.getTables().hideout.scavcase.find(r => r._id === body.recipeId);
const recipe = this.databaseServer.getTables().hideout.scavcase.find((r) => r._id === body.recipeId);
if (!recipe)
{
this.logger.error(
@ -678,7 +683,9 @@ export class HideoutController
// @Important: Here we need to be very exact:
// - normal recipe: Production time value is stored in attribute "productionTime" with small "p"
// - scav case recipe: Production time value is stored in attribute "ProductionTime" with capital "P"
const adjustedCraftTime = recipe.ProductionTime - this.hideoutHelper.getSkillProductionTimeReduction(
const adjustedCraftTime
= recipe.ProductionTime
- this.hideoutHelper.getSkillProductionTimeReduction(
pmcData,
recipe.ProductionTime,
SkillTypes.CRAFTING,
@ -770,7 +777,7 @@ export class HideoutController
return output;
}
const recipe = hideoutDb.production.find(r => r._id === request.recipeId);
const recipe = hideoutDb.production.find((r) => r._id === request.recipeId);
if (recipe)
{
this.handleRecipe(sessionID, recipe, pmcData, request, output);
@ -778,7 +785,7 @@ export class HideoutController
return output;
}
const scavCase = hideoutDb.scavcase.find(r => r._id === request.recipeId);
const scavCase = hideoutDb.scavcase.find((r) => r._id === request.recipeId);
if (scavCase)
{
this.handleScavCase(sessionID, pmcData, request, output);
@ -936,7 +943,7 @@ export class HideoutController
}
// Check if the recipe is the same as the last one - get bonus when crafting same thing multiple times
const area = pmcData.Hideout.Areas.find(area => area.type === recipe.areaType);
const area = pmcData.Hideout.Areas.find((area) => area.type === recipe.areaType);
if (area && request.recipeId !== area.lastRecipe)
{
// 1 point per craft upon the end of production for alternating between 2 different crafting recipes in the same module
@ -1042,7 +1049,10 @@ export class HideoutController
* @param recipe Recipe being crafted
* @returns ITaskConditionCounter
*/
protected getHoursCraftingTaskConditionCounter(pmcData: IPmcData, recipe: IHideoutProduction): ITaskConditionCounter
protected getHoursCraftingTaskConditionCounter(
pmcData: IPmcData,
recipe: IHideoutProduction,
): ITaskConditionCounter
{
let counterHoursCrafting = pmcData.TaskConditionCounters[HideoutController.nameTaskConditionCountersCrafting];
if (!counterHoursCrafting)
@ -1078,7 +1088,8 @@ export class HideoutController
for (const production of ongoingProductions)
{
if (this.hideoutHelper.isProductionType(production[1]))
{ // Production or ScavCase
{
// Production or ScavCase
if ((production[1] as ScavCase).RecipeId === request.recipeId)
{
prodId = production[0]; // Set to objects key
@ -1187,13 +1198,13 @@ export class HideoutController
public recordShootingRangePoints(sessionId: string, pmcData: IPmcData, request: IRecordShootingRangePoints): void
{
// Check if counter exists, add placeholder if it doesnt
if (!pmcData.Stats.Eft.OverallCounters.Items.find(x => x.Key.includes("ShootingRangePoints")))
if (!pmcData.Stats.Eft.OverallCounters.Items.find((x) => x.Key.includes("ShootingRangePoints")))
{
pmcData.Stats.Eft.OverallCounters.Items.push({ Key: ["ShootingRangePoints"], Value: 0 });
}
// Find counter by key and update value
const shootingRangeHighScore = pmcData.Stats.Eft.OverallCounters.Items.find(x =>
const shootingRangeHighScore = pmcData.Stats.Eft.OverallCounters.Items.find((x) =>
x.Key.includes("ShootingRangePoints"),
);
shootingRangeHighScore.Value = request.points;
@ -1216,7 +1227,7 @@ export class HideoutController
// Create mapping of required item with corrisponding item from player inventory
const items = request.items.map((reqItem) =>
{
const item = pmcData.Inventory.items.find(invItem => invItem._id === reqItem.id);
const item = pmcData.Inventory.items.find((invItem) => invItem._id === reqItem.id);
return { inventoryItem: item, requestedItem: reqItem };
});
@ -1246,14 +1257,14 @@ export class HideoutController
}
}
const profileHideoutArea = pmcData.Hideout.Areas.find(x => x.type === request.areaType);
const profileHideoutArea = pmcData.Hideout.Areas.find((x) => x.type === request.areaType);
if (!profileHideoutArea)
{
this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType));
return this.httpResponse.appendErrorToOutput(output);
}
const hideoutDbData = this.databaseServer.getTables().hideout.areas.find(x => x.type === request.areaType);
const hideoutDbData = this.databaseServer.getTables().hideout.areas.find((x) => x.type === request.areaType);
if (!hideoutDbData)
{
this.logger.error(

View File

@ -201,7 +201,7 @@ export class InraidController
if (locationName === "lighthouse" && postRaidRequest.profile.Info.Side.toLowerCase() === "usec")
{
// Decrement counter if it exists, don't go below 0
const remainingCounter = serverPmcProfile?.Stats.Eft.OverallCounters.Items.find(x =>
const remainingCounter = serverPmcProfile?.Stats.Eft.OverallCounters.Items.find((x) =>
x.Key.includes("UsecRaidRemainKills"),
);
if (remainingCounter?.Value > 0)
@ -226,9 +226,9 @@ export class InraidController
// Not dead
// Check for cultist amulets in special slot (only slot it can fit)
const amuletOnPlayer = serverPmcProfile.Inventory.items.filter(item =>
item.slotId?.startsWith("SpecialSlot"),
).find(item => item._tpl === "64d0b40fbe2eed70e254e2d4");
const amuletOnPlayer = serverPmcProfile.Inventory.items
.filter((item) => item.slotId?.startsWith("SpecialSlot"))
.find((item) => item._tpl === "64d0b40fbe2eed70e254e2d4");
if (amuletOnPlayer)
{
// No charges left, delete it
@ -247,7 +247,7 @@ export class InraidController
}
}
const victims = postRaidRequest.profile.Stats.Eft.Victims.filter(x =>
const victims = postRaidRequest.profile.Stats.Eft.Victims.filter((x) =>
["sptbear", "sptusec"].includes(x.Role.toLowerCase()),
);
if (victims?.length > 0)
@ -281,12 +281,11 @@ export class InraidController
// and quest items cannot be picked up again
const allQuests = this.questHelper.getQuestsFromDb();
const activeQuestIdsInProfile = pmcData.Quests.filter(
profileQuest => ![
QuestStatus.AvailableForStart,
QuestStatus.Success,
QuestStatus.Expired,
].includes(profileQuest.status),
).map(x => x.qid);
(profileQuest) =>
![QuestStatus.AvailableForStart, QuestStatus.Success, QuestStatus.Expired].includes(
profileQuest.status,
),
).map((x) => x.qid);
for (const questItem of postRaidSaveRequest.profile.Stats.Eft.CarriedQuestItems)
{
// Get quest/find condition for carried quest item
@ -470,7 +469,7 @@ export class InraidController
for (const quest of scavProfile.Quests)
{
const pmcQuest = pmcProfile.Quests.find(x => x.qid === quest.qid);
const pmcQuest = pmcProfile.Quests.find((x) => x.qid === quest.qid);
if (!pmcQuest)
{
this.logger.warning(`No PMC quest found for ID: ${quest.qid}`);
@ -505,7 +504,7 @@ export class InraidController
for (const scavCounter of Object.values(scavProfile.TaskConditionCounters))
{
// If this is an achievement that isn't for the scav, don't process it
const achievement = achievements.find(achievement => achievement.id === scavCounter.sourceId);
const achievement = achievements.find((achievement) => achievement.id === scavCounter.sourceId);
if (achievement && achievement.side !== "Savage")
{
continue;
@ -687,8 +686,8 @@ export class InraidController
// Remove any items that were returned by the item delivery, but also insured, from the player's insurance list
// This is to stop items being duplicated by being returned from both the item delivery, and insurance
const deliveredItemIds = items.map(x => x._id);
pmcData.InsuredItems = pmcData.InsuredItems.filter(x => !deliveredItemIds.includes(x.itemId));
const deliveredItemIds = items.map((x) => x._id);
pmcData.InsuredItems = pmcData.InsuredItems.filter((x) => !deliveredItemIds.includes(x.itemId));
// Send the items to the player
this.mailSendService.sendLocalisedNpcMessageToPlayer(

View File

@ -112,7 +112,7 @@ export class InsuranceController
this.logger.debug(`Found ${profileInsuranceDetails.length} insurance packages in profile ${sessionID}`);
}
return profileInsuranceDetails.filter(insured => insuranceTime >= insured.scheduledTime);
return profileInsuranceDetails.filter((insured) => insuranceTime >= insured.scheduledTime);
}
/**
@ -125,9 +125,9 @@ export class InsuranceController
protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void
{
this.logger.debug(
`Processing ${insuranceDetails.length} insurance packages, which includes a total of ${
this.countAllInsuranceItems(insuranceDetails)
} items, in profile ${sessionID}`,
`Processing ${insuranceDetails.length} insurance packages, which includes a total of ${this.countAllInsuranceItems(
insuranceDetails,
)} items, in profile ${sessionID}`,
);
// Fetch the root Item parentId property value that should be used for insurance packages.
@ -160,7 +160,7 @@ export class InsuranceController
*/
protected countAllInsuranceItems(insurance: Insurance[]): number
{
return this.mathUtil.arraySum(insurance.map(ins => ins.items.length));
return this.mathUtil.arraySum(insurance.map((ins) => ins.items.length));
}
/**
@ -173,7 +173,8 @@ export class InsuranceController
protected removeInsurancePackageFromProfile(sessionID: string, insPackage: Insurance): void
{
const profile = this.saveServer.getProfile(sessionID);
profile.insurance = profile.insurance.filter(insurance =>
profile.insurance = profile.insurance.filter(
(insurance) =>
insurance.traderId !== insPackage.traderId
|| insurance.systemData.date !== insPackage.systemData.date
|| insurance.systemData.time !== insPackage.systemData.time
@ -200,8 +201,8 @@ export class InsuranceController
let parentAttachmentsMap = this.populateParentAttachmentsMap(rootItemParentID, insured, itemsMap);
// Check to see if any regular items are present.
const hasRegularItems = Array.from(itemsMap.values()).some(item =>
!this.itemHelper.isAttachmentAttached(item),
const hasRegularItems = Array.from(itemsMap.values()).some(
(item) => !this.itemHelper.isAttachmentAttached(item),
);
// Process all items that are not attached, attachments; those are handled separately, by value.
@ -249,7 +250,7 @@ export class InsuranceController
for (const insuredItem of insured.items)
{
// Use the parent ID from the item to get the parent item.
const parentItem = insured.items.find(item => item._id === insuredItem.parentId);
const parentItem = insured.items.find((item) => item._id === insuredItem.parentId);
// The parent (not the hideout) could not be found. Skip and warn.
if (!parentItem && insuredItem.parentId !== rootItemParentID)
@ -489,7 +490,7 @@ export class InsuranceController
{
this.logger.debug(
`Attachment ${index} Id: ${attachmentId} Tpl: ${
attachments.find(x => x._id === attachmentId)?._tpl
attachments.find((x) => x._id === attachmentId)?._tpl
} - Price: ${attachmentPrices[attachmentId]}`,
);
index++;
@ -556,7 +557,7 @@ export class InsuranceController
*/
protected removeItemsFromInsurance(insured: Insurance, toDelete: Set<string>): void
{
insured.items = insured.items.filter(item => !toDelete.has(item._id));
insured.items = insured.items.filter((item) => !toDelete.has(item._id));
}
/**

View File

@ -106,7 +106,7 @@ export class InventoryController
}
// Check for item in inventory before allowing internal transfer
const originalItemLocation = ownerInventoryItems.from.find(item => item._id === moveRequest.item);
const originalItemLocation = ownerInventoryItems.from.find((item) => item._id === moveRequest.item);
if (!originalItemLocation)
{
// Internal item move but item never existed, possible dupe glitch
@ -168,7 +168,8 @@ export class InventoryController
return;
}
const profileToRemoveItemFrom = (!request.fromOwner || request.fromOwner.id === pmcData._id)
const profileToRemoveItemFrom
= !request.fromOwner || request.fromOwner.id === pmcData._id
? pmcData
: this.profileHelper.getFullProfile(sessionID).characters.scav;
@ -197,12 +198,12 @@ export class InventoryController
// Handle cartridge edge-case
if (!request.container.location && request.container.container === "cartridges")
{
const matchingItems = inventoryItems.to.filter(x => x.parentId === request.container.id);
const matchingItems = inventoryItems.to.filter((x) => x.parentId === request.container.id);
request.container.location = matchingItems.length; // Wrong location for first cartridge
}
// The item being merged has three possible sources: pmc, scav or mail, getOwnerInventoryItems() handles getting correct one
const itemToSplit = inventoryItems.from.find(x => x._id === request.splitItem);
const itemToSplit = inventoryItems.from.find((x) => x._id === request.splitItem);
if (!itemToSplit)
{
const errorMessage = `Unable to split stack as source item: ${request.splitItem} cannot be found`;
@ -258,7 +259,7 @@ export class InventoryController
const inventoryItems = this.inventoryHelper.getOwnerInventoryItems(body, sessionID);
// Get source item (can be from player or trader or mail)
const sourceItem = inventoryItems.from.find(x => x._id === body.item);
const sourceItem = inventoryItems.from.find((x) => x._id === body.item);
if (!sourceItem)
{
const errorMessage = `Unable to merge stacks as source item: ${body.with} cannot be found`;
@ -270,7 +271,7 @@ export class InventoryController
}
// Get item being merged into
const destinationItem = inventoryItems.to.find(x => x._id === body.with);
const destinationItem = inventoryItems.to.find((x) => x._id === body.with);
if (!destinationItem)
{
const errorMessage = `Unable to merge stacks as destination item: ${body.with} cannot be found`;
@ -306,7 +307,7 @@ export class InventoryController
destinationItem.upd.StackObjectsCount += sourceItem.upd.StackObjectsCount; // Add source stackcount to destination
output.profileChanges[sessionID].items.del.push({ _id: sourceItem._id }); // Inform client source item being deleted
const indexOfItemToRemove = inventoryItems.from.findIndex(x => x._id === sourceItem._id);
const indexOfItemToRemove = inventoryItems.from.findIndex((x) => x._id === sourceItem._id);
if (indexOfItemToRemove === -1)
{
const errorMessage = `Unable to find item: ${sourceItem._id} to remove from sender inventory`;
@ -339,8 +340,8 @@ export class InventoryController
): IItemEventRouterResponse
{
const inventoryItems = this.inventoryHelper.getOwnerInventoryItems(body, sessionID);
const sourceItem = inventoryItems.from.find(item => item._id === body.item);
const destinationItem = inventoryItems.to.find(item => item._id === body.with);
const sourceItem = inventoryItems.from.find((item) => item._id === body.item);
const destinationItem = inventoryItems.to.find((item) => item._id === body.with);
if (sourceItem === null)
{
@ -394,15 +395,19 @@ export class InventoryController
* its used for "reload" if you have weapon in hands and magazine is somewhere else in rig or backpack in equipment
* Also used to swap items using quick selection on character screen
*/
public swapItem(pmcData: IPmcData, request: IInventorySwapRequestData, sessionID: string): IItemEventRouterResponse
public swapItem(
pmcData: IPmcData,
request: IInventorySwapRequestData,
sessionID: string,
): IItemEventRouterResponse
{
const itemOne = pmcData.Inventory.items.find(x => x._id === request.item);
const itemOne = pmcData.Inventory.items.find((x) => x._id === request.item);
if (!itemOne)
{
this.logger.error(`Unable to find item: ${request.item} to swap positions with: ${request.item2}`);
}
const itemTwo = pmcData.Inventory.items.find(x => x._id === request.item2);
const itemTwo = pmcData.Inventory.items.find((x) => x._id === request.item2);
if (!itemTwo)
{
this.logger.error(`Unable to find item: ${request.item2} to swap positions with: ${request.item}`);
@ -442,7 +447,11 @@ export class InventoryController
/**
* Handles folding of Weapons
*/
public foldItem(pmcData: IPmcData, request: IInventoryFoldRequestData, sessionID: string): IItemEventRouterResponse
public foldItem(
pmcData: IPmcData,
request: IInventoryFoldRequestData,
sessionID: string,
): IItemEventRouterResponse
{
// May need to reassign to scav profile
let playerData = pmcData;
@ -453,7 +462,7 @@ export class InventoryController
playerData = this.profileHelper.getScavProfile(sessionID);
}
const itemToFold = playerData.Inventory.items.find(item => item?._id === request.item);
const itemToFold = playerData.Inventory.items.find((item) => item?._id === request.item);
if (!itemToFold)
{
// Item not found
@ -476,7 +485,11 @@ export class InventoryController
* @param sessionID Session id
* @returns IItemEventRouterResponse
*/
public toggleItem(pmcData: IPmcData, body: IInventoryToggleRequestData, sessionID: string): IItemEventRouterResponse
public toggleItem(
pmcData: IPmcData,
body: IInventoryToggleRequestData,
sessionID: string,
): IItemEventRouterResponse
{
// May need to reassign to scav profile
let playerData = pmcData;
@ -487,7 +500,7 @@ export class InventoryController
playerData = this.profileHelper.getScavProfile(sessionID);
}
const itemToToggle = playerData.Inventory.items.find(x => x._id === body.item);
const itemToToggle = playerData.Inventory.items.find((x) => x._id === body.item);
if (itemToToggle)
{
this.itemHelper.addUpdObjectToItem(
@ -688,16 +701,16 @@ export class InventoryController
if (request.fromOwner.id === Traders.FENCE)
{
// Get tpl from fence assorts
return this.fenceService.getRawFenceAssorts().items.find(x => x._id === request.item)._tpl;
return this.fenceService.getRawFenceAssorts().items.find((x) => x._id === request.item)._tpl;
}
if (request.fromOwner.type === "Trader")
{
// Not fence
// get tpl from trader assort
return this.databaseServer.getTables().traders[request.fromOwner.id].assort.items.find(item =>
item._id === request.item,
)._tpl;
return this.databaseServer
.getTables()
.traders[request.fromOwner.id].assort.items.find((item) => item._id === request.item)._tpl;
}
if (request.fromOwner.type === "RagFair")
@ -717,7 +730,7 @@ export class InventoryController
}
// Try find examine item inside offer items array
const matchingItem = offer.items.find(offerItem => offerItem._id === request.item);
const matchingItem = offer.items.find((offerItem) => offerItem._id === request.item);
if (matchingItem)
{
return matchingItem._tpl;
@ -753,7 +766,7 @@ export class InventoryController
{
for (const change of request.changedItems)
{
const inventoryItem = pmcData.Inventory.items.find(x => x._id === change._id);
const inventoryItem = pmcData.Inventory.items.find((x) => x._id === change._id);
if (!inventoryItem)
{
this.logger.error(
@ -792,7 +805,7 @@ export class InventoryController
): void
{
// Get map from inventory
const mapItem = pmcData.Inventory.items.find(i => i._id === request.item);
const mapItem = pmcData.Inventory.items.find((i) => i._id === request.item);
// add marker
mapItem.upd.Map = mapItem.upd.Map || { Markers: [] };
@ -818,7 +831,7 @@ export class InventoryController
): void
{
// Get map from inventory
const mapItem = pmcData.Inventory.items.find(i => i._id === request.item);
const mapItem = pmcData.Inventory.items.find((i) => i._id === request.item);
// remove marker
const markers = mapItem.upd.Map.Markers.filter((marker) =>
@ -846,10 +859,10 @@ export class InventoryController
): void
{
// Get map from inventory
const mapItem = pmcData.Inventory.items.find(i => i._id === request.item);
const mapItem = pmcData.Inventory.items.find((i) => i._id === request.item);
// edit marker
const indexOfExistingNote = mapItem.upd.Map.Markers.findIndex(m => m.X === request.X && m.Y === request.Y);
const indexOfExistingNote = mapItem.upd.Map.Markers.findIndex((m) => m.X === request.X && m.Y === request.Y);
request.mapMarker.Note = this.sanitiseMapMarkerText(request.mapMarker.Note);
mapItem.upd.Map.Markers[indexOfExistingNote] = request.mapMarker;
@ -883,7 +896,7 @@ export class InventoryController
): void
{
/** Container player opened in their inventory */
const openedItem = pmcData.Inventory.items.find(item => item._id === body.item);
const openedItem = pmcData.Inventory.items.find((item) => item._id === body.item);
const containerDetailsDb = this.itemHelper.getItem(openedItem._tpl);
const isSealedWeaponBox = containerDetailsDb[1]._name.includes("event_container_airdrop");
@ -934,8 +947,8 @@ export class InventoryController
// Hard coded to `SYSTEM` for now
// TODO: make this dynamic
const dialog = fullProfile.dialogues["59e7125688a45068a6249071"];
const mail = dialog.messages.find(x => x._id === event.MessageId);
const mailEvent = mail.profileChangeEvents.find(x => x._id === event.EventId);
const mail = dialog.messages.find((x) => x._id === event.MessageId);
const mailEvent = mail.profileChangeEvents.find((x) => x._id === event.EventId);
switch (mailEvent.Type)
{
@ -954,15 +967,18 @@ export class InventoryController
break;
case "SkillPoints":
{
const profileSkill = pmcData.Skills.Common.find(x => x.Id === mailEvent.entity);
const profileSkill = pmcData.Skills.Common.find((x) => x.Id === mailEvent.entity);
profileSkill.Progress = mailEvent.value;
this.logger.success(`Set profile skill: ${mailEvent.entity} to: ${mailEvent.value}`);
break;
}
case "ExamineAllItems":
{
const itemsToInspect = this.itemHelper.getItems().filter(x => x._type !== "Node");
this.flagItemsAsInspectedAndRewardXp(itemsToInspect.map(x => x._id), fullProfile);
const itemsToInspect = this.itemHelper.getItems().filter((x) => x._type !== "Node");
this.flagItemsAsInspectedAndRewardXp(
itemsToInspect.map((x) => x._id),
fullProfile,
);
this.logger.success(`Flagged ${itemsToInspect.length} items as examined`);
break;
}
@ -987,7 +1003,7 @@ export class InventoryController
for (const itemId of request.items)
{
// If id already exists in array, we're removing it
const indexOfItemAlreadyFavorited = pmcData.Inventory.favoriteItems.findIndex(x => x === itemId);
const indexOfItemAlreadyFavorited = pmcData.Inventory.favoriteItems.findIndex((x) => x === itemId);
if (indexOfItemAlreadyFavorited > -1)
{
pmcData.Inventory.favoriteItems.splice(indexOfItemAlreadyFavorited, 1);

View File

@ -92,9 +92,9 @@ export class LocationController
// Check for a loot multipler adjustment in app context and apply if one is found
let locationConfigCopy: ILocationConfig;
const raidAdjustments = this.applicationContext.getLatestValue(ContextVariableType.RAID_ADJUSTMENTS)?.getValue<
IRaidChanges
>();
const raidAdjustments = this.applicationContext
.getLatestValue(ContextVariableType.RAID_ADJUSTMENTS)
?.getValue<IRaidChanges>();
if (raidAdjustments)
{
locationConfigCopy = this.cloner.clone(this.locationConfig); // Clone values so they can be used to reset originals later

View File

@ -24,9 +24,7 @@ export class PresetController
if (id !== preset._id)
{
this.logger.error(
`Preset for template tpl: '${
preset._items[0]._tpl
} ${preset._name}' has invalid key: (${id} != ${preset._id}). Skipping`,
`Preset for template tpl: '${preset._items[0]._tpl} ${preset._name}' has invalid key: (${id} != ${preset._id}). Skipping`,
);
continue;

View File

@ -129,10 +129,8 @@ export class ProfileController
public createProfile(info: IProfileCreateRequestData, sessionID: string): string
{
const account = this.saveServer.getProfile(sessionID).info;
const profile: ITemplateSide = this.databaseServer
.getTables()
.templates
.profiles[account.edition][info.side.toLowerCase()];
const profile: ITemplateSide
= this.databaseServer.getTables().templates.profiles[account.edition][info.side.toLowerCase()];
const pmcData = profile.character;
// Delete existing profile
@ -152,7 +150,7 @@ export class ProfileController
pmcData.Customization.Head = info.headId;
pmcData.Health.UpdateTime = this.timeUtil.getTimestamp();
pmcData.Quests = [];
pmcData.Hideout.Seed = this.timeUtil.getTimestamp() + (8 * 60 * 60 * 24 * 365); // 8 years in future why? who knows, we saw it in live
pmcData.Hideout.Seed = this.timeUtil.getTimestamp() + 8 * 60 * 60 * 24 * 365; // 8 years in future why? who knows, we saw it in live
pmcData.RepeatableQuests = [];
pmcData.CarExtractCounts = {};
pmcData.CoopExtractCounts = {};
@ -398,7 +396,8 @@ export class ProfileController
const profile = this.saveServer.getProfile(sessionID);
// return some of the current player info for now
return [{
return [
{
_id: profile.characters.pmc._id,
aid: profile.characters.pmc.aid,
Info: {
@ -407,7 +406,8 @@ export class ProfileController
Level: 1,
MemberCategory: profile.characters.pmc.Info.MemberCategory,
},
}];
},
];
}
/**
@ -418,14 +418,17 @@ export class ProfileController
const account = this.saveServer.getProfile(sessionId).info;
const response: GetProfileStatusResponseData = {
maxPveCountExceeded: false,
profiles: [{ profileid: account.scavId, profileToken: null, status: "Free", sid: "", ip: "", port: 0 }, {
profiles: [
{ profileid: account.scavId, profileToken: null, status: "Free", sid: "", ip: "", port: 0 },
{
profileid: account.id,
profileToken: null,
status: "Free",
sid: "",
ip: "",
port: 0,
}],
},
],
};
return response;
@ -459,7 +462,7 @@ export class ProfileController
skills: playerPmc.Skills,
equipment: {
// Default inventory tpl
Id: playerPmc.Inventory.items.find(x => x._tpl === "55d7217a4bdc2d86028b456d")._id,
Id: playerPmc.Inventory.items.find((x) => x._tpl === "55d7217a4bdc2d86028b456d")._id,
Items: playerPmc.Inventory.items,
},
achievements: playerPmc.Achievements,

View File

@ -78,7 +78,7 @@ export class QuestController
for (const quest of allQuests)
{
// Player already accepted the quest, show it regardless of status
const questInProfile = profile.Quests.find(x => x.qid === quest._id);
const questInProfile = profile.Quests.find((x) => x.qid === quest._id);
if (questInProfile)
{
quest.sptStatus = questInProfile.status;
@ -123,7 +123,11 @@ export class QuestController
);
// Quest has no conditions, standing or loyalty conditions, add to visible quest list
if (questRequirements.length === 0 && loyaltyRequirements.length === 0 && standingRequirements.length === 0)
if (
questRequirements.length === 0
&& loyaltyRequirements.length === 0
&& standingRequirements.length === 0
)
{
quest.sptStatus = QuestStatus.AvailableForStart;
questsToShowPlayer.push(quest);
@ -136,7 +140,7 @@ export class QuestController
for (const conditionToFulfil of questRequirements)
{
// If the previous quest isn't in the user profile, it hasn't been completed or started
const prerequisiteQuest = profile.Quests.find(profileQuest =>
const prerequisiteQuest = profile.Quests.find((profileQuest) =>
conditionToFulfil.target.includes(profileQuest.qid),
);
if (!prerequisiteQuest)
@ -147,7 +151,7 @@ export class QuestController
// Prereq does not have its status requirement fulfilled
// Some bsg status ids are strings, MUST convert to number before doing includes check
if (!conditionToFulfil.status.map(status => Number(status)).includes(prerequisiteQuest.status))
if (!conditionToFulfil.status.map((status) => Number(status)).includes(prerequisiteQuest.status))
{
haveCompletedPreviousQuest = false;
break;
@ -291,7 +295,7 @@ export class QuestController
// Does quest exist in profile
// Restarting a failed quest can mean quest exists in profile
const existingQuestStatus = pmcData.Quests.find(x => x.qid === acceptedQuest.qid);
const existingQuestStatus = pmcData.Quests.find((x) => x.qid === acceptedQuest.qid);
if (existingQuestStatus)
{
// Update existing
@ -398,16 +402,17 @@ export class QuestController
fullProfile.characters.scav.Quests.push(newRepeatableQuest);
}
const repeatableSettings = pmcData.RepeatableQuests.find(x =>
x.name === repeatableQuestProfile.sptRepatableGroupName,
const repeatableSettings = pmcData.RepeatableQuests.find(
(x) => x.name === repeatableQuestProfile.sptRepatableGroupName,
);
const change = {};
change[repeatableQuestProfile._id] = repeatableSettings.changeRequirement[repeatableQuestProfile._id];
const responseData: IPmcDataRepeatableQuest = {
id: repeatableSettings.id ?? this.questConfig.repeatableQuests.find(x =>
x.name === repeatableQuestProfile.sptRepatableGroupName,
).id,
id:
repeatableSettings.id
?? this.questConfig.repeatableQuests.find((x) => x.name === repeatableQuestProfile.sptRepatableGroupName)
.id,
name: repeatableSettings.name,
endTime: repeatableSettings.endTime,
changeRequirement: change,
@ -430,11 +435,14 @@ export class QuestController
* @param acceptedQuest Quest to search for
* @returns IRepeatableQuest
*/
protected getRepeatableQuestFromProfile(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData): IRepeatableQuest
protected getRepeatableQuestFromProfile(
pmcData: IPmcData,
acceptedQuest: IAcceptQuestRequestData,
): IRepeatableQuest
{
for (const repeatableQuest of pmcData.RepeatableQuests)
{
const matchingQuest = repeatableQuest.activeQuests.find(x => x._id === acceptedQuest.qid);
const matchingQuest = repeatableQuest.activeQuests.find((x) => x._id === acceptedQuest.qid);
if (matchingQuest)
{
this.logger.debug(`Accepted repeatable quest ${acceptedQuest.qid} from ${repeatableQuest.name}`);
@ -503,8 +511,8 @@ export class QuestController
// Check if it's a repeatable quest. If so, remove from Quests
for (const currentRepeatable of pmcData.RepeatableQuests)
{
const repeatableQuest = currentRepeatable.activeQuests.find(activeRepeatable =>
activeRepeatable._id === completedQuestId,
const repeatableQuest = currentRepeatable.activeQuests.find(
(activeRepeatable) => activeRepeatable._id === completedQuestId,
);
if (repeatableQuest)
{
@ -547,15 +555,15 @@ export class QuestController
// Quest already failed in profile, skip
if (
pmcProfile.Quests.some(profileQuest =>
profileQuest.qid === quest._id && profileQuest.status === QuestStatus.Fail,
pmcProfile.Quests.some(
(profileQuest) => profileQuest.qid === quest._id && profileQuest.status === QuestStatus.Fail,
)
)
{
return false;
}
return quest.conditions.Fail.some(condition => condition.target?.includes(completedQuestId));
return quest.conditions.Fail.some((condition) => condition.target?.includes(completedQuestId));
});
}
@ -567,7 +575,7 @@ export class QuestController
protected removeQuestFromScavProfile(sessionId: string, questIdToRemove: string): void
{
const fullProfile = this.profileHelper.getFullProfile(sessionId);
const repeatableInScavProfile = fullProfile.characters.scav.Quests?.find(x => x.qid === questIdToRemove);
const repeatableInScavProfile = fullProfile.characters.scav.Quests?.find((x) => x.qid === questIdToRemove);
if (!repeatableInScavProfile)
{
this.logger.warning(
@ -599,7 +607,7 @@ export class QuestController
for (const quest of postQuestStatuses)
{
// Add quest if status differs or quest not found
const preQuest = preQuestStatusus.find(x => x.qid === quest.qid);
const preQuest = preQuestStatusus.find((x) => x.qid === quest.qid);
if (!preQuest || preQuest.status !== quest.status)
{
result.push(quest);
@ -652,8 +660,8 @@ export class QuestController
for (const quest of quests)
{
// If quest has prereq of completed quest + availableAfter value > 0 (quest has wait time)
const nextQuestWaitCondition = quest.conditions.AvailableForStart.find(x =>
x.target?.includes(completedQuestId) && x.availableAfter > 0,
const nextQuestWaitCondition = quest.conditions.AvailableForStart.find(
(x) => x.target?.includes(completedQuestId) && x.availableAfter > 0,
);
if (nextQuestWaitCondition)
{
@ -661,7 +669,7 @@ export class QuestController
const availableAfterTimestamp = this.timeUtil.getTimestamp() + nextQuestWaitCondition.availableAfter;
// Update quest in profile with status of AvailableAfter
const existingQuestInProfile = pmcData.Quests.find(x => x.qid === quest._id);
const existingQuestInProfile = pmcData.Quests.find((x) => x.qid === quest._id);
if (existingQuestInProfile)
{
existingQuestInProfile.availableAfter = availableAfterTimestamp;
@ -704,12 +712,12 @@ export class QuestController
for (const questToFail of questsToFail)
{
// Skip failing a quest that has a fail status of something other than success
if (questToFail.conditions.Fail?.some(x => x.status?.some(status => status !== QuestStatus.Success)))
if (questToFail.conditions.Fail?.some((x) => x.status?.some((status) => status !== QuestStatus.Success)))
{
continue;
}
const isActiveQuestInPlayerProfile = pmcData.Quests.find(quest => quest.qid === questToFail._id);
const isActiveQuestInPlayerProfile = pmcData.Quests.find((quest) => quest.qid === questToFail._id);
if (isActiveQuestInPlayerProfile)
{
if (isActiveQuestInPlayerProfile.status !== QuestStatus.Fail)
@ -771,7 +779,8 @@ export class QuestController
isItemHandoverQuest = condition.conditionType === handoverQuestTypes[0];
handoverRequirements = condition;
const profileCounter = handoverQuestRequest.conditionId in pmcData.TaskConditionCounters
const profileCounter
= handoverQuestRequest.conditionId in pmcData.TaskConditionCounters
? pmcData.TaskConditionCounters[handoverQuestRequest.conditionId].value
: 0;
handedInCount -= profileCounter;
@ -805,7 +814,7 @@ export class QuestController
let totalItemCountToRemove = 0;
for (const itemHandover of handoverQuestRequest.items)
{
const matchingItemInProfile = pmcData.Inventory.items.find(item => item._id === itemHandover.id);
const matchingItemInProfile = pmcData.Inventory.items.find((item) => item._id === itemHandover.id);
if (!(matchingItemInProfile && handoverRequirements.target.includes(matchingItemInProfile._tpl)))
{
// Item handed in by player doesnt match what was requested

View File

@ -27,7 +27,6 @@ import { ISearchRequestData } from "@spt-aki/models/eft/ragfair/ISearchRequestDa
import { IProcessBuyTradeRequestData } from "@spt-aki/models/eft/trade/IProcessBuyTradeRequestData";
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
import { MemberCategory } from "@spt-aki/models/enums/MemberCategory";
import { RagfairSort } from "@spt-aki/models/enums/RagfairSort";
import { IRagfairConfig } from "@spt-aki/models/spt/config/IRagfairConfig";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { EventOutputHolder } from "@spt-aki/routers/EventOutputHolder";
@ -159,7 +158,7 @@ export class RagfairController
public getOfferById(sessionId: string, request: IGetRagfairOfferByIdRequest): IRagfairOffer
{
const offers = this.ragfairOfferService.getOffers();
const offerToReturn = offers.find(x => x.intId === request.id);
const offerToReturn = offers.find((x) => x.intId === request.id);
return offerToReturn;
}
@ -207,12 +206,8 @@ export class RagfairController
): Record<string, number>
{
// Linked/required search categories
const playerHasFleaUnlocked = pmcProfile.Info.Level >= this.databaseServer
.getTables()
.globals
.config
.RagFair
.minUserLevel;
const playerHasFleaUnlocked
= pmcProfile.Info.Level >= this.databaseServer.getTables().globals.config.RagFair.minUserLevel;
let offerPool = [];
if (this.isLinkedSearch(searchRequest) || this.isRequiredSearch(searchRequest))
{
@ -263,7 +258,7 @@ export class RagfairController
const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(offer.user.id).items;
const assortId = offer.items[0]._id;
const assortData = traderAssorts.find(x => x._id === assortId);
const assortData = traderAssorts.find((x) => x._id === assortId);
// Use value stored in profile, otherwise use value directly from in-memory trader assort data
offer.buyRestrictionCurrent = fullProfile.traderPurchases[offer.user.id][assortId]
@ -282,7 +277,7 @@ export class RagfairController
const firstItem = offer.items[0];
const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(offer.user.id).items;
const assortPurchased = traderAssorts.find(x => x._id === offer.items[0]._id);
const assortPurchased = traderAssorts.find((x) => x._id === offer.items[0]._id);
if (!assortPurchased)
{
this.logger.warning(
@ -357,16 +352,19 @@ export class RagfairController
// Get the average offer price, excluding barter offers
let avgOfferCount = 0;
const avg = offers.reduce((sum, offer) =>
const avg
= offers.reduce((sum, offer) =>
{
// Exclude barter items, they tend to have outrageous equivalent prices
if (offer.requirements.some(req => !this.paymentHelper.isMoneyTpl(req._tpl)))
if (offer.requirements.some((req) => !this.paymentHelper.isMoneyTpl(req._tpl)))
{
return sum;
}
// Figure out how many items the requirementsCost is applying to, and what the per-item price is
const offerItemCount = Math.max(offer.sellInOnePiece ? offer.items[0].upd?.StackObjectsCount ?? 1 : 1);
const offerItemCount = Math.max(
offer.sellInOnePiece ? offer.items[0].upd?.StackObjectsCount ?? 1 : 1,
);
const perItemPrice = offer.requirementsCost / offerItemCount;
// Handle min/max calculations based on the per-item price
@ -428,8 +426,8 @@ export class RagfairController
}
// Get an array of items from player inventory to list on flea
const { items: itemsInInventoryToList, errorMessage: itemsInInventoryError } = this
.getItemsToListOnFleaFromInventory(pmcData, offerRequest.items);
const { items: itemsInInventoryToList, errorMessage: itemsInInventoryError }
= this.getItemsToListOnFleaFromInventory(pmcData, offerRequest.items);
if (!itemsInInventoryToList || itemsInInventoryError)
{
this.httpResponse.appendErrorToOutput(output, itemsInInventoryError);
@ -605,8 +603,8 @@ export class RagfairController
}
else
{
requirementsPriceInRub += this.ragfairPriceService
.getDynamicPriceForItem(requestedItemTpl) * item.count;
requirementsPriceInRub
+= this.ragfairPriceService.getDynamicPriceForItem(requestedItemTpl) * item.count;
}
}
@ -630,7 +628,7 @@ export class RagfairController
// Count how many items are being sold and multiply the requested amount accordingly
for (const itemId of itemIdsFromFleaOfferRequest)
{
let item = pmcData.Inventory.items.find(i => i._id === itemId);
let item = pmcData.Inventory.items.find((i) => i._id === itemId);
if (!item)
{
errorMessage = this.localisationService.getText("ragfair-unable_to_find_item_in_inventory", {
@ -666,7 +664,7 @@ export class RagfairController
const loyalLevel = 1;
const formattedItems: Item[] = items.map((item) =>
{
const isChild = items.find(it => it._id === item.parentId);
const isChild = items.find((it) => it._id === item.parentId);
return {
_id: item._id,
@ -727,7 +725,7 @@ export class RagfairController
pmcData.RagfairInfo.offers = [];
}
const playerOfferIndex = playerProfileOffers.findIndex(offer => offer._id === removeRequest.offerId);
const playerOfferIndex = playerProfileOffers.findIndex((offer) => offer._id === removeRequest.offerId);
if (playerOfferIndex === -1)
{
this.logger.error(
@ -764,7 +762,7 @@ export class RagfairController
const pmcData = this.saveServer.getProfile(sessionId).characters.pmc;
const playerOffers = pmcData.RagfairInfo.offers;
const playerOfferIndex = playerOffers.findIndex(offer => offer._id === extendRequest.offerId);
const playerOfferIndex = playerOffers.findIndex((offer) => offer._id === extendRequest.offerId);
const secondsToAdd = extendRequest.renewalTime * TimeUtil.ONE_HOUR_AS_SECONDS;
if (playerOfferIndex === -1)

View File

@ -7,7 +7,6 @@ import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
import { IRepairActionDataRequest } from "@spt-aki/models/eft/repair/IRepairActionDataRequest";
import { ITraderRepairActionDataRequest } from "@spt-aki/models/eft/repair/ITraderRepairActionDataRequest";
import { SkillTypes } from "@spt-aki/models/enums/SkillTypes";
import { IRepairConfig } from "@spt-aki/models/spt/config/IRepairConfig";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { EventOutputHolder } from "@spt-aki/routers/EventOutputHolder";
@ -86,7 +85,11 @@ export class RepairController
* @param pmcData player profile
* @returns item event router action
*/
public repairWithKit(sessionID: string, body: IRepairActionDataRequest, pmcData: IPmcData): IItemEventRouterResponse
public repairWithKit(
sessionID: string,
body: IRepairActionDataRequest,
pmcData: IPmcData,
): IItemEventRouterResponse
{
const output = this.eventOutputHolder.getOutput(sessionID);

View File

@ -90,7 +90,7 @@ export class RepeatableQuestController
const pmcData = this.profileHelper.getPmcProfile(sessionID);
const time = this.timeUtil.getTimestamp();
const scavQuestUnlocked
= pmcData?.Hideout?.Areas?.find(hideoutArea => hideoutArea.type === HideoutAreas.INTEL_CENTER)?.level >= 1;
= pmcData?.Hideout?.Areas?.find((hideoutArea) => hideoutArea.type === HideoutAreas.INTEL_CENTER)?.level >= 1;
// Daily / weekly / Daily_Savage
for (const repeatableConfig of this.questConfig.repeatableQuests)
@ -118,7 +118,7 @@ export class RepeatableQuestController
for (const activeQuest of currentRepeatableQuestType.activeQuests)
{
// Keep finished quests in list so player can hand in
const quest = pmcData.Quests.find(quest => quest.qid === activeQuest._id);
const quest = pmcData.Quests.find((quest) => quest.qid === activeQuest._id);
if (quest)
{
if (quest.status === QuestStatus.AvailableForFinish)
@ -134,7 +134,7 @@ export class RepeatableQuestController
this.profileFixerService.removeDanglingConditionCounters(pmcData);
// Remove expired quest from pmc.quest array
pmcData.Quests = pmcData.Quests.filter(quest => quest.qid !== activeQuest._id);
pmcData.Quests = pmcData.Quests.filter((quest) => quest.qid !== activeQuest._id);
currentRepeatableQuestType.inactiveQuests.push(activeQuest);
}
currentRepeatableQuestType.activeQuests = questsToKeep;
@ -216,14 +216,11 @@ export class RepeatableQuestController
)
{
// Elite charisma skill gives extra daily quest(s)
return repeatableConfig.numQuests + this.databaseServer.getTables()
.globals
.config
.SkillsSettings
.Charisma
.BonusSettings
.EliteBonusSettings
.RepeatableQuestExtraCount;
return (
repeatableConfig.numQuests
+ this.databaseServer.getTables().globals.config.SkillsSettings.Charisma.BonusSettings.EliteBonusSettings
.RepeatableQuestExtraCount
);
}
return repeatableConfig.numQuests;
@ -241,7 +238,7 @@ export class RepeatableQuestController
): IPmcDataRepeatableQuest
{
// Get from profile, add if missing
let repeatableQuestDetails = pmcData.RepeatableQuests.find(x => x.name === repeatableConfig.name);
let repeatableQuestDetails = pmcData.RepeatableQuests.find((x) => x.name === repeatableConfig.name);
if (!repeatableQuestDetails)
{
repeatableQuestDetails = {
@ -331,8 +328,9 @@ export class RepeatableQuestController
const possibleLocations = Object.keys(locations);
// Set possible locations for elimination task, if target is savage, exclude labs from locations
questPool.pool.Elimination.targets[probabilityObject.key] = probabilityObject.key === "Savage"
? { locations: possibleLocations.filter(x => x !== "laboratory") }
questPool.pool.Elimination.targets[probabilityObject.key]
= probabilityObject.key === "Savage"
? { locations: possibleLocations.filter((x) => x !== "laboratory") }
: { locations: possibleLocations };
}
}
@ -443,7 +441,7 @@ export class RepeatableQuestController
for (const currentRepeatablePool of pmcData.RepeatableQuests)
{
// Check for existing quest in (daily/weekly/scav arrays)
const questToReplace = currentRepeatablePool.activeQuests.find(x => x._id === changeRequest.qid);
const questToReplace = currentRepeatablePool.activeQuests.find((x) => x._id === changeRequest.qid);
if (!questToReplace)
{
continue;
@ -453,8 +451,8 @@ export class RepeatableQuestController
replacedQuestTraderId = questToReplace.traderId;
// Update active quests to exclude the quest we're replacing
currentRepeatablePool.activeQuests = currentRepeatablePool.activeQuests.filter(x =>
x._id !== changeRequest.qid,
currentRepeatablePool.activeQuests = currentRepeatablePool.activeQuests.filter(
(x) => x._id !== changeRequest.qid,
);
// Get cost to replace existing quest
@ -462,8 +460,8 @@ export class RepeatableQuestController
delete currentRepeatablePool.changeRequirement[changeRequest.qid];
// TODO: somehow we need to reduce the questPool by the currently active quests (for all repeatables)
const repeatableConfig = this.questConfig.repeatableQuests.find(x =>
x.name === currentRepeatablePool.name,
const repeatableConfig = this.questConfig.repeatableQuests.find(
(x) => x.name === currentRepeatablePool.name,
);
const questTypePool = this.generateQuestPool(repeatableConfig, pmcData.Info.Level);
const newRepeatableQuest = this.attemptToGenerateRepeatableQuest(pmcData, questTypePool, repeatableConfig);

View File

@ -4,7 +4,7 @@ import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
import { TradeHelper } from "@spt-aki/helpers/TradeHelper";
import { TraderHelper } from "@spt-aki/helpers/TraderHelper";
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
import { Item, Upd } from "@spt-aki/models/eft/common/tables/IItem";
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
import { ITraderBase } from "@spt-aki/models/eft/common/tables/ITrader";
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
import { IRagfairOffer } from "@spt-aki/models/eft/ragfair/IRagfairOffer";
@ -170,9 +170,7 @@ export class TradeController
// Skip buying items when player doesn't have needed loyalty
if (this.playerLacksTraderLoyaltyLevelToBuyOffer(fleaOffer, pmcData))
{
const errorMessage = `Unable to buy item: ${
fleaOffer.items[0]._tpl
} from trader: ${fleaOffer.user.id} as loyalty level too low, skipping`;
const errorMessage = `Unable to buy item: ${fleaOffer.items[0]._tpl} from trader: ${fleaOffer.user.id} as loyalty level too low, skipping`;
this.logger.debug(errorMessage);
this.httpResponse.appendErrorToOutput(output, errorMessage, BackendErrorCodes.RAGFAIRUNAVAILABLE);
@ -291,7 +289,7 @@ export class TradeController
this.traderHelper.getTraderById(trader),
MessageType.MESSAGE_WITH_ITEMS,
this.randomUtil.getArrayValue(this.databaseServer.getTables().traders[trader].dialogue.soldItems),
curencyReward.flatMap(x => x),
curencyReward.flatMap((x) => x),
this.timeUtil.getHoursAsSeconds(72),
);
}
@ -317,10 +315,12 @@ export class TradeController
for (const itemToSell of itemWithChildren)
{
const itemDetails = this.itemHelper.getItem(itemToSell._tpl);
if (!(itemDetails[0] && this.itemHelper.isOfBaseclasses(
itemDetails[1]._id,
traderDetails.items_buy.category,
)))
if (
!(
itemDetails[0]
&& this.itemHelper.isOfBaseclasses(itemDetails[1]._id, traderDetails.items_buy.category)
)
)
{
// Skip if tpl isn't item OR item doesn't fulfil match traders buy categories
continue;

View File

@ -29,7 +29,8 @@ export class TraderController
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
@inject("TraderHelper") protected traderHelper: TraderHelper,
@inject("TraderAssortService") protected traderAssortService: TraderAssortService,
@inject("TraderPurchasePersisterService") protected traderPurchasePersisterService: TraderPurchasePersisterService,
@inject("TraderPurchasePersisterService")
protected traderPurchasePersisterService: TraderPurchasePersisterService,
@inject("FenceService") protected fenceService: FenceService,
@inject("FenceBaseAssortGenerator") protected fenceBaseAssortGenerator: FenceBaseAssortGenerator,
@inject("ConfigServer") protected configServer: ConfigServer,

View File

@ -28,7 +28,11 @@ export class WishlistController
}
/** Handle RemoveFromWishList event */
public removeFromWishList(pmcData: IPmcData, body: IWishlistActionData, sessionID: string): IItemEventRouterResponse
public removeFromWishList(
pmcData: IPmcData,
body: IWishlistActionData,
sessionID: string,
): IItemEventRouterResponse
{
for (let i = 0; i < pmcData.WishList.length; i++)
{

View File

@ -791,9 +791,13 @@ export class Container
depContainer.register<CustomizationController>("CustomizationController", {
useClass: CustomizationController,
});
depContainer.register<DialogueController>("DialogueController", { useClass: DialogueController }, {
depContainer.register<DialogueController>(
"DialogueController",
{ useClass: DialogueController },
{
lifecycle: Lifecycle.Singleton,
});
},
);
depContainer.register<GameController>("GameController", { useClass: GameController });
depContainer.register<HandbookController>("HandbookController", { useClass: HandbookController });
depContainer.register<HealthController>("HealthController", { useClass: HealthController });

View File

@ -29,9 +29,13 @@ export class Router
{
if (partialMatch)
{
return this.getInternalHandledRoutes().filter(r => r.dynamic).some(r => url.includes(r.route));
return this.getInternalHandledRoutes()
.filter((r) => r.dynamic)
.some((r) => url.includes(r.route));
}
return this.getInternalHandledRoutes().filter(r => !r.dynamic).some(r => r.route === url);
return this.getInternalHandledRoutes()
.filter((r) => !r.dynamic)
.some((r) => r.route === url);
}
}
@ -44,12 +48,12 @@ export class StaticRouter extends Router
public async handleStatic(url: string, info: any, sessionID: string, output: string): Promise<any>
{
return this.routes.find(route => route.url === url).action(url, info, sessionID, output);
return this.routes.find((route) => route.url === url).action(url, info, sessionID, output);
}
public override getHandledRoutes(): HandledRoute[]
{
return this.routes.map(route => new HandledRoute(route.url, false));
return this.routes.map((route) => new HandledRoute(route.url, false));
}
}
@ -62,12 +66,12 @@ export class DynamicRouter extends Router
public async handleDynamic(url: string, info: any, sessionID: string, output: string): Promise<any>
{
return this.routes.find(r => url.includes(r.url)).action(url, info, sessionID, output);
return this.routes.find((r) => url.includes(r.url)).action(url, info, sessionID, output);
}
public override getHandledRoutes(): HandledRoute[]
{
return this.routes.map(route => new HandledRoute(route.url, true));
return this.routes.map((route) => new HandledRoute(route.url, true));
}
}
@ -97,7 +101,10 @@ export class SaveLoadRouter extends Router
export class HandledRoute
{
constructor(public route: string, public dynamic: boolean)
constructor(
public route: string,
public dynamic: boolean,
)
{}
}

View File

@ -233,7 +233,8 @@ export class BotEquipmentModGenerator
}
// Get the front/back/side weights based on bots level
const plateSlotWeights = settings.botEquipmentConfig?.armorPlateWeighting?.find(armorWeight =>
const plateSlotWeights = settings.botEquipmentConfig?.armorPlateWeighting?.find(
(armorWeight) =>
settings.botLevel >= armorWeight.levelRange.min && settings.botLevel <= armorWeight.levelRange.max,
);
if (!plateSlotWeights)
@ -260,17 +261,17 @@ export class BotEquipmentModGenerator
const chosenArmorPlateLevel = this.weightedRandomHelper.getWeightedValue<string>(plateWeights);
// Convert the array of ids into database items
const platesFromDb = existingPlateTplPool.map(plateTpl => this.itemHelper.getItem(plateTpl)[1]);
const platesFromDb = existingPlateTplPool.map((plateTpl) => this.itemHelper.getItem(plateTpl)[1]);
// Filter plates to the chosen level based on its armorClass property
const platesOfDesiredLevel = platesFromDb.filter(item => item._props.armorClass === chosenArmorPlateLevel);
const platesOfDesiredLevel = platesFromDb.filter((item) => item._props.armorClass === chosenArmorPlateLevel);
if (platesOfDesiredLevel.length === 0)
{
this.logger.debug(
`Plate filter was too restrictive for armor: ${armorItem._name} ${armorItem._id}, unable to find plates of level: ${chosenArmorPlateLevel}. Using mod items default plate`,
);
const relatedItemDbModSlot = armorItem._props.Slots.find(slot => slot._name.toLowerCase() === modSlot);
const relatedItemDbModSlot = armorItem._props.Slots.find((slot) => slot._name.toLowerCase() === modSlot);
const defaultPlate = relatedItemDbModSlot._props.filters[0].Plate;
if (!defaultPlate)
{
@ -280,8 +281,8 @@ export class BotEquipmentModGenerator
const defaultPreset = this.presetHelper.getDefaultPreset(armorItem._id);
if (defaultPreset)
{
const relatedPresetSlot = defaultPreset._items.find(item =>
item.slotId?.toLowerCase() === modSlot,
const relatedPresetSlot = defaultPreset._items.find(
(item) => item.slotId?.toLowerCase() === modSlot,
);
if (relatedPresetSlot)
{
@ -305,7 +306,7 @@ export class BotEquipmentModGenerator
// Only return the items ids
result.result = Result.SUCCESS;
result.plateModTpls = platesOfDesiredLevel.map(item => item._id);
result.plateModTpls = platesOfDesiredLevel.map((item) => item._id);
return result;
}
@ -345,8 +346,11 @@ export class BotEquipmentModGenerator
const compatibleModsPool = modPool[parentTemplate._id];
if (
!(parentTemplate._props.Slots.length || parentTemplate._props.Cartridges?.length
|| parentTemplate._props.Chambers?.length)
!(
parentTemplate._props.Slots.length
|| parentTemplate._props.Cartridges?.length
|| parentTemplate._props.Chambers?.length
)
)
{
this.logger.error(
@ -467,10 +471,9 @@ export class BotEquipmentModGenerator
// Handguard mod can take a sub handguard mod + weapon has no UBGL (takes same slot)
// Force spawn chance to be 100% to ensure it gets added
if (
modSlot === "mod_handguard" && modToAddTemplate._props.Slots.find(slot =>
slot._name === "mod_handguard",
)
&& !weapon.find(item => item.slotId === "mod_launcher")
modSlot === "mod_handguard"
&& modToAddTemplate._props.Slots.find((slot) => slot._name === "mod_handguard")
&& !weapon.find((item) => item.slotId === "mod_launcher")
)
{
// Needed for handguards with lower
@ -480,8 +483,9 @@ export class BotEquipmentModGenerator
// If stock mod can take a sub stock mod, force spawn chance to be 100% to ensure sub-stock gets added
// Or if mod_stock is configured to be forced on
if (
modSlot === "mod_stock" && modToAddTemplate._props.Slots.find(slot =>
slot._name.includes("mod_stock") || botEquipConfig.forceStock,
modSlot === "mod_stock"
&& modToAddTemplate._props.Slots.find(
(slot) => slot._name.includes("mod_stock") || botEquipConfig.forceStock,
)
)
{
@ -549,8 +553,9 @@ export class BotEquipmentModGenerator
protected modIsFrontOrRearSight(modSlot: string, tpl: string): boolean
{
// Gas block /w front sight is special case, deem it a 'front sight' too
if (modSlot === "mod_gas_block" && tpl === "5ae30e795acfc408fb139a0b") // M4A1 front sight with gas block
if (modSlot === "mod_gas_block" && tpl === "5ae30e795acfc408fb139a0b")
{
// M4A1 front sight with gas block
return true;
}
@ -565,7 +570,8 @@ export class BotEquipmentModGenerator
*/
protected modSlotCanHoldScope(modSlot: string, modsParentId: string): boolean
{
return [
return (
[
"mod_scope",
"mod_mount",
"mod_mount_000",
@ -573,7 +579,8 @@ export class BotEquipmentModGenerator
"mod_scope_001",
"mod_scope_002",
"mod_scope_003",
].includes(modSlot.toLowerCase()) && modsParentId === BaseClasses.MOUNT;
].includes(modSlot.toLowerCase()) && modsParentId === BaseClasses.MOUNT
);
}
/**
@ -700,11 +707,11 @@ export class BotEquipmentModGenerator
case "patron_in_weapon":
case "patron_in_weapon_000":
case "patron_in_weapon_001":
return parentTemplate._props.Chambers.find(chamber => chamber._name.includes(modSlotLower));
return parentTemplate._props.Chambers.find((chamber) => chamber._name.includes(modSlotLower));
case "cartridges":
return parentTemplate._props.Cartridges.find(c => c._name.toLowerCase() === modSlotLower);
return parentTemplate._props.Cartridges.find((c) => c._name.toLowerCase() === modSlotLower);
default:
return parentTemplate._props.Slots.find(s => s._name.toLowerCase() === modSlotLower);
return parentTemplate._props.Slots.find((s) => s._name.toLowerCase() === modSlotLower);
}
}
@ -762,7 +769,7 @@ export class BotEquipmentModGenerator
): [boolean, ITemplateItem]
{
/** Slot mod will fill */
const parentSlot = parentTemplate._props.Slots.find(i => i._name === modSlot);
const parentSlot = parentTemplate._props.Slots.find((i) => i._name === modSlot);
const weaponTemplate = this.itemHelper.getItem(weapon[0]._tpl)[1];
// It's ammo, use predefined ammo parameter
@ -837,9 +844,7 @@ export class BotEquipmentModGenerator
if (parentSlot._required)
{
this.logger.warning(
`Required slot unable to be filled, ${modSlot} on ${parentTemplate._name} ${parentTemplate._id} for weapon: ${
weapon[0]._tpl
}`,
`Required slot unable to be filled, ${modSlot} on ${parentTemplate._name} ${parentTemplate._id} for weapon: ${weapon[0]._tpl}`,
);
}
@ -950,8 +955,8 @@ export class BotEquipmentModGenerator
if (modSpawnResult === ModSpawn.DEFAULT_MOD)
{
const matchingPreset = this.getMatchingPreset(weaponTemplate, parentTemplate._id);
const matchingModFromPreset = matchingPreset?._items.find(item =>
item?.slotId?.toLowerCase() === modSlot.toLowerCase(),
const matchingModFromPreset = matchingPreset?._items.find(
(item) => item?.slotId?.toLowerCase() === modSlot.toLowerCase(),
);
// Only filter mods down to single default item if it already exists in existing itemModPool, OR the default item has no children
@ -968,8 +973,8 @@ export class BotEquipmentModGenerator
// Get an array of items that are allowed in slot from parent item
// Check the filter of the slot to ensure a chosen mod fits
const parentSlotCompatibleItems = parentTemplate._props.Slots?.find(slot =>
slot._name.toLowerCase() === modSlot.toLowerCase(),
const parentSlotCompatibleItems = parentTemplate._props.Slots?.find(
(slot) => slot._name.toLowerCase() === modSlot.toLowerCase(),
)._props.filters[0].Filter;
// Mod isnt in existing pool, only add if it has no children and matches parent filter
@ -985,7 +990,9 @@ export class BotEquipmentModGenerator
if (itemModPool[modSlot]?.length > 1)
{
this.logger.debug(`No default: ${modSlot} mod found on template: ${weaponTemplate._name} and multiple items found in existing pool`);
this.logger.debug(
`No default: ${modSlot} mod found on template: ${weaponTemplate._name} and multiple items found in existing pool`,
);
}
// Couldnt find default in globals, use existing mod pool data
@ -1178,7 +1185,7 @@ export class BotEquipmentModGenerator
botEquipBlacklist: EquipmentFilterDetails,
): void
{
const desiredSlotObject = modTemplate._props.Slots.find(slot => slot._name.includes(desiredSlotName));
const desiredSlotObject = modTemplate._props.Slots.find((slot) => slot._name.includes(desiredSlotName));
if (desiredSlotObject)
{
const supportedSubMods = desiredSlotObject._props.filters[0].Filter;
@ -1261,10 +1268,10 @@ export class BotEquipmentModGenerator
let result: string[] = [];
// Get item blacklist and mod equipment blacklist as one array
const blacklist = this.itemFilterService.getBlacklistedItems().concat(
botEquipBlacklist.equipment[modSlot] || [],
);
result = allowedMods.filter(tpl => !blacklist.includes(tpl));
const blacklist = this.itemFilterService
.getBlacklistedItems()
.concat(botEquipBlacklist.equipment[modSlot] || []);
result = allowedMods.filter((tpl) => !blacklist.includes(tpl));
return result;
}
@ -1290,7 +1297,7 @@ export class BotEquipmentModGenerator
weaponName: parentTemplate._name,
}),
);
const camoraSlots = parentTemplate._props.Slots.filter(slot => slot._name.startsWith("camora"));
const camoraSlots = parentTemplate._props.Slots.filter((slot) => slot._name.startsWith("camora"));
// Attempt to generate camora slots for item
modPool[parentTemplate._id] = {};
@ -1397,9 +1404,7 @@ export class BotEquipmentModGenerator
if (!whitelistedSightTypes)
{
this.logger.debug(
`Unable to find whitelist for weapon type: ${weaponDetails[1]._parent} ${
weaponDetails[1]._name
}, skipping sight filtering`,
`Unable to find whitelist for weapon type: ${weaponDetails[1]._parent} ${weaponDetails[1]._name}, skipping sight filtering`,
);
return scopes;
@ -1424,14 +1429,15 @@ export class BotEquipmentModGenerator
{
// Check to see if mount has a scope slot (only include primary slot, ignore the rest like the backup sight slots)
// Should only find 1 as there's currently no items with a mod_scope AND a mod_scope_000
const scopeSlot = itemDetails._props.Slots.filter(slot =>
const scopeSlot = itemDetails._props.Slots.filter((slot) =>
["mod_scope", "mod_scope_000"].includes(slot._name),
);
// Mods scope slot found must allow ALL whitelisted scope types OR be a mount
if (
scopeSlot?.every(slot =>
slot._props.filters[0].Filter.every(tpl =>
scopeSlot?.every((slot) =>
slot._props.filters[0].Filter.every(
(tpl) =>
this.itemHelper.isOfBaseclasses(tpl, whitelistedSightTypes)
|| this.itemHelper.isOfBaseclass(tpl, BaseClasses.MOUNT),
),

View File

@ -232,7 +232,11 @@ export class BotGenerator
* @param appearance Appearance settings to choose from
* @param botGenerationDetails Generation details
*/
protected setBotAppearance(bot: IBotBase, appearance: Appearance, botGenerationDetails: BotGenerationDetails): void
protected setBotAppearance(
bot: IBotBase,
appearance: Appearance,
botGenerationDetails: BotGenerationDetails,
): void
{
bot.Customization.Head = this.weightedRandomHelper.getWeightedValue<string>(appearance.head);
bot.Customization.Body = this.weightedRandomHelper.getWeightedValue<string>(appearance.body);
@ -425,7 +429,8 @@ export class BotGenerator
return [];
}
return Object.keys(skills).map((skillKey): IBaseSkill =>
return Object.keys(skills)
.map((skillKey): IBaseSkill =>
{
// Get skill from dict, skip if not found
const skill = skills[skillKey];
@ -445,7 +450,8 @@ export class BotGenerator
}
return skillToAdd;
}).filter(x => x !== null);
})
.filter((x) => x !== null);
}
/**

View File

@ -307,8 +307,9 @@ export class BotInventoryGenerator
*/
protected generateEquipment(settings: IGenerateEquipmentProperties): boolean
{
const spawnChance = ([EquipmentSlots.POCKETS, EquipmentSlots.SECURED_CONTAINER] as string[])
.includes(settings.rootEquipmentSlot)
const spawnChance = ([EquipmentSlots.POCKETS, EquipmentSlots.SECURED_CONTAINER] as string[]).includes(
settings.rootEquipmentSlot,
)
? 100
: settings.spawnChances.equipment[settings.rootEquipmentSlot];
@ -442,7 +443,7 @@ export class BotInventoryGenerator
for (const modSlot of Object.keys(modPool ?? []))
{
const blacklistedMods = equipmentBlacklist[0]?.equipment[modSlot] || [];
const filteredMods = modPool[modSlot].filter(x => !blacklistedMods.includes(x));
const filteredMods = modPool[modSlot].filter((x) => !blacklistedMods.includes(x));
if (filteredMods.length > 0)
{
@ -504,17 +505,21 @@ export class BotInventoryGenerator
protected getDesiredWeaponsForBot(equipmentChances: Chances): { slot: EquipmentSlots, shouldSpawn: boolean }[]
{
const shouldSpawnPrimary = this.randomUtil.getChance100(equipmentChances.equipment.FirstPrimaryWeapon);
return [{ slot: EquipmentSlots.FIRST_PRIMARY_WEAPON, shouldSpawn: shouldSpawnPrimary }, {
return [
{ slot: EquipmentSlots.FIRST_PRIMARY_WEAPON, shouldSpawn: shouldSpawnPrimary },
{
slot: EquipmentSlots.SECOND_PRIMARY_WEAPON,
shouldSpawn: shouldSpawnPrimary
? this.randomUtil.getChance100(equipmentChances.equipment.SecondPrimaryWeapon)
: false,
}, {
},
{
slot: EquipmentSlots.HOLSTER,
shouldSpawn: shouldSpawnPrimary
? this.randomUtil.getChance100(equipmentChances.equipment.Holster) // Primary weapon = roll for chance at pistol
: true, // No primary = force pistol
}];
},
];
}
/**

View File

@ -65,7 +65,8 @@ export class BotLevelGenerator
maxLevel: number,
): number
{
const maxPossibleLevel = botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride
const maxPossibleLevel
= botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride
? Math.min(botGenerationDetails.locationSpecificPmcLevelOverride.max, maxLevel) // Was a PMC and they have a level override
: Math.min(levelDetails.max, maxLevel); // Not pmc with override or non-pmc
@ -91,7 +92,8 @@ export class BotLevelGenerator
maxlevel: number,
): number
{
const minPossibleLevel = botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride
const minPossibleLevel
= botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride
? Math.min(
Math.max(levelDetails.min, botGenerationDetails.locationSpecificPmcLevelOverride.min), // Biggest between json min and the botgen min
maxlevel, // Fallback if value above is crazy (default is 79)

View File

@ -85,7 +85,8 @@ export class BotLootGenerator
// Limits on item types to be added as loot
const itemCounts = botJsonTemplate.generation.items;
if(!itemCounts.backpackLoot.weights
if (
!itemCounts.backpackLoot.weights
|| !itemCounts.pocketLoot.weights
|| !itemCounts.vestLoot.weights
|| !itemCounts.specialItems.weights
@ -98,7 +99,9 @@ export class BotLootGenerator
|| !itemCounts.grenades.weights
)
{
this.logger.warning(`Unable to generate bot loot for ${botRole} as bot.generation.items lacks data, skipping`);
this.logger.warning(
`Unable to generate bot loot for ${botRole} as bot.generation.items lacks data, skipping`,
);
return;
}
@ -334,12 +337,12 @@ export class BotLootGenerator
{
const result = [EquipmentSlots.POCKETS];
if (botInventory.items.find(item => item.slotId === EquipmentSlots.TACTICAL_VEST))
if (botInventory.items.find((item) => item.slotId === EquipmentSlots.TACTICAL_VEST))
{
result.push(EquipmentSlots.TACTICAL_VEST);
}
if (botInventory.items.find(item => item.slotId === EquipmentSlots.BACKPACK))
if (botInventory.items.find((item) => item.slotId === EquipmentSlots.BACKPACK))
{
result.push(EquipmentSlots.BACKPACK);
}
@ -457,11 +460,13 @@ export class BotLootGenerator
}
const newRootItemId = this.hashUtil.generate();
const itemWithChildrenToAdd: Item[] = [{
const itemWithChildrenToAdd: Item[] = [
{
_id: newRootItemId,
_tpl: itemToAddTemplate._id,
...this.botGeneratorHelper.generateExtraPropertiesForItem(itemToAddTemplate, botRole),
}];
},
];
// Is Simple-Wallet / WZ wallet
if (this.botConfig.walletLoot.walletTplPool.includes(weightedItemTpl))
@ -493,7 +498,7 @@ export class BotLootGenerator
);
}
itemWithChildrenToAdd.push(...itemsToAdd.flatMap(moneyStack => moneyStack));
itemWithChildrenToAdd.push(...itemsToAdd.flatMap((moneyStack) => moneyStack));
}
}
}
@ -526,9 +531,9 @@ export class BotLootGenerator
if (fitItemIntoContainerAttempts >= 4)
{
this.logger.debug(
`Failed to place item ${i} of ${totalItemCount} items into ${botRole} containers: ${
equipmentSlots.join(",")
}. Tried ${fitItemIntoContainerAttempts} times, reason: ${
`Failed to place item ${i} of ${totalItemCount} items into ${botRole} containers: ${equipmentSlots.join(
",",
)}. Tried ${fitItemIntoContainerAttempts} times, reason: ${
ItemAddedResult[itemAddedResult]
}, skipping`,
);
@ -571,12 +576,14 @@ export class BotLootGenerator
const chosenStackCount = Number(
this.weightedRandomHelper.getWeightedValue<string>(this.botConfig.walletLoot.stackSizeWeight),
);
result.push([{
result.push([
{
_id: this.hashUtil.generate(),
_tpl: this.weightedRandomHelper.getWeightedValue<string>(this.botConfig.walletLoot.currencyWeight),
parentId: walletId,
upd: { StackObjectsCount: chosenStackCount },
}]);
},
]);
}
return result;
@ -675,9 +682,7 @@ export class BotLootGenerator
if (result !== ItemAddedResult.SUCCESS)
{
this.logger.debug(
`Failed to add additional weapon ${generatedWeapon.weapon[0]._id} to bot backpack, reason: ${
ItemAddedResult[result]
}`,
`Failed to add additional weapon ${generatedWeapon.weapon[0]._id} to bot backpack, reason: ${ItemAddedResult[result]}`,
);
}
}
@ -789,7 +794,8 @@ export class BotLootGenerator
*/
protected randomiseAmmoStackSize(isPmc: boolean, itemTemplate: ITemplateItem, ammoItem: Item): void
{
const randomSize = itemTemplate._props.StackMaxSize === 1
const randomSize
= itemTemplate._props.StackMaxSize === 1
? 1
: this.randomUtil.getInt(
itemTemplate._props.StackMinRandom,

View File

@ -199,7 +199,7 @@ export class BotWeaponGenerator
}
// Fill existing magazines to full and sync ammo type
for (const magazine of weaponWithModsArray.filter(item => item.slotId === this.modMagazineSlotId))
for (const magazine of weaponWithModsArray.filter((item) => item.slotId === this.modMagazineSlotId))
{
this.fillExistingMagazines(weaponWithModsArray, magazine, ammoTpl);
}
@ -211,12 +211,12 @@ export class BotWeaponGenerator
)
{
// Guns have variety of possible Chamber ids, patron_in_weapon/patron_in_weapon_000/patron_in_weapon_001
const chamberSlotNames = weaponItemTemplate._props.Chambers.map(x => x._name);
const chamberSlotNames = weaponItemTemplate._props.Chambers.map((x) => x._name);
this.addCartridgeToChamber(weaponWithModsArray, ammoTpl, chamberSlotNames);
}
// Fill UBGL if found
const ubglMod = weaponWithModsArray.find(x => x.slotId === "mod_launcher");
const ubglMod = weaponWithModsArray.find((x) => x.slotId === "mod_launcher");
let ubglAmmoTpl: string = undefined;
if (ubglMod)
{
@ -245,7 +245,7 @@ export class BotWeaponGenerator
{
for (const slotId of chamberSlotIds)
{
const existingItemWithSlot = weaponWithModsArray.find(x => x.slotId === slotId);
const existingItemWithSlot = weaponWithModsArray.find((x) => x.slotId === slotId);
if (!existingItemWithSlot)
{
// Not found, add new slot to weapon
@ -284,13 +284,15 @@ export class BotWeaponGenerator
botRole: string,
): Item[]
{
return [{
return [
{
_id: this.hashUtil.generate(),
_tpl: weaponTpl,
parentId: weaponParentId,
slotId: equipmentSlot,
...this.botGeneratorHelper.generateExtraPropertiesForItem(weaponItemTemplate, botRole),
}];
},
];
}
/**
@ -366,11 +368,11 @@ export class BotWeaponGenerator
}
// Iterate over required slots in db item, check mod exists for that slot
for (const modSlotTemplate of modTemplate._props.Slots.filter(slot => slot._required))
for (const modSlotTemplate of modTemplate._props.Slots.filter((slot) => slot._required))
{
const slotName = modSlotTemplate._name;
const weaponSlotItem = weaponItemArray.find(weaponItem =>
weaponItem.parentId === mod._id && weaponItem.slotId === slotName,
const weaponSlotItem = weaponItemArray.find(
(weaponItem) => weaponItem.parentId === mod._id && weaponItem.slotId === slotName,
);
if (!weaponSlotItem)
{
@ -441,9 +443,9 @@ export class BotWeaponGenerator
ammoTemplate,
inventory,
);
this.inventoryMagGenComponents.find(v => v.canHandleInventoryMagGen(inventoryMagGenModel)).process(
inventoryMagGenModel,
);
this.inventoryMagGenComponents
.find((v) => v.canHandleInventoryMagGen(inventoryMagGenModel))
.process(inventoryMagGenModel);
// Add x stacks of bullets to SecuredContainer (bots use a magic mag packing skill to reload instantly)
this.addAmmoToSecureContainer(
@ -467,7 +469,7 @@ export class BotWeaponGenerator
): void
{
// Find ubgl mod item + get details of it from db
const ubglMod = weaponMods.find(x => x.slotId === "mod_launcher");
const ubglMod = weaponMods.find((x) => x.slotId === "mod_launcher");
const ubglDbTemplate = this.itemHelper.getItem(ubglMod._tpl)[1];
// Define min/max of how many grenades bot will have
@ -488,9 +490,9 @@ export class BotWeaponGenerator
ubglAmmoDbTemplate,
inventory,
);
this.inventoryMagGenComponents.find(v => v.canHandleInventoryMagGen(ubglAmmoGenModel)).process(
ubglAmmoGenModel,
);
this.inventoryMagGenComponents
.find((v) => v.canHandleInventoryMagGen(ubglAmmoGenModel))
.process(ubglAmmoGenModel);
// Store extra grenades in secure container
this.addAmmoToSecureContainer(5, generatedWeaponResult.chosenUbglAmmoTpl, 20, inventory);
@ -536,7 +538,7 @@ export class BotWeaponGenerator
botRole: string,
): string
{
const magazine = weaponMods.find(m => m.slotId === this.modMagazineSlotId);
const magazine = weaponMods.find((m) => m.slotId === this.modMagazineSlotId);
if (!magazine)
{
// Edge case - magazineless chamber loaded weapons dont have magazines, e.g. mp18
@ -736,8 +738,8 @@ export class BotWeaponGenerator
magazineTemplate: ITemplateItem,
): void
{
const magazineCartridgeChildItem = weaponWithMods.find(m =>
m.parentId === magazine._id && m.slotId === "cartridges",
const magazineCartridgeChildItem = weaponWithMods.find(
(m) => m.parentId === magazine._id && m.slotId === "cartridges",
);
if (magazineCartridgeChildItem)
{
@ -766,7 +768,7 @@ export class BotWeaponGenerator
// for CylinderMagazine we exchange the ammo in the "camoras".
// This might not be necessary since we already filled the camoras with a random whitelisted and compatible ammo type,
// but I'm not sure whether this is also used elsewhere
const camoras = weaponMods.filter(x => x.parentId === magazineId && x.slotId.startsWith("camora"));
const camoras = weaponMods.filter((x) => x.parentId === magazineId && x.slotId.startsWith("camora"));
for (const camora of camoras)
{
camora._tpl = ammoTpl;

View File

@ -47,7 +47,7 @@ export class FenceBaseAssortGenerator
const blockedSeasonalItems = this.seasonalEventService.getInactiveSeasonalEventItems();
const baseFenceAssort = this.databaseServer.getTables().traders[Traders.FENCE].assort;
for (const rootItemDb of this.itemHelper.getItems().filter(item => this.isValidFenceItem(item)))
for (const rootItemDb of this.itemHelper.getItems().filter((item) => this.isValidFenceItem(item)))
{
// Skip blacklisted items
if (this.itemFilterService.isItemBlacklisted(rootItemDb._id))
@ -86,13 +86,15 @@ export class FenceBaseAssortGenerator
}
// Create item object in array
const itemWithChildrenToAdd: Item[] = [{
const itemWithChildrenToAdd: Item[] = [
{
_id: this.hashUtil.generate(),
_tpl: rootItemDb._id,
parentId: "hideout",
slotId: "hideout",
upd: { StackObjectsCount: 9999999 },
}];
},
];
// Ensure ammo is not above penetration limit value
if (this.itemHelper.isOfBaseclasses(rootItemDb._id, [BaseClasses.AMMO_BOX, BaseClasses.AMMO]))
@ -141,7 +143,7 @@ export class FenceBaseAssortGenerator
for (const defaultPreset of defaultPresets)
{
// Skip presets we've already added
if (baseFenceAssort.items.some(item => item.upd && item.upd.sptPresetId === defaultPreset._id))
if (baseFenceAssort.items.some((item) => item.upd && item.upd.sptPresetId === defaultPreset._id))
{
continue;
}
@ -249,7 +251,7 @@ export class FenceBaseAssortGenerator
}
// Check for and add required soft inserts to armors
const requiredSlots = itemDbDetails._props.Slots.filter(slot => slot._required);
const requiredSlots = itemDbDetails._props.Slots.filter((slot) => slot._required);
const hasRequiredSlots = requiredSlots.length > 0;
if (hasRequiredSlots)
{
@ -281,7 +283,7 @@ export class FenceBaseAssortGenerator
}
// Check for and add plate items
const plateSlots = itemDbDetails._props.Slots.filter(slot =>
const plateSlots = itemDbDetails._props.Slots.filter((slot) =>
this.itemHelper.isRemovablePlateSlot(slot._name),
);
if (plateSlots.length > 0)

View File

@ -92,7 +92,7 @@ export class LocationGenerator
}
// Add mounted weapons to output loot
result.push(...staticWeaponsOnMapClone ?? []);
result.push(...(staticWeaponsOnMapClone ?? []));
const allStaticContainersOnMapClone = this.cloner.clone(mapData.staticContainers.staticContainers);
@ -137,8 +137,10 @@ export class LocationGenerator
// Randomisation is turned off globally or just turned off for this map
if (
!(this.locationConfig.containerRandomisationSettings.enabled
&& this.locationConfig.containerRandomisationSettings.maps[locationId])
!(
this.locationConfig.containerRandomisationSettings.enabled
&& this.locationConfig.containerRandomisationSettings.maps[locationId]
)
)
{
this.logger.debug(
@ -221,15 +223,13 @@ export class LocationGenerator
for (const chosenContainerId of chosenContainerIds)
{
// Look up container object from full list of containers on map
const containerObject = staticRandomisableContainersOnMap.find(staticContainer =>
staticContainer.template.Id === chosenContainerId,
const containerObject = staticRandomisableContainersOnMap.find(
(staticContainer) => staticContainer.template.Id === chosenContainerId,
);
if (!containerObject)
{
this.logger.debug(
`Container: ${
chosenContainerIds[chosenContainerId]
} not found in staticRandomisableContainersOnMap, this is bad`,
`Container: ${chosenContainerIds[chosenContainerId]} not found in staticRandomisableContainersOnMap, this is bad`,
);
continue;
}
@ -265,8 +265,10 @@ export class LocationGenerator
*/
protected getRandomisableContainersOnMap(staticContainers: IStaticContainerData[]): IStaticContainerData[]
{
return staticContainers.filter(staticContainer =>
staticContainer.probability !== 1 && !staticContainer.template.IsAlwaysSpawn
return staticContainers.filter(
(staticContainer) =>
staticContainer.probability !== 1
&& !staticContainer.template.IsAlwaysSpawn
&& !this.locationConfig.containerRandomisationSettings.containerTypesToNotRandomise.includes(
staticContainer.template.Items[0]._tpl,
),
@ -280,8 +282,10 @@ export class LocationGenerator
*/
protected getGuaranteedContainers(staticContainersOnMap: IStaticContainerData[]): IStaticContainerData[]
{
return staticContainersOnMap.filter(staticContainer =>
staticContainer.probability === 1 || staticContainer.template.IsAlwaysSpawn
return staticContainersOnMap.filter(
(staticContainer) =>
staticContainer.probability === 1
|| staticContainer.template.IsAlwaysSpawn
|| this.locationConfig.containerRandomisationSettings.containerTypesToNotRandomise.includes(
staticContainer.template.Items[0]._tpl,
),
@ -415,9 +419,9 @@ export class LocationGenerator
const containerLootPool = this.getPossibleLootItemsForContainer(containerTpl, staticLootDist);
// Some containers need to have items forced into it (quest keys etc)
const tplsForced = staticForced.filter(forcedStaticProp =>
forcedStaticProp.containerId === containerClone.template.Id,
).map(x => x.itemTpl);
const tplsForced = staticForced
.filter((forcedStaticProp) => forcedStaticProp.containerId === containerClone.template.Id)
.map((x) => x.itemTpl);
// Draw random loot
// Money spawn more than once in container
@ -426,11 +430,9 @@ export class LocationGenerator
// Choose items to add to container, factor in weighting + lock money down
// Filter out items picked that're already in the above `tplsForced` array
const chosenTpls = containerLootPool.draw(
itemCountToAdd,
this.locationConfig.allowDuplicateItemsInStaticContainers,
locklist,
).filter(tpl => !tplsForced.includes(tpl));
const chosenTpls = containerLootPool
.draw(itemCountToAdd, this.locationConfig.allowDuplicateItemsInStaticContainers, locklist)
.filter((tpl) => !tplsForced.includes(tpl));
// Add forced loot to chosen item pool
const tplsToAddToContainer = tplsForced.concat(chosenTpls);
@ -495,7 +497,9 @@ export class LocationGenerator
const width = containerTemplate._props.Grids[0]._props.cellsH;
// Calcualte 2d array and return
return Array(height).fill(0).map(() => Array(width).fill(0));
return Array(height)
.fill(0)
.map(() => Array(width).fill(0));
}
/**
@ -600,7 +604,7 @@ export class LocationGenerator
// Build the list of forced loot from both `spawnpointsForced` and any point marked `IsAlwaysSpawn`
dynamicForcedSpawnPoints.push(...dynamicLootDist.spawnpointsForced);
dynamicForcedSpawnPoints.push(...dynamicLootDist.spawnpoints.filter(point => point.template.IsAlwaysSpawn));
dynamicForcedSpawnPoints.push(...dynamicLootDist.spawnpoints.filter((point) => point.template.IsAlwaysSpawn));
// Add forced loot
this.addForcedLoot(loot, dynamicForcedSpawnPoints, locationName);
@ -663,7 +667,7 @@ export class LocationGenerator
// Filter out duplicate locationIds
chosenSpawnpoints = [
...new Map(chosenSpawnpoints.map(spawnPoint => [spawnPoint.locationId, spawnPoint])).values(),
...new Map(chosenSpawnpoints.map((spawnPoint) => [spawnPoint.locationId, spawnPoint])).values(),
];
// Do we have enough items in pool to fulfill requirement
@ -706,8 +710,9 @@ export class LocationGenerator
for (const itemDist of spawnPoint.itemDistribution)
{
if (
!seasonalEventActive && seasonalItemTplBlacklist.includes(
spawnPoint.template.Items.find(item => item._id === itemDist.composedKey.key)._tpl,
!seasonalEventActive
&& seasonalItemTplBlacklist.includes(
spawnPoint.template.Items.find((item) => item._id === itemDist.composedKey.key)._tpl,
)
)
{
@ -758,8 +763,8 @@ export class LocationGenerator
for (const itemTpl of lootToForceSingleAmountOnMap)
{
// Get all spawn positions for item tpl in forced loot array
const items = forcedSpawnPoints.filter(forcedSpawnPoint =>
forcedSpawnPoint.template.Items[0]._tpl === itemTpl,
const items = forcedSpawnPoints.filter(
(forcedSpawnPoint) => forcedSpawnPoint.template.Items[0]._tpl === itemTpl,
);
if (!items || items.length === 0)
{
@ -783,7 +788,7 @@ export class LocationGenerator
// Choose 1 out of all found spawn positions for spawn id and add to loot array
for (const spawnPointLocationId of spawnpointArray.draw(1, false))
{
const itemToAdd = items.find(item => item.locationId === spawnPointLocationId);
const itemToAdd = items.find((item) => item.locationId === spawnPointLocationId);
const lootItem = itemToAdd.template;
lootItem.Root = this.objectId.generate();
lootItem.Items[0]._id = lootItem.Root;
@ -819,8 +824,8 @@ export class LocationGenerator
locationTemplateToAdd.Items[0]._id = locationTemplateToAdd.Root;
// Push forced location into array as long as it doesnt exist already
const existingLocation = lootLocationTemplates.find(spawnPoint =>
spawnPoint.Id === locationTemplateToAdd.Id,
const existingLocation = lootLocationTemplates.find(
(spawnPoint) => spawnPoint.Id === locationTemplateToAdd.Id,
);
if (!existingLocation)
{
@ -848,7 +853,7 @@ export class LocationGenerator
staticAmmoDist: Record<string, IStaticAmmoDetails[]>,
): IContainerItem
{
const chosenItem = spawnPoint.template.Items.find(item => item._id === chosenComposedKey);
const chosenItem = spawnPoint.template.Items.find((item) => item._id === chosenComposedKey);
const chosenTpl = chosenItem._tpl;
const itemTemplate = this.itemHelper.getItem(chosenTpl)[1];
@ -858,7 +863,8 @@ export class LocationGenerator
// Money/Ammo - don't rely on items in spawnPoint.template.Items so we can randomise it ourselves
if (this.itemHelper.isOfBaseclasses(chosenTpl, [BaseClasses.MONEY, BaseClasses.AMMO]))
{
const stackCount = itemTemplate._props.StackMaxSize === 1
const stackCount
= itemTemplate._props.StackMaxSize === 1
? 1
: this.randomUtil.getInt(itemTemplate._props.StackMinRandom, itemTemplate._props.StackMaxRandom);
@ -948,10 +954,10 @@ export class LocationGenerator
{
if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.WEAPON))
{
return items.find(v => v._tpl === chosenTpl && v.parentId === undefined);
return items.find((v) => v._tpl === chosenTpl && v.parentId === undefined);
}
return items.find(item => item._tpl === chosenTpl);
return items.find((item) => item._tpl === chosenTpl);
}
// TODO: rewrite, BIG yikes
@ -979,7 +985,8 @@ export class LocationGenerator
)
{
// Edge case - some ammos e.g. flares or M406 grenades shouldn't be stacked
const stackCount = itemTemplate._props.StackMaxSize === 1
const stackCount
= itemTemplate._props.StackMaxSize === 1
? 1
: this.randomUtil.getInt(itemTemplate._props.StackMinRandom, itemTemplate._props.StackMaxRandom);
@ -1055,7 +1062,7 @@ export class LocationGenerator
// it can handle revolver ammo (it's not restructured to be used here yet.)
// General: Make a WeaponController for Ragfair preset stuff and the generating weapons and ammo stuff from
// BotGenerator
const magazine = items.filter(item => item.slotId === "mod_magazine")[0];
const magazine = items.filter((item) => item.slotId === "mod_magazine")[0];
// some weapon presets come without magazine; only fill the mag if it exists
if (magazine)
{

View File

@ -6,7 +6,6 @@ import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
import { IPreset } from "@spt-aki/models/eft/common/IGlobals";
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem";
import { AddItem } from "@spt-aki/models/eft/inventory/IAddItemRequestData";
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
import { ISealedAirdropContainerSettings, RewardDetails } from "@spt-aki/models/spt/config/IInventoryConfig";
import { LootItem } from "@spt-aki/models/spt/services/LootItem";
@ -71,7 +70,7 @@ export class LootGenerator
if (desiredWeaponCrateCount > 0)
{
// Get list of all sealed containers from db
const sealedWeaponContainerPool = Object.values(tables.templates.items).filter(x =>
const sealedWeaponContainerPool = Object.values(tables.templates.items).filter((x) =>
x._name.includes("event_container_airdrop"),
);
@ -89,7 +88,8 @@ export class LootGenerator
}
// Get items from items.json that have a type of item + not in global blacklist + basetype is in whitelist
const items = Object.entries(tables.templates.items).filter(x =>
const items = Object.entries(tables.templates.items).filter(
(x) =>
!itemBlacklist.has(x[1]._id)
&& x[1]._type.toLowerCase() === "item"
&& !x[1]._props.QuestItem
@ -119,7 +119,7 @@ export class LootGenerator
);
if (randomisedWeaponPresetCount > 0)
{
const weaponDefaultPresets = globalDefaultPresets.filter(preset =>
const weaponDefaultPresets = globalDefaultPresets.filter((preset) =>
this.itemHelper.isOfBaseclass(preset._encyclopedia, BaseClasses.WEAPON),
);
@ -150,10 +150,10 @@ export class LootGenerator
);
if (randomisedArmorPresetCount > 0)
{
const armorDefaultPresets = globalDefaultPresets.filter(preset =>
const armorDefaultPresets = globalDefaultPresets.filter((preset) =>
this.itemHelper.armorItemCanHoldMods(preset._encyclopedia),
);
const levelFilteredArmorPresets = armorDefaultPresets.filter(armor =>
const levelFilteredArmorPresets = armorDefaultPresets.filter((armor) =>
this.armorIsDesiredProtectionLevel(armor, options),
);
@ -189,21 +189,21 @@ export class LootGenerator
*/
protected armorIsDesiredProtectionLevel(armor: IPreset, options: LootRequest): boolean
{
const frontPlate = armor._items.find(mod => mod?.slotId?.toLowerCase() === "front_plate");
const frontPlate = armor._items.find((mod) => mod?.slotId?.toLowerCase() === "front_plate");
if (frontPlate)
{
const plateDb = this.itemHelper.getItem(frontPlate._tpl);
return options.armorLevelWhitelist.includes(Number.parseInt(plateDb[1]._props.armorClass as any));
}
const helmetTop = armor._items.find(mod => mod?.slotId?.toLowerCase() === "helmet_top");
const helmetTop = armor._items.find((mod) => mod?.slotId?.toLowerCase() === "helmet_top");
if (helmetTop)
{
const plateDb = this.itemHelper.getItem(helmetTop._tpl);
return options.armorLevelWhitelist.includes(Number.parseInt(plateDb[1]._props.armorClass as any));
}
const softArmorFront = armor._items.find(mod => mod?.slotId?.toLowerCase() === "soft_armor_front");
const softArmorFront = armor._items.find((mod) => mod?.slotId?.toLowerCase() === "soft_armor_front");
if (softArmorFront)
{
const plateDb = this.itemHelper.getItem(softArmorFront._tpl);
@ -470,7 +470,7 @@ export class LootGenerator
// Need to find boxes that matches weapons caliber
const weaponCaliber = weaponDetailsDb._props.ammoCaliber;
const ammoBoxesMatchingCaliber = ammoBoxesDetails.filter(x => x._props.ammoCaliber === weaponCaliber);
const ammoBoxesMatchingCaliber = ammoBoxesDetails.filter((x) => x._props.ammoCaliber === weaponCaliber);
if (ammoBoxesMatchingCaliber.length === 0)
{
this.logger.debug(`No ammo box with caliber ${weaponCaliber} found, skipping`);
@ -490,7 +490,8 @@ export class LootGenerator
}
// Get all items of the desired type + not quest items + not globally blacklisted
const rewardItemPool = Object.values(this.databaseServer.getTables().templates.items).filter(x =>
const rewardItemPool = Object.values(this.databaseServer.getTables().templates.items).filter(
(x) =>
x._parent === rewardTypeId
&& x._type.toLowerCase() === "item"
&& !this.itemFilterService.isItemBlacklisted(x._id)
@ -544,8 +545,8 @@ export class LootGenerator
}
// Get items that fulfil reward type criteria from items that fit on gun
const relatedItems = linkedItemsToWeapon.filter(x =>
x._parent === rewardTypeId && !this.itemFilterService.isItemBlacklisted(x._id),
const relatedItems = linkedItemsToWeapon.filter(
(x) => x._parent === rewardTypeId && !this.itemFilterService.isItemBlacklisted(x._id),
);
if (!relatedItems || relatedItems.length === 0)
{

View File

@ -58,7 +58,8 @@ export class PMCLootGenerator
// Blacklist inactive seasonal items
itemBlacklist.push(...this.seasonalEventService.getInactiveSeasonalEventItems());
const itemsToAdd = Object.values(items).filter(item =>
const itemsToAdd = Object.values(items).filter(
(item) =>
allowedItemTypes.includes(item._parent)
&& this.itemHelper.isValidItem(item._id)
&& !pmcItemBlacklist.includes(item._id)
@ -87,7 +88,7 @@ export class PMCLootGenerator
{
// Invert price so cheapest has a larger weight
// Times by highest price so most expensive item has weight of 1
this.pocketLootPool[key] = Math.round(1 / this.pocketLootPool[key] * highestPrice);
this.pocketLootPool[key] = Math.round((1 / this.pocketLootPool[key]) * highestPrice);
}
this.weightedRandomHelper.reduceWeightValues(this.pocketLootPool);
@ -117,7 +118,8 @@ export class PMCLootGenerator
// Blacklist seasonal items
itemBlacklist.push(...this.seasonalEventService.getInactiveSeasonalEventItems());
const itemsToAdd = Object.values(items).filter(item =>
const itemsToAdd = Object.values(items).filter(
(item) =>
allowedItemTypes.includes(item._parent)
&& this.itemHelper.isValidItem(item._id)
&& !pmcItemBlacklist.includes(item._id)
@ -145,7 +147,7 @@ export class PMCLootGenerator
{
// Invert price so cheapest has a larger weight
// Times by highest price so most expensive item has weight of 1
this.vestLootPool[key] = Math.round(1 / this.vestLootPool[key] * highestPrice);
this.vestLootPool[key] = Math.round((1 / this.vestLootPool[key]) * highestPrice);
}
this.weightedRandomHelper.reduceWeightValues(this.vestLootPool);
@ -186,7 +188,8 @@ export class PMCLootGenerator
// Blacklist seasonal items
itemBlacklist.push(...this.seasonalEventService.getInactiveSeasonalEventItems());
const itemsToAdd = Object.values(items).filter(item =>
const itemsToAdd = Object.values(items).filter(
(item) =>
allowedItemTypes.includes(item._parent)
&& this.itemHelper.isValidItem(item._id)
&& !pmcItemBlacklist.includes(item._id)
@ -213,7 +216,7 @@ export class PMCLootGenerator
{
// Invert price so cheapest has a larger weight
// Times by highest price so most expensive item has weight of 1
this.backpackLootPool[key] = Math.round(1 / this.backpackLootPool[key] * highestPrice);
this.backpackLootPool[key] = Math.round((1 / this.backpackLootPool[key]) * highestPrice);
}
this.weightedRandomHelper.reduceWeightValues(this.backpackLootPool);

View File

@ -162,11 +162,13 @@ export class PlayerScavGenerator
}
const itemTemplate = itemResult[1];
const itemsToAdd: Item[] = [{
const itemsToAdd: Item[] = [
{
_id: this.hashUtil.generate(),
_tpl: itemTemplate._id,
...this.botGeneratorHelper.generateExtraPropertiesForItem(itemTemplate),
}];
},
];
const result = this.botGeneratorHelper.addItemWithChildrenToEquipmentSlot(
containersToAddTo,

View File

@ -72,7 +72,7 @@ export class RagfairAssortGenerator
const results: Item[][] = [];
/** Get cloned items from db */
const dbItemsClone = this.itemHelper.getItems().filter(item => item._type !== "Node");
const dbItemsClone = this.itemHelper.getItems().filter((item) => item._type !== "Node");
/** Store processed preset tpls so we dont add them when procesing non-preset items */
const processedArmorItems: string[] = [];
@ -105,7 +105,8 @@ export class RagfairAssortGenerator
// Skip seasonal items when not in-season
if (
this.ragfairConfig.dynamic.removeSeasonalItemsWhenNotInEvent && !seasonalEventActive
this.ragfairConfig.dynamic.removeSeasonalItemsWhenNotInEvent
&& !seasonalEventActive
&& seasonalItemTplBlacklist.includes(item._id)
)
{

View File

@ -135,7 +135,7 @@ export class RagfairOfferGenerator
}
}
const itemCount = items.filter(x => x.slotId === "hideout").length;
const itemCount = items.filter((x) => x.slotId === "hideout").length;
const roublePrice = Math.round(this.convertOfferRequirementsIntoRoubles(offerRequirements));
const offer: IRagfairOffer = {
@ -143,9 +143,8 @@ export class RagfairOfferGenerator
intId: this.offerCounter,
user: {
id: this.getTraderId(userID),
memberType: userID === "ragfair"
? MemberCategory.DEFAULT
: this.ragfairServerHelper.getMemberType(userID),
memberType:
userID === "ragfair" ? MemberCategory.DEFAULT : this.ragfairServerHelper.getMemberType(userID),
nickname: this.ragfairServerHelper.getNickname(userID),
rating: this.getRating(userID),
isRatingGrowing: this.getRatingGrowing(userID),
@ -410,7 +409,7 @@ export class RagfairOfferGenerator
return false;
}
const plateSlots = presetWithChildren.filter(item =>
const plateSlots = presetWithChildren.filter((item) =>
this.itemHelper.getRemovablePlateSlotIds().includes(item.slotId?.toLowerCase()),
);
if (plateSlots.length === 0)
@ -459,7 +458,8 @@ export class RagfairOfferGenerator
);
const isBarterOffer = this.randomUtil.getChance100(this.ragfairConfig.dynamic.barter.chancePercent);
const isPackOffer = this.randomUtil.getChance100(this.ragfairConfig.dynamic.pack.chancePercent)
const isPackOffer
= this.randomUtil.getChance100(this.ragfairConfig.dynamic.pack.chancePercent)
&& !isBarterOffer
&& itemWithChildren.length === 1
&& this.itemHelper.isOfBaseclasses(
@ -477,7 +477,7 @@ export class RagfairOfferGenerator
const shouldRemovePlates = this.randomUtil.getChance100(armorConfig.removeRemovablePlateChance);
if (shouldRemovePlates && this.itemHelper.armorItemHasRemovablePlateSlots(itemWithChildren[0]._tpl))
{
const offerItemPlatesToRemove = itemWithChildren.filter(item =>
const offerItemPlatesToRemove = itemWithChildren.filter((item) =>
armorConfig.plateSlotIdToRemovePool.includes(item.slotId?.toLowerCase()),
);
@ -683,8 +683,8 @@ export class RagfairOfferGenerator
this.randomiseArmorDurabilityValues(itemWithMods, currentMultiplier, maxMultiplier);
// Add hits to visor
const visorMod = itemWithMods.find(item =>
item.parentId === BaseClasses.ARMORED_EQUIPMENT && item.slotId === "mod_equipment_000",
const visorMod = itemWithMods.find(
(item) => item.parentId === BaseClasses.ARMORED_EQUIPMENT && item.slotId === "mod_equipment_000",
);
if (this.randomUtil.getChance100(25) && visorMod)
{
@ -715,8 +715,8 @@ export class RagfairOfferGenerator
if (rootItem.upd.Key && itemDetails._props.MaximumNumberOfUsage > 1)
{
// randomize key uses
rootItem.upd.Key.NumberOfUsages = Math.round(itemDetails._props.MaximumNumberOfUsage * (1 - maxMultiplier))
|| 0;
rootItem.upd.Key.NumberOfUsages
= Math.round(itemDetails._props.MaximumNumberOfUsage * (1 - maxMultiplier)) || 0;
return;
}
@ -792,8 +792,8 @@ export class RagfairOfferGenerator
{
this.itemHelper.addUpdObjectToItem(armorItem);
const lowestMaxDurability = this.randomUtil.getFloat(maxMultiplier, 1)
* itemDbDetails._props.MaxDurability;
const lowestMaxDurability
= this.randomUtil.getFloat(maxMultiplier, 1) * itemDbDetails._props.MaxDurability;
const chosenMaxDurability = Math.round(
this.randomUtil.getFloat(lowestMaxDurability, itemDbDetails._props.MaxDurability),
);
@ -882,13 +882,15 @@ export class RagfairOfferGenerator
const desiredItemCost = Math.round(priceOfItemOffer / barterItemCount);
// amount to go above/below when looking for an item (Wiggle cost of item a little)
const offerCostVariance = desiredItemCost * this.ragfairConfig.dynamic.barter.priceRangeVariancePercent / 100;
const offerCostVariance = (desiredItemCost * this.ragfairConfig.dynamic.barter.priceRangeVariancePercent) / 100;
const fleaPrices = this.getFleaPricesAsArray();
// Filter possible barters to items that match the price range + not itself
const filtered = fleaPrices.filter(x =>
x.price >= desiredItemCost - offerCostVariance && x.price <= desiredItemCost + offerCostVariance
const filtered = fleaPrices.filter(
(x) =>
x.price >= desiredItemCost - offerCostVariance
&& x.price <= desiredItemCost + offerCostVariance
&& x.tpl !== offerItems[0]._tpl,
);
@ -917,10 +919,10 @@ export class RagfairOfferGenerator
const fleaArray = Object.entries(fleaPrices).map(([tpl, price]) => ({ tpl: tpl, price: price }));
// Only get item prices for items that also exist in items.json
const filteredItems = fleaArray.filter(x => this.itemHelper.getItem(x.tpl)[0]);
const filteredItems = fleaArray.filter((x) => this.itemHelper.getItem(x.tpl)[0]);
this.allowedFleaPriceItemsForBarter = filteredItems.filter(x =>
!this.itemHelper.isOfBaseclasses(x.tpl, this.ragfairConfig.dynamic.barter.itemTypeBlacklist),
this.allowedFleaPriceItemsForBarter = filteredItems.filter(
(x) => !this.itemHelper.isOfBaseclasses(x.tpl, this.ragfairConfig.dynamic.barter.itemTypeBlacklist),
);
}
@ -941,8 +943,8 @@ export class RagfairOfferGenerator
): IBarterScheme[]
{
const currency = this.ragfairServerHelper.getDynamicOfferCurrency();
const price = this.ragfairPriceService.getDynamicOfferPriceForOffer(offerWithChildren, currency, isPackOffer)
* multipler;
const price
= this.ragfairPriceService.getDynamicOfferPriceForOffer(offerWithChildren, currency, isPackOffer) * multipler;
return [{ count: price, _tpl: currency }];
}

View File

@ -39,8 +39,8 @@ export class RepeatableQuestGenerator
@inject("LocalisationService") protected localisationService: LocalisationService,
@inject("ObjectId") protected objectId: ObjectId,
@inject("RepeatableQuestHelper") protected repeatableQuestHelper: RepeatableQuestHelper,
@inject("RepeatableQuestRewardGenerator") protected repeatableQuestRewardGenerator:
RepeatableQuestRewardGenerator,
@inject("RepeatableQuestRewardGenerator")
protected repeatableQuestRewardGenerator: RepeatableQuestRewardGenerator,
@inject("ConfigServer") protected configServer: ConfigServer,
@inject("RecursiveCloner") protected cloner: ICloner,
)
@ -67,11 +67,11 @@ export class RepeatableQuestGenerator
const questType = this.randomUtil.drawRandomFromList<string>(questTypePool.types)[0];
// get traders from whitelist and filter by quest type availability
let traders = repeatableConfig.traderWhitelist.filter(x => x.questTypes.includes(questType)).map(x =>
x.traderId,
);
let traders = repeatableConfig.traderWhitelist
.filter((x) => x.questTypes.includes(questType))
.map((x) => x.traderId);
// filter out locked traders
traders = traders.filter(x => pmcTraderInfo[x].unlocked);
traders = traders.filter((x) => pmcTraderInfo[x].unlocked);
const traderId = this.randomUtil.drawRandomFromList(traders)[0];
switch (questType)
@ -158,15 +158,15 @@ export class RepeatableQuestGenerator
return Math.sqrt(Math.sqrt(target) + bodyPart + dist + weaponRequirement) * kill;
}
targetsConfig = targetsConfig.filter(x =>
targetsConfig = targetsConfig.filter((x) =>
Object.keys(questTypePool.pool.Elimination.targets).includes(x.key),
);
if (targetsConfig.length === 0 || targetsConfig.every(x => x.data.isBoss))
if (targetsConfig.length === 0 || targetsConfig.every((x) => x.data.isBoss))
{
// There are no more targets left for elimination; delete it as a possible quest type
// 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");
questTypePool.types = questTypePool.types.filter((t) => t !== "Elimination");
return null;
}
@ -188,12 +188,12 @@ export class RepeatableQuestGenerator
}
else
{
locations = locations.filter(l => l !== "any");
locations = locations.filter((l) => l !== "any");
if (locations.length > 0)
{
locationKey = this.randomUtil.drawRandomFromList<string>(locations)[0];
questTypePool.pool.Elimination.targets[targetKey].locations = locations.filter(l =>
l !== locationKey,
questTypePool.pool.Elimination.targets[targetKey].locations = locations.filter(
(l) => l !== locationKey,
);
if (questTypePool.pool.Elimination.targets[targetKey].locations.length === 0)
{
@ -238,16 +238,18 @@ export class RepeatableQuestGenerator
if (targetsConfig.data(targetKey).isBoss)
{
// Get all boss spawn information
const bossSpawns = Object.values(this.databaseServer.getTables().locations).filter(x =>
"base" in x && "Id" in x.base,
).map(x => ({ Id: x.base.Id, BossSpawn: x.base.BossLocationSpawn }));
const bossSpawns = Object.values(this.databaseServer.getTables().locations)
.filter((x) => "base" in x && "Id" in x.base)
.map((x) => ({ Id: x.base.Id, BossSpawn: x.base.BossLocationSpawn }));
// filter for the current boss to spawn on map
const thisBossSpawns = bossSpawns.map(x => ({
const thisBossSpawns = bossSpawns
.map((x) => ({
Id: x.Id,
BossSpawn: x.BossSpawn.filter(e => e.BossName === targetKey),
})).filter(x => x.BossSpawn.length > 0);
BossSpawn: x.BossSpawn.filter((e) => e.BossName === targetKey),
}))
.filter((x) => x.BossSpawn.length > 0);
// remove blacklisted locations
const allowedSpawns = thisBossSpawns.filter(x => !eliminationConfig.distLocationBlacklist.includes(x.Id));
const allowedSpawns = thisBossSpawns.filter((x) => !eliminationConfig.distLocationBlacklist.includes(x.Id));
// if the boss spawns on nom-blacklisted locations and the current location is allowed we can generate a distance kill requirement
isDistanceRequirementAllowed = isDistanceRequirementAllowed && allowedSpawns.length > 0;
}
@ -260,7 +262,7 @@ export class RepeatableQuestGenerator
+ eliminationConfig.minDist,
);
distance = Math.ceil(distance / 5) * 5;
distanceDifficulty = maxDistDifficulty * distance / eliminationConfig.maxDist;
distanceDifficulty = (maxDistDifficulty * distance) / eliminationConfig.maxDist;
}
let allowedWeaponsCategory: string = undefined;
@ -269,13 +271,14 @@ export class RepeatableQuestGenerator
// Filter out close range weapons from far distance requirement
if (distance > 50)
{
weaponCategoryRequirementConfig = weaponCategoryRequirementConfig.filter(category =>
weaponCategoryRequirementConfig = weaponCategoryRequirementConfig.filter((category) =>
["Shotgun", "Pistol"].includes(category.key),
);
}
else if (distance < 20)
{ // Filter out far range weapons from close distance requirement
weaponCategoryRequirementConfig = weaponCategoryRequirementConfig.filter(category =>
{
// Filter out far range weapons from close distance requirement
weaponCategoryRequirementConfig = weaponCategoryRequirementConfig.filter((category) =>
["MarksmanRifle", "DMR"].includes(category.key),
);
}
@ -497,8 +500,8 @@ export class RepeatableQuestGenerator
this.mathUtil.interp1(pmcLevel, levelsConfig, roublesConfig) * this.randomUtil.getFloat(0.5, 1),
);
roublesBudget = Math.max(roublesBudget, 5000);
let itemSelection = possibleItemsToRetrievePool.filter(x =>
this.itemHelper.getItemPrice(x[0]) < roublesBudget,
let itemSelection = possibleItemsToRetrievePool.filter(
(x) => this.itemHelper.getItemPrice(x[0]) < roublesBudget,
);
// We also have the option to use whitelist and/or blacklist which is defined in repeatableQuests.json as
@ -509,15 +512,16 @@ export class RepeatableQuestGenerator
= this.databaseServer.getTables().templates.repeatableQuests.data.Completion.itemsWhitelist;
// Filter and concatenate the arrays according to current player level
const itemIdsWhitelisted = itemWhitelist.filter(p => p.minPlayerLevel <= pmcLevel).reduce(
(a, p) => a.concat(p.itemIds),
[],
);
const itemIdsWhitelisted = itemWhitelist
.filter((p) => p.minPlayerLevel <= pmcLevel)
.reduce((a, p) => a.concat(p.itemIds), []);
itemSelection = itemSelection.filter((x) =>
{
// Whitelist can contain item tpls and item base type ids
return itemIdsWhitelisted.some(v => this.itemHelper.isOfBaseclass(x[0], v))
|| itemIdsWhitelisted.includes(x[0]);
return (
itemIdsWhitelisted.some((v) => this.itemHelper.isOfBaseclass(x[0], v))
|| itemIdsWhitelisted.includes(x[0])
);
});
// check if items are missing
// const flatList = itemSelection.reduce((a, il) => a.concat(il[0]), []);
@ -530,15 +534,16 @@ export class RepeatableQuestGenerator
= this.databaseServer.getTables().templates.repeatableQuests.data.Completion.itemsBlacklist;
// we filter and concatenate the arrays according to current player level
const itemIdsBlacklisted = itemBlacklist.filter(p => p.minPlayerLevel <= pmcLevel).reduce(
(a, p) => a.concat(p.itemIds),
[],
);
const itemIdsBlacklisted = itemBlacklist
.filter((p) => p.minPlayerLevel <= pmcLevel)
.reduce((a, p) => a.concat(p.itemIds), []);
itemSelection = itemSelection.filter((x) =>
{
return itemIdsBlacklisted.every(v => !this.itemHelper.isOfBaseclass(x[0], v))
|| !itemIdsBlacklisted.includes(x[0]);
return (
itemIdsBlacklisted.every((v) => !this.itemHelper.isOfBaseclass(x[0], v))
|| !itemIdsBlacklisted.includes(x[0])
);
});
}
@ -601,7 +606,7 @@ export class RepeatableQuestGenerator
if (roublesBudget > 0)
{
// reduce the list possible items to fulfill the new budget constraint
itemSelection = itemSelection.filter(x => this.itemHelper.getItemPrice(x[0]) < roublesBudget);
itemSelection = itemSelection.filter((x) => this.itemHelper.getItemPrice(x[0]) < roublesBudget);
if (itemSelection.length === 0)
{
break;
@ -692,7 +697,7 @@ export class RepeatableQuestGenerator
if (Object.keys(questTypePool.pool.Exploration.locations).length === 0)
{
// there are no more locations left for exploration; delete it as a possible quest type
questTypePool.types = questTypePool.types.filter(t => t !== "Exploration");
questTypePool.types = questTypePool.types.filter((t) => t !== "Exploration");
return null;
}
@ -737,10 +742,12 @@ export class RepeatableQuestGenerator
const mapExits = this.getLocationExitsForSide(locationKey, repeatableConfig.side);
// Only get exits that have a greater than 0% chance to spawn
const exitPool = mapExits.filter(exit => exit.Chance > 0);
const exitPool = mapExits.filter((exit) => exit.Chance > 0);
// Exclude exits with a requirement to leave (e.g. car extracts)
const possibleExits = exitPool.filter(exit => !("PassageRequirement" in exit)
const possibleExits = exitPool.filter(
(exit) =>
!("PassageRequirement" in exit)
|| repeatableConfig.questConfig.Exploration.specificExits.passageRequirementWhitelist.includes(
exit.PassageRequirement,
),
@ -788,7 +795,7 @@ export class RepeatableQuestGenerator
const mapExtracts = this.databaseServer.getTables().locations[locationKey.toLocaleLowerCase()]
.allExtracts as Exit[];
return mapExtracts.filter(exit => exit.Side === playerSide);
return mapExtracts.filter((exit) => exit.Side === playerSide);
}
protected generatePickupQuest(
@ -811,18 +818,18 @@ export class RepeatableQuestGenerator
// const locationKey: string = this.randomUtil.drawRandomFromDict(questTypePool.pool.Pickup.locations)[0];
// const locationTarget = questTypePool.pool.Pickup.locations[locationKey];
const findCondition = quest.conditions.AvailableForFinish.find(x => x.conditionType === "FindItem");
const findCondition = quest.conditions.AvailableForFinish.find((x) => x.conditionType === "FindItem");
findCondition.target = [itemTypeToFetchWithCount.itemType];
findCondition.value = itemCountToFetch;
const counterCreatorCondition = quest.conditions.AvailableForFinish.find(x =>
x.conditionType === "CounterCreator",
const counterCreatorCondition = quest.conditions.AvailableForFinish.find(
(x) => x.conditionType === "CounterCreator",
);
// const locationCondition = counterCreatorCondition._props.counter.conditions.find(x => x._parent === "Location");
// (locationCondition._props as ILocationConditionProps).target = [...locationTarget];
const equipmentCondition = counterCreatorCondition.counter.conditions.find(x =>
x.conditionType === "Equipment",
const equipmentCondition = counterCreatorCondition.counter.conditions.find(
(x) => x.conditionType === "Equipment",
);
equipmentCondition.equipmentInclusive = [[itemTypeToFetchWithCount.itemType]];
@ -887,46 +894,36 @@ export class RepeatableQuestGenerator
// Get template id from config based on side and type of quest
questClone.templateId = this.questConfig.questTemplateIds[side.toLowerCase()][type.toLowerCase()];
questClone.name = questClone.name.replace("{traderId}", traderId).replace(
"{templateId}",
questClone.templateId,
);
questClone.note = questClone.note.replace("{traderId}", traderId).replace(
"{templateId}",
questClone.templateId,
);
questClone.description = questClone.description.replace("{traderId}", traderId).replace(
"{templateId}",
questClone.templateId,
);
questClone.successMessageText = questClone.successMessageText.replace("{traderId}", traderId).replace(
"{templateId}",
questClone.templateId,
);
questClone.failMessageText = questClone.failMessageText.replace("{traderId}", traderId).replace(
"{templateId}",
questClone.templateId,
);
questClone.startedMessageText = questClone.startedMessageText.replace("{traderId}", traderId).replace(
"{templateId}",
questClone.templateId,
);
questClone.changeQuestMessageText = questClone.changeQuestMessageText.replace("{traderId}", traderId).replace(
"{templateId}",
questClone.templateId,
);
questClone.acceptPlayerMessage = questClone.acceptPlayerMessage.replace("{traderId}", traderId).replace(
"{templateId}",
questClone.templateId,
);
questClone.declinePlayerMessage = questClone.declinePlayerMessage.replace("{traderId}", traderId).replace(
"{templateId}",
questClone.templateId,
);
questClone.completePlayerMessage = questClone.completePlayerMessage.replace("{traderId}", traderId).replace(
"{templateId}",
questClone.templateId,
);
questClone.name = questClone.name
.replace("{traderId}", traderId)
.replace("{templateId}", questClone.templateId);
questClone.note = questClone.note
.replace("{traderId}", traderId)
.replace("{templateId}", questClone.templateId);
questClone.description = questClone.description
.replace("{traderId}", traderId)
.replace("{templateId}", questClone.templateId);
questClone.successMessageText = questClone.successMessageText
.replace("{traderId}", traderId)
.replace("{templateId}", questClone.templateId);
questClone.failMessageText = questClone.failMessageText
.replace("{traderId}", traderId)
.replace("{templateId}", questClone.templateId);
questClone.startedMessageText = questClone.startedMessageText
.replace("{traderId}", traderId)
.replace("{templateId}", questClone.templateId);
questClone.changeQuestMessageText = questClone.changeQuestMessageText
.replace("{traderId}", traderId)
.replace("{templateId}", questClone.templateId);
questClone.acceptPlayerMessage = questClone.acceptPlayerMessage
.replace("{traderId}", traderId)
.replace("{templateId}", questClone.templateId);
questClone.declinePlayerMessage = questClone.declinePlayerMessage
.replace("{traderId}", traderId)
.replace("{templateId}", questClone.templateId);
questClone.completePlayerMessage = questClone.completePlayerMessage
.replace("{traderId}", traderId)
.replace("{templateId}", questClone.templateId);
return questClone;
}

View File

@ -94,11 +94,13 @@ export class RepeatableQuestRewardGenerator
// rewards are generated based on pmcLevel, difficulty and a random spread
const rewardXP = Math.floor(
effectiveDifficulty * this.mathUtil.interp1(pmcLevel, levelsConfig, xpConfig)
effectiveDifficulty
* this.mathUtil.interp1(pmcLevel, levelsConfig, xpConfig)
* this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig),
);
const rewardRoubles = Math.floor(
effectiveDifficulty * this.mathUtil.interp1(pmcLevel, levelsConfig, roublesConfig)
effectiveDifficulty
* this.mathUtil.interp1(pmcLevel, levelsConfig, roublesConfig)
* this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig),
);
const rewardNumItems = this.randomUtil.randInt(
@ -107,7 +109,9 @@ export class RepeatableQuestRewardGenerator
);
const rewardReputation
= Math.round(
100 * effectiveDifficulty * this.mathUtil.interp1(pmcLevel, levelsConfig, reputationConfig)
100
* effectiveDifficulty
* this.mathUtil.interp1(pmcLevel, levelsConfig, reputationConfig)
* this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig),
) / 100;
const skillRewardChance = this.mathUtil.interp1(pmcLevel, levelsConfig, skillRewardChanceConfig);
@ -134,7 +138,7 @@ export class RepeatableQuestRewardGenerator
this.addMoneyReward(traderId, rewards, rewardRoubles, rewardIndex);
rewardIndex++;
const traderWhitelistDetails = repeatableConfig.traderWhitelist.find(x => x.traderId === traderId);
const traderWhitelistDetails = repeatableConfig.traderWhitelist.find((x) => x.traderId === traderId);
if (
traderWhitelistDetails.rewardCanBeWeapon
&& this.randomUtil.getChance100(traderWhitelistDetails.weaponRewardChancePercent)
@ -150,7 +154,7 @@ export class RepeatableQuestRewardGenerator
while (defaultPresetPool.hasValues())
{
const randomPreset = defaultPresetPool.getRandomValue();
const tpls = randomPreset._items.map(item => item._tpl);
const tpls = randomPreset._items.map((item) => item._tpl);
const presetPrice = this.itemHelper.getItemAndChildrenPrice(tpls);
if (presetPrice <= roublesBudget)
{
@ -307,14 +311,16 @@ export class RepeatableQuestRewardGenerator
*/
protected canIncreaseRewardItemStackSize(item: ITemplateItem, maxRoublePriceToStack: number): boolean
{
return this.presetHelper.getDefaultPresetOrItemPrice(item._id) < maxRoublePriceToStack
return (
this.presetHelper.getDefaultPresetOrItemPrice(item._id) < maxRoublePriceToStack
&& !this.itemHelper.isOfBaseclasses(item._id, [
BaseClasses.WEAPON,
BaseClasses.ARMORED_EQUIPMENT,
BaseClasses.AMMO,
])
&& !this.itemHelper.itemRequiresSoftInserts(item._id)
&& this.randomUtil.getChance100(25);
&& this.randomUtil.getChance100(25)
);
}
protected calculateAmmoStackSizeThatFitsBudget(
@ -354,7 +360,7 @@ export class RepeatableQuestRewardGenerator
const rewardableItemPool = this.getRewardableItems(repeatableConfig, traderId);
const minPrice = Math.min(25000, 0.5 * roublesBudget);
let rewardableItemPoolWithinBudget = rewardableItemPool.map(x => x[1]);
let rewardableItemPoolWithinBudget = rewardableItemPool.map((x) => x[1]);
rewardableItemPoolWithinBudget = this.filterRewardPoolWithinBudget(
rewardableItemPoolWithinBudget,
roublesBudget,
@ -369,9 +375,9 @@ export class RepeatableQuestRewardGenerator
}),
);
// In case we don't find any items in the price range
rewardableItemPoolWithinBudget = rewardableItemPool.filter(x =>
this.itemHelper.getItemPrice(x[0]) < roublesBudget,
).map(x => x[1]);
rewardableItemPoolWithinBudget = rewardableItemPool
.filter((x) => this.itemHelper.getItemPrice(x[0]) < roublesBudget)
.map((x) => x[1]);
}
return rewardableItemPoolWithinBudget;
@ -392,7 +398,7 @@ export class RepeatableQuestRewardGenerator
if (preset)
{
const rootItem = preset.find(x => x._tpl === tpl);
const rootItem = preset.find((x) => x._tpl === tpl);
rewardItem.items = this.itemHelper.reparentItemAndChildren(rootItem, preset);
rewardItem.target = rootItem._id; // Target property and root items id must match
}
@ -435,8 +441,8 @@ export class RepeatableQuestRewardGenerator
return false;
}
const traderWhitelist = repeatableQuestConfig.traderWhitelist.find(trader =>
trader.traderId === traderId,
const traderWhitelist = repeatableQuestConfig.traderWhitelist.find(
(trader) => trader.traderId === traderId,
);
return this.isValidRewardItem(tpl, repeatableQuestConfig, traderWhitelist?.rewardBaseWhitelist);
},
@ -502,7 +508,12 @@ export class RepeatableQuestRewardGenerator
return true;
}
protected addMoneyReward(traderId: string, rewards: IQuestRewards, rewardRoubles: number, rewardIndex: number): void
protected addMoneyReward(
traderId: string,
rewards: IQuestRewards,
rewardRoubles: number,
rewardIndex: number,
): void
{
// PK and Fence use euros
if (traderId === Traders.PEACEKEEPER || traderId === Traders.FENCE)

View File

@ -1,8 +1,7 @@
import { inject, injectable } from "tsyringe";
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
import { Product } from "@spt-aki/models/eft/common/tables/IBotBase";
import { Item, Upd } from "@spt-aki/models/eft/common/tables/IItem";
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem";
import { IHideoutScavCase } from "@spt-aki/models/eft/hideout/IHideoutScavCase";
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
@ -58,7 +57,7 @@ export class ScavCaseRewardGenerator
this.cacheDbItems();
// Get scavcase details from hideout/scavcase.json
const scavCaseDetails = this.databaseServer.getTables().hideout.scavcase.find(r => r._id === recipeId);
const scavCaseDetails = this.databaseServer.getTables().hideout.scavcase.find((r) => r._id === recipeId);
const rewardItemCounts = this.getScavCaseRewardCountsAndPrices(scavCaseDetails);
// Get items that fit the price criteria as set by the scavCase config
@ -231,7 +230,8 @@ export class ScavCaseRewardGenerator
for (let i = 0; i < randomCount; i++)
{
if (this.rewardShouldBeMoney() && !rewardWasMoney)
{ // Only allow one reward to be money
{
// Only allow one reward to be money
result.push(this.getRandomMoney());
if (!this.scavCaseConfig.allowMultipleMoneyRewardsPerRarity)
{
@ -239,7 +239,8 @@ export class ScavCaseRewardGenerator
}
}
else if (this.rewardShouldBeAmmo() && !rewardWasAmmo)
{ // Only allow one reward to be ammo
{
// Only allow one reward to be ammo
result.push(this.getRandomAmmo(rarity));
if (!this.scavCaseConfig.allowMultipleAmmoRewardsPerRarity)
{

View File

@ -1,10 +1,8 @@
import { inject, injectable } from "tsyringe";
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
import { ContextVariableType } from "@spt-aki/context/ContextVariableType";
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
import { IWeather, IWeatherData } from "@spt-aki/models/eft/weather/IWeatherData";
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
import { Season } from "@spt-aki/models/enums/Season";
import { WindDirection } from "@spt-aki/models/enums/WindDirection";
import { IWeatherConfig } from "@spt-aki/models/spt/config/IWeatherConfig";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
@ -181,7 +179,8 @@ export class WeatherGenerator
protected getRandomFloat(node: string): number
{
return Number.parseFloat(
this.randomUtil.getFloat(this.weatherConfig.weather[node].min, this.weatherConfig.weather[node].max)
this.randomUtil
.getFloat(this.weatherConfig.weather[node].min, this.weatherConfig.weather[node].max)
.toPrecision(3),
);
}

View File

@ -153,15 +153,15 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
): ITemplateItem
{
// The mag Slot data for the weapon
const magSlot = this.itemHelper.getItem(weaponTpl)[1]._props.Slots.find(x => x._name === "mod_magazine");
const magSlot = this.itemHelper.getItem(weaponTpl)[1]._props.Slots.find((x) => x._name === "mod_magazine");
if (!magSlot)
{
return null;
}
// All possible mags that fit into the weapon excluding blacklisted
const magazinePool = magSlot._props.filters[0].Filter.filter(x => !magazineBlacklist.includes(x)).map(x =>
this.itemHelper.getItem(x)[1],
const magazinePool = magSlot._props.filters[0].Filter.filter((x) => !magazineBlacklist.includes(x)).map(
(x) => this.itemHelper.getItem(x)[1],
);
if (!magazinePool)
{
@ -169,7 +169,7 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
}
// Non-internal magazines that fit into the weapon
const externalMagazineOnlyPool = magazinePool.filter(x => x._props.ReloadMagType !== "InternalMagazine");
const externalMagazineOnlyPool = magazinePool.filter((x) => x._props.ReloadMagType !== "InternalMagazine");
if (!externalMagazineOnlyPool || externalMagazineOnlyPool?.length === 0)
{
return null;

View File

@ -92,7 +92,8 @@ export class BotDifficultyHelper
*/
protected getDifficultySettings(type: string, difficulty: string): Difficulty
{
let difficultySetting = this.pmcConfig.difficulty.toLowerCase() === "asonline"
let difficultySetting
= this.pmcConfig.difficulty.toLowerCase() === "asonline"
? difficulty
: this.pmcConfig.difficulty.toLowerCase();

View File

@ -54,9 +54,9 @@ export class BotGeneratorHelper
public generateExtraPropertiesForItem(itemTemplate: ITemplateItem, botRole?: string): { upd?: Upd }
{
// Get raid settings, if no raid, default to day
const raidSettings = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION)?.getValue<
IGetRaidConfigurationRequestData
>();
const raidSettings = this.applicationContext
.getLatestValue(ContextVariableType.RAID_CONFIGURATION)
?.getValue<IGetRaidConfigurationRequestData>();
const raidIsNight = raidSettings?.timeVariant === "PAST";
const itemProperties: Upd = {};
@ -64,11 +64,13 @@ export class BotGeneratorHelper
if (itemTemplate._props.MaxDurability)
{
if (itemTemplate._props.weapClass)
{ // Is weapon
{
// Is weapon
itemProperties.Repairable = this.generateWeaponRepairableProperties(itemTemplate, botRole);
}
else if (itemTemplate._props.armorClass)
{ // Is armor
{
// Is armor
itemProperties.Repairable = this.generateArmorRepairableProperties(itemTemplate, botRole);
}
}
@ -287,7 +289,7 @@ export class BotGeneratorHelper
): IChooseRandomCompatibleModResult
{
// TODO: Can probably be optimized to cache itemTemplates as items are added to inventory
const equippedItemsDb = itemsEquipped.map(item => this.databaseServer.getTables().templates.items[item._tpl]);
const equippedItemsDb = itemsEquipped.map((item) => this.databaseServer.getTables().templates.items[item._tpl]);
const itemToEquipDb = this.itemHelper.getItem(tplToCheck);
const itemToEquip = itemToEquipDb[1];
@ -318,27 +320,25 @@ export class BotGeneratorHelper
}
// Check if any of the current weapon mod templates have the incoming item defined as incompatible
const blockingItem = equippedItemsDb.find(x => x._props.ConflictingItems?.includes(tplToCheck));
const blockingItem = equippedItemsDb.find((x) => x._props.ConflictingItems?.includes(tplToCheck));
if (blockingItem)
{
return {
incompatible: true,
found: false,
reason:
`Cannot add: ${tplToCheck} ${itemToEquip._name} to slot: ${modSlot}. Blocked by: ${blockingItem._id} ${blockingItem._name}`,
reason: `Cannot add: ${tplToCheck} ${itemToEquip._name} to slot: ${modSlot}. Blocked by: ${blockingItem._id} ${blockingItem._name}`,
slotBlocked: true,
};
}
// Check inverse to above, if the incoming item has any existing mods in its conflicting items array
const blockingModItem = itemsEquipped.find(item => itemToEquip._props.ConflictingItems?.includes(item._tpl));
const blockingModItem = itemsEquipped.find((item) => itemToEquip._props.ConflictingItems?.includes(item._tpl));
if (blockingModItem)
{
return {
incompatible: true,
found: false,
reason:
` Cannot add: ${tplToCheck} to slot: ${modSlot}. Would block existing item: ${blockingModItem._tpl} in slot: ${blockingModItem.slotId}`,
reason: ` Cannot add: ${tplToCheck} to slot: ${modSlot}. Would block existing item: ${blockingModItem._tpl} in slot: ${blockingModItem.slotId}`,
};
}
@ -365,7 +365,7 @@ export class BotGeneratorHelper
}
// TODO: Can probably be optimized to cache itemTemplates as items are added to inventory
const equippedItemsDb = itemsEquipped.map(i => this.databaseServer.getTables().templates.items[i._tpl]);
const equippedItemsDb = itemsEquipped.map((i) => this.databaseServer.getTables().templates.items[i._tpl]);
const itemToEquipDb = this.itemHelper.getItem(tplToCheck);
const itemToEquip = itemToEquipDb[1];
@ -395,29 +395,27 @@ export class BotGeneratorHelper
}
// Does an equipped item have a property that blocks the desired item - check for prop "BlocksX" .e.g BlocksEarpiece / BlocksFaceCover
let blockingItem = equippedItemsDb.find(x => x._props[`Blocks${equipmentSlot}`]);
let blockingItem = equippedItemsDb.find((x) => x._props[`Blocks${equipmentSlot}`]);
if (blockingItem)
{
// this.logger.warning(`1 incompatibility found between - ${itemToEquip[1]._name} and ${blockingItem._name} - ${equipmentSlot}`);
return {
incompatible: true,
found: false,
reason:
`${tplToCheck} ${itemToEquip._name} in slot: ${equipmentSlot} blocked by: ${blockingItem._id} ${blockingItem._name}`,
reason: `${tplToCheck} ${itemToEquip._name} in slot: ${equipmentSlot} blocked by: ${blockingItem._id} ${blockingItem._name}`,
slotBlocked: true,
};
}
// Check if any of the current inventory templates have the incoming item defined as incompatible
blockingItem = equippedItemsDb.find(x => x._props.ConflictingItems?.includes(tplToCheck));
blockingItem = equippedItemsDb.find((x) => x._props.ConflictingItems?.includes(tplToCheck));
if (blockingItem)
{
// this.logger.warning(`2 incompatibility found between - ${itemToEquip[1]._name} and ${blockingItem._props.Name} - ${equipmentSlot}`);
return {
incompatible: true,
found: false,
reason:
`${tplToCheck} ${itemToEquip._name} in slot: ${equipmentSlot} blocked by: ${blockingItem._id} ${blockingItem._name}`,
reason: `${tplToCheck} ${itemToEquip._name} in slot: ${equipmentSlot} blocked by: ${blockingItem._id} ${blockingItem._name}`,
slotBlocked: true,
};
}
@ -425,14 +423,13 @@ export class BotGeneratorHelper
// Does item being checked get blocked/block existing item
if (itemToEquip._props.BlocksHeadwear)
{
const existingHeadwear = itemsEquipped.find(x => x.slotId === "Headwear");
const existingHeadwear = itemsEquipped.find((x) => x.slotId === "Headwear");
if (existingHeadwear)
{
return {
incompatible: true,
found: false,
reason:
`${tplToCheck} ${itemToEquip._name} is blocked by: ${existingHeadwear._tpl} in slot: ${existingHeadwear.slotId}`,
reason: `${tplToCheck} ${itemToEquip._name} is blocked by: ${existingHeadwear._tpl} in slot: ${existingHeadwear.slotId}`,
slotBlocked: true,
};
}
@ -441,14 +438,13 @@ export class BotGeneratorHelper
// Does item being checked get blocked/block existing item
if (itemToEquip._props.BlocksFaceCover)
{
const existingFaceCover = itemsEquipped.find(item => item.slotId === "FaceCover");
const existingFaceCover = itemsEquipped.find((item) => item.slotId === "FaceCover");
if (existingFaceCover)
{
return {
incompatible: true,
found: false,
reason:
`${tplToCheck} ${itemToEquip._name} is blocked by: ${existingFaceCover._tpl} in slot: ${existingFaceCover.slotId}`,
reason: `${tplToCheck} ${itemToEquip._name} is blocked by: ${existingFaceCover._tpl} in slot: ${existingFaceCover.slotId}`,
slotBlocked: true,
};
}
@ -457,14 +453,13 @@ export class BotGeneratorHelper
// Does item being checked get blocked/block existing item
if (itemToEquip._props.BlocksEarpiece)
{
const existingEarpiece = itemsEquipped.find(item => item.slotId === "Earpiece");
const existingEarpiece = itemsEquipped.find((item) => item.slotId === "Earpiece");
if (existingEarpiece)
{
return {
incompatible: true,
found: false,
reason:
`${tplToCheck} ${itemToEquip._name} is blocked by: ${existingEarpiece._tpl} in slot: ${existingEarpiece.slotId}`,
reason: `${tplToCheck} ${itemToEquip._name} is blocked by: ${existingEarpiece._tpl} in slot: ${existingEarpiece.slotId}`,
slotBlocked: true,
};
}
@ -473,29 +468,27 @@ export class BotGeneratorHelper
// Does item being checked get blocked/block existing item
if (itemToEquip._props.BlocksArmorVest)
{
const existingArmorVest = itemsEquipped.find(item => item.slotId === "ArmorVest");
const existingArmorVest = itemsEquipped.find((item) => item.slotId === "ArmorVest");
if (existingArmorVest)
{
return {
incompatible: true,
found: false,
reason:
`${tplToCheck} ${itemToEquip._name} is blocked by: ${existingArmorVest._tpl} in slot: ${existingArmorVest.slotId}`,
reason: `${tplToCheck} ${itemToEquip._name} is blocked by: ${existingArmorVest._tpl} in slot: ${existingArmorVest.slotId}`,
slotBlocked: true,
};
}
}
// Check if the incoming item has any inventory items defined as incompatible
const blockingInventoryItem = itemsEquipped.find(x => itemToEquip._props.ConflictingItems?.includes(x._tpl));
const blockingInventoryItem = itemsEquipped.find((x) => itemToEquip._props.ConflictingItems?.includes(x._tpl));
if (blockingInventoryItem)
{
// this.logger.warning(`3 incompatibility found between - ${itemToEquip[1]._name} and ${blockingInventoryItem._tpl} - ${equipmentSlot}`)
return {
incompatible: true,
found: false,
reason:
`${tplToCheck} blocks existing item ${blockingInventoryItem._tpl} in slot ${blockingInventoryItem.slotId}`,
reason: `${tplToCheck} blocks existing item ${blockingInventoryItem._tpl} in slot ${blockingInventoryItem.slotId}`,
};
}
@ -543,7 +536,7 @@ export class BotGeneratorHelper
continue;
}
// Get container to put item into
const container = inventory.items.find(item => item.slotId === equipmentSlotId);
const container = inventory.items.find((item) => item.slotId === equipmentSlotId);
if (!container)
{
missingContainerCount++;
@ -551,9 +544,9 @@ export class BotGeneratorHelper
{
// Bot doesnt have any containers we want to add item to
this.logger.debug(
`Unable to add item: ${itemWithChildren[0]._tpl} to bot as it lacks the following containers: ${
equipmentSlots.join(",")
}`,
`Unable to add item: ${itemWithChildren[0]._tpl} to bot as it lacks the following containers: ${equipmentSlots.join(
",",
)}`,
);
return ItemAddedResult.NO_CONTAINERS;
@ -589,7 +582,8 @@ export class BotGeneratorHelper
{
// Grid is empty, skip or item size is bigger than grid
if (
slotGrid._props.cellsH === 0 || slotGrid._props.cellsV === 0
slotGrid._props.cellsH === 0
|| slotGrid._props.cellsV === 0
|| itemSize[0] * itemSize[1] > slotGrid._props.cellsV * slotGrid._props.cellsH
)
{
@ -604,12 +598,12 @@ export class BotGeneratorHelper
}
// Get all root items in found container
const existingContainerItems = inventory.items.filter(item =>
item.parentId === container._id && item.slotId === slotGrid._name,
const existingContainerItems = inventory.items.filter(
(item) => item.parentId === container._id && item.slotId === slotGrid._name,
);
// Get root items in container we can iterate over to find out what space is free
const containerItemsToCheck = existingContainerItems.filter(x => x.slotId === slotGrid._name);
const containerItemsToCheck = existingContainerItems.filter((x) => x.slotId === slotGrid._name);
for (const item of containerItemsToCheck)
{
// Look for children on items, insert into array if found
@ -635,7 +629,7 @@ export class BotGeneratorHelper
// Open slot found, add item to inventory
if (findSlotResult.success)
{
const parentItem = itemWithChildren.find(i => i._id === rootItemId);
const parentItem = itemWithChildren.find((i) => i._id === rootItemId);
// Set items parent to container id
parentItem.parentId = container._id;

View File

@ -66,7 +66,7 @@ export class BotHelper
public isBotBoss(botRole: string): boolean
{
return this.botConfig.bosses.some(x => x.toLowerCase() === botRole?.toLowerCase());
return this.botConfig.bosses.some((x) => x.toLowerCase() === botRole?.toLowerCase());
}
public isBotFollower(botRole: string): boolean
@ -182,8 +182,10 @@ export class BotHelper
public rollChanceToBePmc(role: string, botConvertMinMax: MinMax): boolean
{
return role.toLowerCase() in this.pmcConfig.convertIntoPmcChance
&& this.randomUtil.getChance100(this.randomUtil.getInt(botConvertMinMax.min, botConvertMinMax.max));
return (
role.toLowerCase() in this.pmcConfig.convertIntoPmcChance
&& this.randomUtil.getChance100(this.randomUtil.getInt(botConvertMinMax.min, botConvertMinMax.max))
);
}
public botRoleIsPmc(botRole: string): boolean
@ -207,7 +209,7 @@ export class BotHelper
return null;
}
return botEquipConfig.randomisation.find(x => botLevel >= x.levelRange.min && botLevel <= x.levelRange.max);
return botEquipConfig.randomisation.find((x) => botLevel >= x.levelRange.min && botLevel <= x.levelRange.max);
}
/**
@ -216,9 +218,7 @@ export class BotHelper
*/
public getRandomizedPmcRole(): string
{
return this.randomUtil.getChance100(this.pmcConfig.isUsec)
? this.pmcConfig.usecType
: this.pmcConfig.bearType;
return this.randomUtil.getChance100(this.pmcConfig.isUsec) ? this.pmcConfig.usecType : this.pmcConfig.bearType;
}
/**

View File

@ -45,7 +45,8 @@ export class BotWeaponGeneratorHelper
{
const firstSlotAmmoTpl = magTemplate._props.Cartridges[0]._props.filters[0].Filter[0];
const ammoMaxStackSize = this.itemHelper.getItem(firstSlotAmmoTpl)[1]?._props?.StackMaxSize ?? 1;
chamberBulletCount = ammoMaxStackSize === 1
chamberBulletCount
= ammoMaxStackSize === 1
? 1 // Rotating grenade launcher
: magTemplate._props.Slots.length; // Shotguns/revolvers. We count the number of camoras as the _max_count of the magazine is 0
}

View File

@ -35,7 +35,7 @@ export class ContainerHelper
const limitX = containerX - minVolume;
// Every x+y slot taken up in container, exit
if (container2D.every(x => x.every(y => y === 1)))
if (container2D.every((x) => x.every((y) => y === 1)))
{
return new FindSlotResult(false);
}
@ -44,7 +44,7 @@ export class ContainerHelper
for (let y = 0; y < limitY; y++)
{
// Across
if (container2D[y].every(x => x === 1))
if (container2D[y].every((x) => x === 1))
{
// Every item in row is full, skip row
continue;

View File

@ -12,8 +12,7 @@ export abstract class AbstractDialogueChatBot implements IDialogueChatBot
protected mailSendService: MailSendService,
protected chatCommands: IChatCommand[] | ICommandoCommand[],
)
{
}
{}
/**
* @deprecated As of v3.7.6. Use registerChatCommand.
@ -26,7 +25,7 @@ export abstract class AbstractDialogueChatBot implements IDialogueChatBot
public registerChatCommand(chatCommand: IChatCommand | ICommandoCommand): void
{
if (this.chatCommands.some(cc => cc.getCommandPrefix() === chatCommand.getCommandPrefix()))
if (this.chatCommands.some((cc) => cc.getCommandPrefix() === chatCommand.getCommandPrefix()))
{
throw new Error(
`The command "${chatCommand.getCommandPrefix()}" attempting to be registered already exists.`,
@ -49,7 +48,7 @@ export abstract class AbstractDialogueChatBot implements IDialogueChatBot
const splitCommand = request.text.split(" ");
const commandos = this.chatCommands.filter(c => c.getCommandPrefix() === splitCommand[0]);
const commandos = this.chatCommands.filter((c) => c.getCommandPrefix() === splitCommand[0]);
if (commandos[0]?.getCommands().has(splitCommand[1]))
{
return commandos[0].handle(splitCommand[1], this.getChatBot(), sessionId, request);

View File

@ -18,18 +18,20 @@ export class SptCommandoCommands implements IChatCommand
const coreConfigs = this.configServer.getConfig<ICoreConfig>(ConfigTypes.CORE);
// if give command is disabled or commando commands are disabled
if (
!(coreConfigs.features?.chatbotFeatures?.commandoFeatures?.giveCommandEnabled
&& coreConfigs.features?.chatbotFeatures?.commandoEnabled)
!(
coreConfigs.features?.chatbotFeatures?.commandoFeatures?.giveCommandEnabled
&& coreConfigs.features?.chatbotFeatures?.commandoEnabled
)
)
{
const giveCommand = this.sptCommands.find(c => c.getCommand().toLocaleLowerCase() === "give");
const giveCommand = this.sptCommands.find((c) => c.getCommand().toLocaleLowerCase() === "give");
this.sptCommands.splice(this.sptCommands.indexOf(giveCommand), 1);
}
}
public registerSptCommandoCommand(command: ISptCommand): void
{
if (this.sptCommands.some(c => c.getCommand() === command.getCommand()))
if (this.sptCommands.some((c) => c.getCommand() === command.getCommand()))
{
throw new Error(`The command "${command.getCommand()}" attempting to be registered already exists.`);
}
@ -38,7 +40,7 @@ export class SptCommandoCommands implements IChatCommand
public getCommandHelp(command: string): string
{
return this.sptCommands.find(c => c.getCommand() === command)?.getCommandHelp();
return this.sptCommands.find((c) => c.getCommand() === command)?.getCommandHelp();
}
public getCommandPrefix(): string
@ -48,7 +50,7 @@ export class SptCommandoCommands implements IChatCommand
public getCommands(): Set<string>
{
return new Set(this.sptCommands.map(c => c.getCommand()));
return new Set(this.sptCommands.map((c) => c.getCommand()));
}
public handle(
@ -58,10 +60,8 @@ export class SptCommandoCommands implements IChatCommand
request: ISendMessageRequest,
): string
{
return this.sptCommands.find(c => c.getCommand() === command).performAction(
commandHandler,
sessionId,
request,
);
return this.sptCommands
.find((c) => c.getCommand() === command)
.performAction(commandHandler, sessionId, request);
}
}

View File

@ -31,7 +31,12 @@ export class GiveSptCommand implements ISptCommand
private static commandRegex = /^spt give (((([a-z]{2,5}) )?"(.+)"|\w+) )?([0-9]+)$/;
private static acceptableConfidence = 0.9;
// exception for flares
private static excludedPresetItems = new Set<string>(["62178c4d4ecf221597654e3d", "6217726288ed9f0845317459", "624c0b3340357b5f566e8766"]);
private static excludedPresetItems = new Set<string>([
"62178c4d4ecf221597654e3d",
"6217726288ed9f0845317459",
"624c0b3340357b5f566e8766",
]);
protected savedCommand: Map<string, SavedCommand> = new Map<string, SavedCommand>();
public constructor(
@ -45,8 +50,7 @@ export class GiveSptCommand implements ISptCommand
@inject("ItemFilterService") protected itemFilterService: ItemFilterService,
@inject("RecursiveCloner") protected cloner: ICloner,
)
{
}
{}
public getCommand(): string
{
@ -55,7 +59,7 @@ export class GiveSptCommand implements ISptCommand
public getCommandHelp(): string
{
return "spt give\n========\nSends items to the player through the message system.\n\n\tspt give [template ID] [quantity]\n\t\tEx: spt give 544fb25a4bdc2dfb738b4567 2\n\n\tspt give [\"item name\"] [quantity]\n\t\tEx: spt give \"pack of sugar\" 10\n\n\tspt give [locale] [\"item name\"] [quantity]\n\t\tEx: spt give fr \"figurine de chat\" 3";
return 'spt give\n========\nSends items to the player through the message system.\n\n\tspt give [template ID] [quantity]\n\t\tEx: spt give 544fb25a4bdc2dfb738b4567 2\n\n\tspt give ["item name"] [quantity]\n\t\tEx: spt give "pack of sugar" 10\n\n\tspt give [locale] ["item name"] [quantity]\n\t\tEx: spt give fr "figurine de chat" 3';
}
public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string
@ -65,7 +69,7 @@ export class GiveSptCommand implements ISptCommand
this.mailSendService.sendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid use of give command. Use \"help\" for more information.",
'Invalid use of give command. Use "help" for more information.',
);
return request.dialogId;
}
@ -85,7 +89,7 @@ export class GiveSptCommand implements ISptCommand
this.mailSendService.sendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid use of give command. Use \"help\" for more information.",
'Invalid use of give command. Use "help" for more information.',
);
return request.dialogId;
}
@ -95,7 +99,7 @@ export class GiveSptCommand implements ISptCommand
this.mailSendService.sendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid selection. Outside of bounds! Use \"help\" for more information.",
'Invalid selection. Outside of bounds! Use "help" for more information.',
);
return request.dialogId;
}
@ -120,7 +124,7 @@ export class GiveSptCommand implements ISptCommand
this.mailSendService.sendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid quantity! Must be 1 or higher. Use \"help\" for more information.",
'Invalid quantity! Must be 1 or higher. Use "help" for more information.',
);
return request.dialogId;
}
@ -142,17 +146,19 @@ export class GiveSptCommand implements ISptCommand
locale = "en";
}
const localizedGlobal = this.databaseServer.getTables().locales.global[locale]
const localizedGlobal
= this.databaseServer.getTables().locales.global[locale]
?? this.databaseServer.getTables().locales.global.en;
const closestItemsMatchedByName = this.itemHelper.getItems()
.filter(i => this.isItemAllowed(i))
.map(i => localizedGlobal[`${i?._id} Name`]?.toLowerCase() ?? i._props.Name)
.filter(i => i !== undefined && i !== "")
.map(i => ({ match: stringSimilarity(
item.toLocaleLowerCase(),
i.toLocaleLowerCase(),
), itemName: i }))
const closestItemsMatchedByName = this.itemHelper
.getItems()
.filter((i) => this.isItemAllowed(i))
.map((i) => localizedGlobal[`${i?._id} Name`]?.toLowerCase() ?? i._props.Name)
.filter((i) => i !== undefined && i !== "")
.map((i) => ({
match: stringSimilarity(item.toLocaleLowerCase(), i.toLocaleLowerCase()),
itemName: i,
}))
.sort((a1, a2) => a2.match - a1.match);
if (closestItemsMatchedByName[0].match >= GiveSptCommand.acceptableConfidence)
@ -164,11 +170,16 @@ export class GiveSptCommand implements ISptCommand
let i = 1;
const slicedItems = closestItemsMatchedByName.slice(0, 10);
// max 10 item names and map them
const itemList = slicedItems.map(match => `${i++}. ${match.itemName} (conf: ${(match.match * 100).toFixed(2)})`)
const itemList = slicedItems
.map((match) => `${i++}. ${match.itemName} (conf: ${(match.match * 100).toFixed(2)})`)
.join("\n");
this.savedCommand.set(
sessionId,
new SavedCommand(quantity, slicedItems.map(i => i.itemName), locale),
new SavedCommand(
quantity,
slicedItems.map((i) => i.itemName),
locale,
),
);
this.mailSendService.sendUserMessageToPlayer(
sessionId,
@ -180,14 +191,15 @@ export class GiveSptCommand implements ISptCommand
}
}
const localizedGlobal = this.databaseServer.getTables().locales.global[locale]
?? this.databaseServer.getTables().locales.global.en;
const localizedGlobal
= this.databaseServer.getTables().locales.global[locale] ?? this.databaseServer.getTables().locales.global.en;
// If item is an item name, we need to search using that item name and the locale which one we want otherwise
// item is just the tplId.
const tplId = isItemName
? this.itemHelper.getItems()
.filter(i => this.isItemAllowed(i))
.find(i => (localizedGlobal[`${i?._id} Name`]?.toLowerCase() ?? i._props.Name) === item)._id
? this.itemHelper
.getItems()
.filter((i) => this.isItemAllowed(i))
.find((i) => (localizedGlobal[`${i?._id} Name`]?.toLowerCase() ?? i._props.Name) === item)._id
: item;
const checkedItem = this.itemHelper.getItem(tplId);
@ -274,13 +286,15 @@ export class GiveSptCommand implements ISptCommand
*/
protected isItemAllowed(templateItem: ITemplateItem): boolean
{
return templateItem._type !== "Node"
return (
templateItem._type !== "Node"
&& !this.itemHelper.isQuestItem(templateItem._id)
&& !this.itemFilterService.isItemBlacklisted(templateItem._id)
&& (templateItem._props?.Prefab?.path ?? "") !== ""
&& !this.itemHelper.isOfBaseclass(templateItem._id, BaseClasses.HIDEOUT_AREA_CONTAINER)
&& !this.itemHelper.isOfBaseclass(templateItem._id, BaseClasses.LOOT_CONTAINER)
&& !this.itemHelper.isOfBaseclass(templateItem._id, BaseClasses.RANDOM_LOOT_CONTAINER)
&& !this.itemHelper.isOfBaseclass(templateItem._id, BaseClasses.MOB_CONTAINER);
&& !this.itemHelper.isOfBaseclass(templateItem._id, BaseClasses.MOB_CONTAINER)
);
}
}

View File

@ -1,6 +1,9 @@
export class SavedCommand
{
public constructor(public quantity: number, public potentialItemNames: string[], public locale: string)
{
}
public constructor(
public quantity: number,
public potentialItemNames: string[],
public locale: string,
)
{}
}

View File

@ -37,8 +37,7 @@ export class ProfileSptCommand implements ISptCommand
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
)
{
}
{}
public getCommand(): string
{
@ -57,7 +56,7 @@ export class ProfileSptCommand implements ISptCommand
this.mailSendService.sendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid use of trader command. Use \"help\" for more information.",
'Invalid use of trader command. Use "help" for more information.',
);
return request.dialogId;
}
@ -77,7 +76,7 @@ export class ProfileSptCommand implements ISptCommand
this.mailSendService.sendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid use of profile command, the level was outside bounds: 1 to 70. Use \"help\" for more information.",
'Invalid use of profile command, the level was outside bounds: 1 to 70. Use "help" for more information.',
);
return request.dialogId;
}
@ -85,8 +84,8 @@ export class ProfileSptCommand implements ISptCommand
break;
case "skill":
{
const enumSkill = Object.values(SkillTypes).find(t =>
t.toLocaleLowerCase() === skill.toLocaleLowerCase(),
const enumSkill = Object.values(SkillTypes).find(
(t) => t.toLocaleLowerCase() === skill.toLocaleLowerCase(),
);
if (enumSkill === undefined)
@ -94,7 +93,7 @@ export class ProfileSptCommand implements ISptCommand
this.mailSendService.sendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid use of profile command, the skill was not found. Use \"help\" for more information.",
'Invalid use of profile command, the skill was not found. Use "help" for more information.',
);
return request.dialogId;
}
@ -104,7 +103,7 @@ export class ProfileSptCommand implements ISptCommand
this.mailSendService.sendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid use of profile command, the skill level was outside bounds: 1 to 51. Use \"help\" for more information.",
'Invalid use of profile command, the skill level was outside bounds: 1 to 51. Use "help" for more information.',
);
return request.dialogId;
}
@ -123,13 +122,15 @@ export class ProfileSptCommand implements ISptCommand
this.mailSendService.sendSystemMessageToPlayer(
sessionId,
"A single ruble is being attached, required by BSG logic.",
[{
[
{
_id: this.hashUtil.generate(),
_tpl: "5449016a4bdc2d6f028b456f",
upd: { StackObjectsCount: 1 },
parentId: this.hashUtil.generate(),
slotId: "main",
}],
},
],
undefined,
[event],
);

View File

@ -33,8 +33,7 @@ export class TraderSptCommand implements ISptCommand
@inject("LocaleService") protected localeService: LocaleService,
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
)
{
}
{}
public getCommand(): string
{
@ -53,7 +52,7 @@ export class TraderSptCommand implements ISptCommand
this.mailSendService.sendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid use of trader command. Use \"help\" for more information.",
'Invalid use of trader command. Use "help" for more information.',
);
return request.dialogId;
}
@ -64,15 +63,15 @@ export class TraderSptCommand implements ISptCommand
const command: string = result.groups.command;
const quantity: number = +result.groups.quantity;
const dbTrader = Object.values(this.databaseServer.getTables().traders).find(t =>
t.base.nickname.toLocaleLowerCase() === trader.toLocaleLowerCase(),
const dbTrader = Object.values(this.databaseServer.getTables().traders).find(
(t) => t.base.nickname.toLocaleLowerCase() === trader.toLocaleLowerCase(),
);
if (dbTrader === undefined)
{
this.mailSendService.sendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid use of trader command, the trader was not found. Use \"help\" for more information.",
'Invalid use of trader command, the trader was not found. Use "help" for more information.',
);
return request.dialogId;
}
@ -97,13 +96,15 @@ export class TraderSptCommand implements ISptCommand
this.mailSendService.sendSystemMessageToPlayer(
sessionId,
"A single ruble is being attached, required by BSG logic.",
[{
[
{
_id: this.hashUtil.generate(),
_tpl: "5449016a4bdc2d6f028b456f",
upd: { StackObjectsCount: 1 },
parentId: this.hashUtil.generate(),
slotId: "main",
}],
},
],
undefined,
[event],
);

View File

@ -66,7 +66,7 @@ export class DialogueHelper
const dialogueData = this.saveServer.getProfile(sessionID).dialogues;
for (const dialogueId in dialogueData)
{
const message = dialogueData[dialogueId].messages.find(x => x._id === messageID);
const message = dialogueData[dialogueId].messages.find((x) => x._id === messageID);
if (!message)
{
continue;
@ -87,7 +87,7 @@ export class DialogueHelper
message.items.data = [];
}
const rewardItemCount = message.items.data?.filter(item => item._id !== itemId);
const rewardItemCount = message.items.data?.filter((item) => item._id !== itemId);
if (rewardItemCount.length === 0)
{
message.rewardCollected = true;

View File

@ -172,7 +172,7 @@ export class DurabilityLimitsHelper
const delta = this.randomUtil.getInt(minDelta, maxDelta);
const result = Number((maxDurability - delta).toFixed(2));
const durabilityValueMinLimit = Math.round(
this.getMinWeaponLimitPercentFromConfig(botRole) / 100 * maxDurability,
(this.getMinWeaponLimitPercentFromConfig(botRole) / 100) * maxDurability,
);
// Dont let weapon dura go below the percent defined in config
@ -186,7 +186,7 @@ export class DurabilityLimitsHelper
const delta = this.randomUtil.getInt(minDelta, maxDelta);
const result = Number((maxDurability - delta).toFixed(2));
const durabilityValueMinLimit = Math.round(
this.getMinArmorLimitPercentFromConfig(botRole) / 100 * maxDurability,
(this.getMinArmorLimitPercentFromConfig(botRole) / 100) * maxDurability,
);
// Dont let armor dura go below the percent defined in config

View File

@ -56,9 +56,9 @@ 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({
@ -66,9 +66,9 @@ export class HandbookHelper
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,
);
itemToUpdate = this.databaseServer
.getTables()
.templates.handbook.Items.find((item) => item.Id === itemTpl);
}
itemToUpdate.Price = this.itemConfig.handbookPriceOverride[itemTpl];
@ -118,7 +118,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;
@ -207,6 +207,6 @@ export class HandbookHelper
public getCategoryById(handbookId: string): Category
{
return this.databaseServer.getTables().templates.handbook.Categories.find(x => x.Id === handbookId);
return this.databaseServer.getTables().templates.handbook.Categories.find((x) => x.Id === handbookId);
}
}

View File

@ -36,7 +36,8 @@ export class HealthHelper
const profile = this.saveServer.getProfile(sessionID);
if (!profile.vitality)
{ // Occurs on newly created profiles
{
// Occurs on newly created profiles
profile.vitality = { health: null, effects: null };
}
profile.vitality.health = {
@ -99,13 +100,14 @@ export class HealthHelper
profileEffects[bodyPart] = postRaidBodyParts[bodyPart].Effects;
}
if (request.IsAlive === true)
{ // is player alive, not is limb alive
{
// is player alive, not is limb alive
profileHealth[bodyPart] = postRaidBodyParts[bodyPart].Current;
}
else
{
profileHealth[bodyPart] = pmcData.Health.BodyParts[bodyPart].Health.Maximum
* this.healthConfig.healthMultipliers.death;
profileHealth[bodyPart]
= pmcData.Health.BodyParts[bodyPart].Health.Maximum * this.healthConfig.healthMultipliers.death;
}
}

View File

@ -72,9 +72,9 @@ export class HideoutHelper
sessionID: string,
): IItemEventRouterResponse
{
const recipe = this.databaseServer.getTables().hideout.production.find(production =>
production._id === body.recipeId,
);
const recipe = this.databaseServer
.getTables()
.hideout.production.find((production) => production._id === body.recipeId);
if (!recipe)
{
this.logger.error(this.localisationService.getText("hideout-missing_recipe_in_db", body.recipeId));
@ -106,7 +106,7 @@ export class HideoutHelper
for (const tool of bodyAsSingle.tools)
{
const toolItem = this.cloner.clone(pmcData.Inventory.items.find(x => x._id === tool.id));
const toolItem = this.cloner.clone(pmcData.Inventory.items.find((x) => x._id === tool.id));
// Make sure we only return as many as we took
this.itemHelper.addUpdObjectToItem(toolItem);
@ -168,7 +168,7 @@ export class HideoutHelper
case BonusType.STASH_SIZE:
{
// Find stash item and adjust tpl to new tpl from bonus
const stashItem = pmcData.Inventory.items.find(x => x._id === pmcData.Inventory.stash);
const stashItem = pmcData.Inventory.items.find((x) => x._id === pmcData.Inventory.stash);
if (!stashItem)
{
this.logger.warning(
@ -216,18 +216,20 @@ export class HideoutHelper
* @param pmcData Player profile
* @returns Properties
*/
protected getHideoutProperties(
pmcData: IPmcData,
): { btcFarmCGs: number, isGeneratorOn: boolean, waterCollectorHasFilter: boolean }
protected getHideoutProperties(pmcData: IPmcData): {
btcFarmCGs: number
isGeneratorOn: boolean
waterCollectorHasFilter: boolean
}
{
const bitcoinFarm = pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.BITCOIN_FARM);
const bitcoinCount = bitcoinFarm?.slots.filter(slot => slot.item).length ?? 0; // Get slots with an item property
const bitcoinFarm = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.BITCOIN_FARM);
const bitcoinCount = bitcoinFarm?.slots.filter((slot) => slot.item).length ?? 0; // Get slots with an item property
const hideoutProperties = {
btcFarmCGs: bitcoinCount,
isGeneratorOn: pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.GENERATOR)?.active ?? false,
isGeneratorOn: pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.GENERATOR)?.active ?? false,
waterCollectorHasFilter: this.doesWaterCollectorHaveFilter(
pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.WATER_COLLECTOR),
pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.WATER_COLLECTOR),
),
};
@ -240,7 +242,7 @@ export class HideoutHelper
if (waterCollector.level === 3)
{
// Has filter in at least one slot
return waterCollector.slots.some(slot => slot.item);
return waterCollector.slots.some((slot) => slot.item);
}
// No Filter
@ -308,7 +310,7 @@ export class HideoutHelper
}
// Other recipes not covered by above
const recipe = recipes.find(r => r._id === prodId);
const recipe = recipes.find((r) => r._id === prodId);
if (!recipe)
{
this.logger.error(this.localisationService.getText("hideout-missing_recipe_for_area", prodId));
@ -364,9 +366,8 @@ export class HideoutHelper
// Increment progress by time passed
const production = pmcData.Hideout.Production[prodId];
production.Progress += production.needFuelForAllProductionTime && !hideoutProperties.isGeneratorOn
? 0
: timeElapsed; // Some items NEED power to craft (e.g. DSP)
production.Progress
+= production.needFuelForAllProductionTime && !hideoutProperties.isGeneratorOn ? 0 : timeElapsed; // Some items NEED power to craft (e.g. DSP)
// Limit progress to total production time if progress is over (dont run for continious crafts))
if (!recipe.continuous)
@ -395,7 +396,9 @@ export class HideoutHelper
*/
protected updateScavCaseProductionTimer(pmcData: IPmcData, productionId: string): void
{
const timeElapsed = this.timeUtil.getTimestamp() - pmcData.Hideout.Production[productionId].StartTimestamp
const timeElapsed
= this.timeUtil.getTimestamp()
- pmcData.Hideout.Production[productionId].StartTimestamp
- pmcData.Hideout.Production[productionId].Progress;
pmcData.Hideout.Production[productionId].Progress += timeElapsed;
}
@ -446,10 +449,11 @@ export class HideoutHelper
{
// 1 resource last 14 min 27 sec, 1/14.45/60 = 0.00115
// 10-10-2021 From wiki, 1 resource last 12 minutes 38 seconds, 1/12.63333/60 = 0.00131
let fuelUsedSinceLastTick = this.databaseServer.getTables().hideout.settings.generatorFuelFlowRate
let fuelUsedSinceLastTick
= this.databaseServer.getTables().hideout.settings.generatorFuelFlowRate
* this.getTimeElapsedSinceLastServerTick(pmcData, isGeneratorOn);
const profileFuelConsumptionBonus = pmcData.Bonuses.find(bonus => bonus.type === BonusType.FUEL_CONSUMPTION);
const profileFuelConsumptionBonus = pmcData.Bonuses.find((bonus) => bonus.type === BonusType.FUEL_CONSUMPTION);
// 0 to 1
const fuelConsumptionBonusMultipler
@ -602,9 +606,9 @@ export class HideoutHelper
{
const globalSkillsDb = this.databaseServer.getTables().globals.config.SkillsSettings;
const recipe = this.databaseServer.getTables().hideout.production.find(production =>
production._id === recipeId,
);
const recipe = this.databaseServer
.getTables()
.hideout.production.find((production) => production._id === recipeId);
if (!recipe)
{
this.logger.error(this.localisationService.getText("hideout-missing_recipe_in_db", recipeId));
@ -754,7 +758,8 @@ export class HideoutHelper
baseFilterDrainRate: number,
): number
{
const drainTimeSeconds = secondsSinceServerTick > totalProductionTime
const drainTimeSeconds
= secondsSinceServerTick > totalProductionTime
? totalProductionTime - productionProgress // More time passed than prod time, get total minus the current progress
: secondsSinceServerTick;
@ -786,7 +791,8 @@ export class HideoutHelper
);
// Never let bonus become 0
const reductionBonus = hideoutManagementConsumptionBonus + craftSkillTimeReductionMultipler === 0
const reductionBonus
= hideoutManagementConsumptionBonus + craftSkillTimeReductionMultipler === 0
? 1
: 1 - (hideoutManagementConsumptionBonus + craftSkillTimeReductionMultipler);
@ -800,7 +806,7 @@ export class HideoutHelper
*/
protected getTotalProductionTimeSeconds(prodId: string): number
{
const recipe = this.databaseServer.getTables().hideout.production.find(prod => prod._id === prodId);
const recipe = this.databaseServer.getTables().hideout.production.find((prod) => prod._id === prodId);
return recipe.productionTime || 0;
}
@ -833,7 +839,8 @@ export class HideoutHelper
Lasts for 17 hours 38 minutes and 49 seconds (23 hours 31 minutes and 45 seconds with elite hideout management skill),
300/17.64694/60/60 = 0.004722
*/
let filterDrainRate = this.databaseServer.getTables().hideout.settings.airFilterUnitFlowRate
let filterDrainRate
= this.databaseServer.getTables().hideout.settings.airFilterUnitFlowRate
* this.getTimeElapsedSinceLastServerTick(pmcData, isGeneratorOn);
// Hideout management resource consumption bonus:
@ -888,9 +895,9 @@ export class HideoutHelper
protected updateBitcoinFarm(pmcData: IPmcData, btcFarmCGs: number, isGeneratorOn: boolean): Production
{
const btcProd = pmcData.Hideout.Production[HideoutHelper.bitcoinFarm];
const bitcoinProdData = this.databaseServer.getTables().hideout.production.find(production =>
production._id === HideoutHelper.bitcoinProductionId,
);
const bitcoinProdData = this.databaseServer
.getTables()
.hideout.production.find((production) => production._id === HideoutHelper.bitcoinProductionId);
const coinSlotCount = this.getBTCSlots(pmcData);
// Full on bitcoins, halt progress
@ -1024,9 +1031,9 @@ export class HideoutHelper
*/
protected getBTCSlots(pmcData: IPmcData): number
{
const bitcoinProductions = this.databaseServer.getTables().hideout.production.find(production =>
production._id === HideoutHelper.bitcoinFarm,
);
const bitcoinProductions = this.databaseServer
.getTables()
.hideout.production.find((production) => production._id === HideoutHelper.bitcoinFarm);
const productionSlots = bitcoinProductions?.productionLimitCount || 3; // Default to 3 if none found
const hasManagementSkillSlots = this.profileHelper.hasEliteSkillLevel(SkillTypes.HIDEOUT_MANAGEMENT, pmcData);
const managementSlotsCount = this.getEliteSkillAdditionalBitcoinSlotCount() || 2;
@ -1063,9 +1070,12 @@ export class HideoutHelper
let roundedLevel = Math.floor(hideoutManagementSkill.Progress / 100);
roundedLevel = roundedLevel === 51 ? roundedLevel - 1 : roundedLevel;
return roundedLevel
return (
(roundedLevel
* this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement
.ConsumptionReductionPerLevel / 100;
.ConsumptionReductionPerLevel)
/ 100
);
}
/**
@ -1089,7 +1099,7 @@ export class HideoutHelper
let roundedLevel = Math.floor(profileSkill.Progress / 100);
roundedLevel = roundedLevel === 51 ? roundedLevel - 1 : roundedLevel;
return roundedLevel * valuePerLevel / 100;
return (roundedLevel * valuePerLevel) / 100;
}
/**
@ -1146,11 +1156,13 @@ export class HideoutHelper
const itemsToAdd: Item[][] = [];
for (let index = 0; index < craftedCoinCount; index++)
{
itemsToAdd.push([{
itemsToAdd.push([
{
_id: this.hashUtil.generate(),
_tpl: HideoutHelper.bitcoinTpl,
upd: { StackObjectsCount: 1 },
}]);
},
]);
}
// Create request for what we want to add to stash
@ -1187,9 +1199,9 @@ export class HideoutHelper
*/
public unlockHideoutWallInProfile(pmcProfile: IPmcData): void
{
const waterCollector = pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.WATER_COLLECTOR);
const medStation = pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.MEDSTATION);
const wall = pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.EMERGENCY_WALL);
const waterCollector = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WATER_COLLECTOR);
const medStation = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.MEDSTATION);
const wall = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.EMERGENCY_WALL);
// No collector or med station, skip
if (!(waterCollector && medStation))
@ -1239,29 +1251,29 @@ export class HideoutHelper
*/
public applyPlaceOfFameDogtagBonus(pmcData: IPmcData): void
{
const fameAreaProfile = pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.PLACE_OF_FAME);
const fameAreaProfile = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.PLACE_OF_FAME);
// Get hideout area 16 bonus array
const fameAreaDb = this.databaseServer.getTables().hideout.areas.find(area =>
area.type === HideoutAreas.PLACE_OF_FAME,
);
const fameAreaDb = this.databaseServer
.getTables()
.hideout.areas.find((area) => area.type === HideoutAreas.PLACE_OF_FAME);
// Get SkillGroupLevelingBoost object
const combatBoostBonusDb = fameAreaDb.stages[fameAreaProfile.level].bonuses.find(bonus =>
bonus.type === "SkillGroupLevelingBoost",
const combatBoostBonusDb = fameAreaDb.stages[fameAreaProfile.level].bonuses.find(
(bonus) => bonus.type === "SkillGroupLevelingBoost",
);
// Get SkillGroupLevelingBoost object in profile
const combatBonusProfile = pmcData.Bonuses.find(bonus => bonus.id === combatBoostBonusDb.id);
const combatBonusProfile = pmcData.Bonuses.find((bonus) => bonus.id === combatBoostBonusDb.id);
// Get all slotted dogtag items
const activeDogtags = pmcData.Inventory.items.filter(item => item?.slotId?.startsWith("dogtag"));
const activeDogtags = pmcData.Inventory.items.filter((item) => item?.slotId?.startsWith("dogtag"));
// Calculate bonus percent (apply hideoutManagement bonus)
const hideoutManagementSkill = this.profileHelper.getSkillFromProfile(pmcData, SkillTypes.HIDEOUT_MANAGEMENT);
const hideoutManagementSkillBonusPercent = 1 + hideoutManagementSkill.Progress / 10000; // 5100 becomes 0.51, add 1 to it, 1.51
const bonus = this.getDogtagCombatSkillBonusPercent(pmcData, activeDogtags)
* hideoutManagementSkillBonusPercent;
const bonus
= this.getDogtagCombatSkillBonusPercent(pmcData, activeDogtags) * hideoutManagementSkillBonusPercent;
// Update bonus value to above calcualted value
combatBonusProfile.value = Number.parseFloat(bonus.toFixed(2));

View File

@ -4,7 +4,7 @@ import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
import { PaymentHelper } from "@spt-aki/helpers/PaymentHelper";
import { QuestHelper } from "@spt-aki/helpers/QuestHelper";
import { IPmcData, IPostRaidPmcData } from "@spt-aki/models/eft/common/IPmcData";
import { IQuestStatus, TraderInfo, Victim } from "@spt-aki/models/eft/common/tables/IBotBase";
import { IQuestStatus, TraderInfo } from "@spt-aki/models/eft/common/tables/IBotBase";
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
import { ISaveProgressRequestData } from "@spt-aki/models/eft/inRaid/ISaveProgressRequestData";
import { IFailQuestRequestData } from "@spt-aki/models/eft/quests/IFailQuestRequestData";
@ -67,7 +67,7 @@ export class InRaidHelper
*/
public addUpdToMoneyFromRaid(items: Item[]): void
{
for (const moneyItem of items.filter(item => this.paymentHelper.isMoneyTpl(item._tpl)))
for (const moneyItem of items.filter((item) => this.paymentHelper.isMoneyTpl(item._tpl)))
{
this.itemHelper.addUpdObjectToItem(moneyItem);
@ -128,7 +128,10 @@ export class InRaidHelper
}
/** Check counters are correct in profile */
protected validateTaskConditionCounters(saveProgressRequest: ISaveProgressRequestData, profileData: IPmcData): void
protected validateTaskConditionCounters(
saveProgressRequest: ISaveProgressRequestData,
profileData: IPmcData,
): void
{
for (const backendCounterKey in saveProgressRequest.profile.TaskConditionCounters)
{
@ -203,12 +206,12 @@ export class InRaidHelper
): void
{
// Only copy active quests into scav profile // Progress will later to copied over to PMC profile
const existingActiveQuestIds = scavData.Quests?.filter(
x => x.status !== QuestStatus.AvailableForStart,
).map(x => x.qid);
const existingActiveQuestIds = scavData.Quests?.filter((x) => x.status !== QuestStatus.AvailableForStart).map(
(x) => x.qid,
);
if (existingActiveQuestIds)
{
scavData.Quests = saveProgressRequest.profile.Quests.filter(x => existingActiveQuestIds.includes(x.qid));
scavData.Quests = saveProgressRequest.profile.Quests.filter((x) => existingActiveQuestIds.includes(x.qid));
}
this.profileFixerService.checkForAndFixScavProfileIssues(scavData);
@ -240,10 +243,10 @@ export class InRaidHelper
for (const postRaidQuest of postRaidProfile.Quests)
{
// postRaidQuest.status has a weird value, need to do some nasty casting to compare it
const postRaidQuestStatus = <string><unknown>postRaidQuest.status;
const postRaidQuestStatus = <string>(<unknown>postRaidQuest.status);
// Find matching pre-raid quest, skip if we can't
const preRaidQuest = preRaidQuests?.find(preRaidQuest => preRaidQuest.qid === postRaidQuest.qid);
const preRaidQuest = preRaidQuests?.find((preRaidQuest) => preRaidQuest.qid === postRaidQuest.qid);
if (!preRaidQuest)
{
continue;
@ -269,7 +272,8 @@ export class InRaidHelper
// Quest with time-gate has unlocked
if (
postRaidQuestStatus === "AvailableAfter" && postRaidQuest.availableAfter <= this.timeUtil.getTimestamp()
postRaidQuestStatus === "AvailableAfter"
&& postRaidQuest.availableAfter <= this.timeUtil.getTimestamp()
)
{
// Flag as ready to start
@ -298,8 +302,8 @@ export class InRaidHelper
// Does failed quest have requirement to collect items from raid
const questDbData = this.questHelper.getQuestFromDb(postRaidQuest.qid, pmcData);
// AvailableForFinish
const matchingAffFindConditions = questDbData.conditions.AvailableForFinish.filter(condition =>
condition.conditionType === "FindItem",
const matchingAffFindConditions = questDbData.conditions.AvailableForFinish.filter(
(condition) => condition.conditionType === "FindItem",
);
const itemsToCollect: string[] = [];
if (matchingAffFindConditions)
@ -314,7 +318,7 @@ export class InRaidHelper
// Remove quest items from profile as quest has failed and may still be alive
// Required as restarting the quest from main menu does not remove value from CarriedQuestItems array
postRaidProfile.Stats.Eft.CarriedQuestItems = postRaidProfile.Stats.Eft.CarriedQuestItems.filter(
carriedQuestItem => !itemsToCollect.includes(carriedQuestItem),
(carriedQuestItem) => !itemsToCollect.includes(carriedQuestItem),
);
// Remove quest item from profile now quest is failed
@ -322,8 +326,8 @@ export class InRaidHelper
for (const itemTpl of itemsToCollect)
{
// Look for sessioncounter and remove it
const counterIndex = postRaidProfile.Stats.Eft.SessionCounters.Items.findIndex(x =>
x.Key.includes(itemTpl) && x.Key.includes("LootItem"),
const counterIndex = postRaidProfile.Stats.Eft.SessionCounters.Items.findIndex(
(x) => x.Key.includes(itemTpl) && x.Key.includes("LootItem"),
);
if (counterIndex > -1)
{
@ -331,7 +335,7 @@ export class InRaidHelper
}
// Look for quest item and remove it
const inventoryItemIndex = postRaidProfile.Inventory.items.findIndex(x => x._tpl === itemTpl);
const inventoryItemIndex = postRaidProfile.Inventory.items.findIndex((x) => x._tpl === itemTpl);
if (inventoryItemIndex > -1)
{
postRaidProfile.Inventory.items.splice(inventoryItemIndex, 1);
@ -454,10 +458,15 @@ export class InRaidHelper
const itemsToRemovePropertyFrom = postRaidProfile.Inventory.items.filter((x) =>
{
// Has upd object + upd.SpawnedInSession property + not a quest item
return "upd" in x && "SpawnedInSession" in x.upd
return (
"upd" in x
&& "SpawnedInSession" in x.upd
&& !dbItems[x._tpl]._props.QuestItem
&& !(this.inRaidConfig.keepFiRSecureContainerOnDeath
&& this.itemHelper.itemIsInsideContainer(x, "SecuredContainer", postRaidProfile.Inventory.items));
&& !(
this.inRaidConfig.keepFiRSecureContainerOnDeath
&& this.itemHelper.itemIsInsideContainer(x, "SecuredContainer", postRaidProfile.Inventory.items)
)
);
});
for (const item of itemsToRemovePropertyFrom)
@ -502,7 +511,7 @@ export class InRaidHelper
public deleteInventory(pmcData: IPmcData, sessionId: string): void
{
// Get inventory item ids to remove from players profile
const itemIdsToDeleteFromProfile = this.getInventoryItemsLostOnDeath(pmcData).map(item => item._id);
const itemIdsToDeleteFromProfile = this.getInventoryItemsLostOnDeath(pmcData).map((item) => item._id);
for (const itemIdToDelete of itemIdsToDeleteFromProfile)
{
// Items inside containers are handled as part of function
@ -555,13 +564,13 @@ export class InRaidHelper
*/
protected getBaseItemsInRigPocketAndBackpack(pmcData: IPmcData): Item[]
{
const rig = pmcData.Inventory.items.find(x => x.slotId === "TacticalVest");
const pockets = pmcData.Inventory.items.find(x => x.slotId === "Pockets");
const backpack = pmcData.Inventory.items.find(x => x.slotId === "Backpack");
const rig = pmcData.Inventory.items.find((x) => x.slotId === "TacticalVest");
const pockets = pmcData.Inventory.items.find((x) => x.slotId === "Pockets");
const backpack = pmcData.Inventory.items.find((x) => x.slotId === "Backpack");
const baseItemsInRig = pmcData.Inventory.items.filter(x => x.parentId === rig?._id);
const baseItemsInPockets = pmcData.Inventory.items.filter(x => x.parentId === pockets?._id);
const baseItemsInBackpack = pmcData.Inventory.items.filter(x => x.parentId === backpack?._id);
const baseItemsInRig = pmcData.Inventory.items.filter((x) => x.parentId === rig?._id);
const baseItemsInPockets = pmcData.Inventory.items.filter((x) => x.parentId === pockets?._id);
const baseItemsInBackpack = pmcData.Inventory.items.filter((x) => x.parentId === backpack?._id);
return [...baseItemsInRig, ...baseItemsInPockets, ...baseItemsInBackpack];
}

View File

@ -23,7 +23,6 @@ import { BackendErrorCodes } from "@spt-aki/models/enums/BackendErrorCodes";
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
import { BonusType } from "@spt-aki/models/enums/BonusType";
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
import { Traders } from "@spt-aki/models/enums/Traders";
import { IInventoryConfig, RewardDetails } from "@spt-aki/models/spt/config/IInventoryConfig";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
@ -167,9 +166,8 @@ export class InventoryHelper
catch (err)
{
// Callback failed
const message = typeof err?.message === "string"
? err.message
: this.localisationService.getText("http-unknown_error");
const message
= typeof err?.message === "string" ? err.message : this.localisationService.getText("http-unknown_error");
this.httpResponse.appendErrorToOutput(output, message);
@ -520,11 +518,13 @@ export class InventoryHelper
if (requestItem.count > itemDetails._props.StackMaxSize)
{
let remainingCountOfItemToAdd = requestItem.count;
const calc = requestItem.count
const calc
= requestItem.count
- Math.floor(requestItem.count / itemDetails._props.StackMaxSize)
* itemDetails._props.StackMaxSize;
maxStackCount = calc > 0
maxStackCount
= calc > 0
? maxStackCount + Math.floor(remainingCountOfItemToAdd / itemDetails._props.StackMaxSize)
: Math.floor(remainingCountOfItemToAdd / itemDetails._props.StackMaxSize);
@ -597,7 +597,7 @@ export class InventoryHelper
{
// We expect that each inventory item and each insured item has unique "_id", respective "itemId".
// Therefore we want to use a NON-Greedy function and escape the iteration as soon as we find requested item.
const inventoryIndex = inventoryItems.findIndex(item => item._id === childId);
const inventoryIndex = inventoryItems.findIndex((item) => item._id === childId);
if (inventoryIndex > -1)
{
inventoryItems.splice(inventoryIndex, 1);
@ -610,7 +610,7 @@ export class InventoryHelper
);
}
const insuredIndex = insuredItems.findIndex(item => item.itemId === childId);
const insuredIndex = insuredItems.findIndex((item) => item.itemId === childId);
if (insuredIndex > -1)
{
insuredItems.splice(insuredIndex, 1);
@ -636,7 +636,7 @@ export class InventoryHelper
const dialogs = Object.values(fullProfile.dialogues);
for (const dialog of dialogs)
{
const messageWithReward = dialog.messages.find(x => x._id === removeRequest.fromOwner.id);
const messageWithReward = dialog.messages.find((x) => x._id === removeRequest.fromOwner.id);
if (messageWithReward)
{
// Find item + any possible children and remove them from mails items array
@ -876,7 +876,9 @@ export class InventoryHelper
*/
protected getBlankContainerMap(containerH: number, containerY: number): number[][]
{
return Array(containerY).fill(0).map(() => Array(containerH).fill(0));
return Array(containerY)
.fill(0)
.map(() => Array(containerH).fill(0));
}
/**
@ -909,12 +911,14 @@ export class InventoryHelper
const iW = tmpSize[0]; // x
const iH = tmpSize[1]; // y
const fH
= (item.location as Location).r === 1 || (item.location as Location).r === "Vertical"
= (item.location as Location).r === 1
|| (item.location as Location).r === "Vertical"
|| (item.location as Location).rotation === "Vertical"
? iW
: iH;
const fW
= (item.location as Location).r === 1 || (item.location as Location).r === "Vertical"
= (item.location as Location).r === 1
|| (item.location as Location).r === "Vertical"
|| (item.location as Location).rotation === "Vertical"
? iH
: iW;
@ -1078,7 +1082,7 @@ export class InventoryHelper
protected getPlayerStashSize(sessionID: string): Record<number, number>
{
const profile = this.profileHelper.getPmcProfile(sessionID);
const stashRowBonus = profile.Bonuses.find(bonus => bonus.type === BonusType.STASH_ROWS);
const stashRowBonus = profile.Bonuses.find((bonus) => bonus.type === BonusType.STASH_ROWS);
// this sets automatically a stash size from items.json (its not added anywhere yet cause we still use base stash)
const stashTPL = this.getStashType(sessionID);
@ -1118,7 +1122,7 @@ export class InventoryHelper
protected getStashType(sessionID: string): string
{
const pmcData = this.profileHelper.getPmcProfile(sessionID);
const stashObj = pmcData.Inventory.items.find(item => item._id === pmcData.Inventory.stash);
const stashObj = pmcData.Inventory.items.find((item) => item._id === pmcData.Inventory.stash);
if (!stashObj)
{
this.logger.error(this.localisationService.getText("inventory-unable_to_find_stash"));
@ -1140,7 +1144,7 @@ export class InventoryHelper
const idsToMove = this.itemHelper.findAndReturnChildrenByItems(fromItems, body.item);
for (const itemId of idsToMove)
{
const itemToMove = fromItems.find(x => x._id === itemId);
const itemToMove = fromItems.find((x) => x._id === itemId);
if (!itemToMove)
{
this.logger.error(`Unable to find item to move: ${itemId}`);
@ -1188,7 +1192,7 @@ export class InventoryHelper
this.handleCartridges(inventoryItems, moveRequest);
// Find item we want to 'move'
const matchingInventoryItem = inventoryItems.find(x => x._id === moveRequest.item);
const matchingInventoryItem = inventoryItems.find((x) => x._id === moveRequest.item);
if (!matchingInventoryItem)
{
const errorMesage = `Unable to move item: ${moveRequest.item}, cannot find in inventory`;
@ -1248,7 +1252,7 @@ export class InventoryHelper
if (pmcData.Inventory.fastPanel[itemKey] === itemBeingMoved._id)
{
// Get moved items parent
const itemParent = pmcData.Inventory.items.find(x => x._id === itemBeingMoved.parentId);
const itemParent = pmcData.Inventory.items.find((x) => x._id === itemBeingMoved.parentId);
// Empty out id if item is moved to a container other than pocket/rig
if (itemParent && !(itemParent.slotId?.startsWith("Pockets") || itemParent.slotId === "TacticalVest"))
@ -1317,7 +1321,7 @@ export class InventoryHelper
return true;
}
container = pmcData.Inventory.items.find(item => item._id === container.parentId);
container = pmcData.Inventory.items.find((item) => item._id === container.parentId);
if (!container)
{
break;

View File

@ -68,7 +68,7 @@ export class ItemHelper
}
for (const itemOf1 of item1)
{
const itemOf2 = item2.find(i2 => i2._tpl === itemOf1._tpl);
const itemOf2 = item2.find((i2) => i2._tpl === itemOf1._tpl);
if (itemOf2 === undefined)
{
return false;
@ -98,7 +98,7 @@ export class ItemHelper
if (compareUpdProperties)
{
return Array.from(compareUpdProperties.values()).every(p =>
return Array.from(compareUpdProperties.values()).every((p) =>
this.compareUtil.recursiveCompare(item1.upd?.[p], item2.upd?.[p]),
);
}
@ -194,11 +194,13 @@ export class ItemHelper
return false;
}
return !itemDetails[1]._props.QuestItem
return (
!itemDetails[1]._props.QuestItem
&& itemDetails[1]._type === "Item"
&& baseTypes.every(x => !this.isOfBaseclass(tpl, x))
&& baseTypes.every((x) => !this.isOfBaseclass(tpl, x))
&& this.getItemPrice(tpl) > 0
&& !this.itemFilterService.isItemBlacklisted(tpl);
&& !this.itemFilterService.isItemBlacklisted(tpl)
);
}
/**
@ -261,7 +263,7 @@ export class ItemHelper
const itemTemplate = this.getItem(itemTpl);
const plateSlotIds = this.getRemovablePlateSlotIds();
return itemTemplate[1]._props.Slots.some(slot => plateSlotIds.includes(slot._name.toLowerCase()));
return itemTemplate[1]._props.Slots.some((slot) => plateSlotIds.includes(slot._name.toLowerCase()));
}
/**
@ -292,7 +294,7 @@ export class ItemHelper
// Check if item has slots that match soft insert name ids
const softInsertIds = this.getSoftInsertSlotIds();
if (itemDbDetails[1]._props.Slots.find(slot => softInsertIds.includes(slot._name.toLowerCase())))
if (itemDbDetails[1]._props.Slots.find((slot) => softInsertIds.includes(slot._name.toLowerCase())))
{
return true;
}
@ -629,7 +631,7 @@ export class ItemHelper
}
// Items parentid matches root item AND returned items doesnt contain current child
if (childItem.parentId === baseItemId && !list.find(item => childItem._id === item._id))
if (childItem.parentId === baseItemId && !list.find((item) => childItem._id === item._id))
{
list.push(...this.findAndReturnChildrenAsItems(items, childItem._id));
}
@ -650,7 +652,7 @@ export class ItemHelper
for (const itemFromAssort of assort)
{
if (itemFromAssort.parentId === itemIdToFind && !list.find(item => itemFromAssort._id === item._id))
if (itemFromAssort.parentId === itemIdToFind && !list.find((item) => itemFromAssort._id === item._id))
{
list.push(itemFromAssort);
list = list.concat(this.findAndReturnChildrenByAssort(itemFromAssort._id, assort));
@ -798,9 +800,8 @@ export class ItemHelper
public findBarterItems(by: "tpl" | "id", itemsToSearch: Item[], desiredBarterItemIds: string | string[]): Item[]
{
// Find required items to take after buying (handles multiple items)
const desiredBarterIds = typeof desiredBarterItemIds === "string"
? [desiredBarterItemIds]
: desiredBarterItemIds;
const desiredBarterIds
= typeof desiredBarterItemIds === "string" ? [desiredBarterItemIds] : desiredBarterItemIds;
const matchingItems: Item[] = [];
for (const barterId of desiredBarterIds)
@ -846,7 +847,7 @@ export class ItemHelper
if (pmcData !== null)
{
// Insured items should not be renamed. Only works for PMCs.
if (insuredItems?.find(insuredItem => insuredItem.itemId === item._id))
if (insuredItems?.find((insuredItem) => insuredItem.itemId === item._id))
{
continue;
}
@ -1054,8 +1055,8 @@ export class ItemHelper
let isRequiredSlot = false;
if (parentTemplate[0] && parentTemplate[1]?._props?.Slots)
{
isRequiredSlot = parentTemplate[1]._props.Slots.some(slot =>
slot._name === item.slotId && slot._required,
isRequiredSlot = parentTemplate[1]._props.Slots.some(
(slot) => slot._name === item.slotId && slot._required,
);
}
@ -1100,11 +1101,13 @@ export class ItemHelper
*/
public isAttachmentAttached(item: Item): boolean
{
const equipmentSlots = Object.values(EquipmentSlots).map(value => value as string);
const equipmentSlots = Object.values(EquipmentSlots).map((value) => value as string);
return !(["hideout", "main"].includes(item.slotId)
return !(
["hideout", "main"].includes(item.slotId)
|| equipmentSlots.includes(item.slotId)
|| !Number.isNaN(Number(item.slotId)));
|| !Number.isNaN(Number(item.slotId))
);
}
/**
@ -1125,7 +1128,7 @@ export class ItemHelper
public getEquipmentParent(itemId: string, itemsMap: Map<string, Item>): Item | null
{
let currentItem = itemsMap.get(itemId);
const equipmentSlots = Object.values(EquipmentSlots).map(value => value as string);
const equipmentSlots = Object.values(EquipmentSlots).map((value) => value as string);
while (currentItem && !equipmentSlots.includes(currentItem.slotId))
{
@ -1146,7 +1149,7 @@ export class ItemHelper
*/
public getItemSize(items: Item[], rootItemId: string): ItemHelper.ItemSize
{
const rootTemplate = this.getItem(items.filter(x => x._id === rootItemId)[0]._tpl)[1];
const rootTemplate = this.getItem(items.filter((x) => x._id === rootItemId)[0]._tpl)[1];
const width = rootTemplate._props.Width;
const height = rootTemplate._props.Height;
@ -1178,9 +1181,8 @@ export class ItemHelper
sizeUp = sizeUp < itemTemplate._props.ExtraSizeUp ? itemTemplate._props.ExtraSizeUp : sizeUp;
sizeDown = sizeDown < itemTemplate._props.ExtraSizeDown ? itemTemplate._props.ExtraSizeDown : sizeDown;
sizeLeft = sizeLeft < itemTemplate._props.ExtraSizeLeft ? itemTemplate._props.ExtraSizeLeft : sizeLeft;
sizeRight = sizeRight < itemTemplate._props.ExtraSizeRight
? itemTemplate._props.ExtraSizeRight
: sizeRight;
sizeRight
= sizeRight < itemTemplate._props.ExtraSizeRight ? itemTemplate._props.ExtraSizeRight : sizeRight;
}
}
@ -1221,7 +1223,7 @@ export class ItemHelper
const cartridgeMaxStackSize = cartridgeDetails[1]._props.StackMaxSize;
// Exit if ammo already exists in box
if (ammoBox.find(item => item._tpl === cartridgeTpl))
if (ammoBox.find((item) => item._tpl === cartridgeTpl))
{
return;
}
@ -1289,7 +1291,7 @@ export class ItemHelper
public itemIsInsideContainer(item: Item, desiredContainerSlotId: string, items: Item[]): boolean
{
// Get items parent
const parent = items.find(x => x._id === item.parentId);
const parent = items.find((x) => x._id === item.parentId);
if (!parent)
{
// No parent, end of line, not inside container
@ -1394,9 +1396,8 @@ export class ItemHelper
while (currentStoredCartridgeCount < desiredStackCount)
{
// Get stack size of cartridges
let cartridgeCountToAdd = desiredStackCount <= cartridgeMaxStackSize
? desiredStackCount
: cartridgeMaxStackSize;
let cartridgeCountToAdd
= desiredStackCount <= cartridgeMaxStackSize ? desiredStackCount : cartridgeMaxStackSize;
// Ensure we don't go over the max stackcount size
const remainingSpace = desiredStackCount - currentStoredCartridgeCount;
@ -1437,9 +1438,9 @@ export class ItemHelper
const ammoTpls = magTemplate._props.Cartridges[0]._props.filters[0].Filter;
const calibers = [
...new Set(
ammoTpls.filter((x: string) => this.getItem(x)[0]).map((x: string) =>
this.getItem(x)[1]._props.Caliber,
),
ammoTpls
.filter((x: string) => this.getItem(x)[0])
.map((x: string) => this.getItem(x)[1]._props.Caliber),
),
];
return this.randomUtil.drawRandomFromList(calibers)[0];
@ -1555,9 +1556,9 @@ export class ItemHelper
public getItemTplsOfBaseType(desiredBaseType: string): string[]
{
return Object.values(this.databaseServer.getTables().templates.items).filter(x =>
x._parent === desiredBaseType,
).map(x => x._id);
return Object.values(this.databaseServer.getTables().templates.items)
.filter((x) => x._parent === desiredBaseType)
.map((x) => x._id);
}
/**
@ -1771,7 +1772,7 @@ export class ItemHelper
for (const item of items)
{
// Check if the item's parent exists.
const parentExists = items.some(parentItem => parentItem._id === item.parentId);
const parentExists = items.some((parentItem) => parentItem._id === item.parentId);
// If the parent does not exist and the item is not already a 'hideout' item, adopt the orphaned item by
// setting the parent ID to the PMCs inventory equipment ID, the slot ID to 'hideout', and remove the location.

View File

@ -86,7 +86,8 @@ export class NotificationSendHelper
protected getDialog(sessionId: string, messageType: MessageType, senderDetails: IUserDialogInfo): Dialogue
{
// Use trader id if sender is trader, otherwise use nickname
const key = senderDetails.Info.MemberCategory === MemberCategory.TRADER
const key
= senderDetails.Info.MemberCategory === MemberCategory.TRADER
? senderDetails._id
: senderDetails.Info.Nickname;
const dialogueData = this.saveServer.getProfile(sessionId).dialogues;

View File

@ -21,8 +21,8 @@ export class PaymentHelper
*/
public isMoneyTpl(tpl: string): boolean
{
return [Money.DOLLARS, Money.EUROS, Money.ROUBLES, ...this.inventoryConfig.customMoneyTpls].some(element =>
element === tpl,
return [Money.DOLLARS, Money.EUROS, Money.ROUBLES, ...this.inventoryConfig.customMoneyTpls].some(
(element) => element === tpl,
);
}

View File

@ -44,11 +44,9 @@ export class PresetHelper
{
if (!this.defaultWeaponPresets)
{
this.defaultWeaponPresets = Object.values(
this.databaseServer.getTables().globals.ItemPresets,
)
this.defaultWeaponPresets = Object.values(this.databaseServer.getTables().globals.ItemPresets)
.filter(
preset =>
(preset) =>
preset._encyclopedia !== undefined
&& this.itemHelper.isOfBaseclass(preset._encyclopedia, BaseClasses.WEAPON),
)
@ -71,9 +69,12 @@ export class PresetHelper
if (!this.defaultEquipmentPresets)
{
this.defaultEquipmentPresets = Object.values(this.databaseServer.getTables().globals.ItemPresets)
.filter(preset => preset._encyclopedia !== undefined
.filter(
(preset) =>
preset._encyclopedia !== undefined
&& this.itemHelper.armorItemCanHoldMods(preset._encyclopedia),
).reduce((acc, cur) =>
)
.reduce((acc, cur) =>
{
acc[cur._id] = cur;
return acc;
@ -186,7 +187,7 @@ export class PresetHelper
const defaultPreset = this.getDefaultPreset(tpl);
// Bundle up tpls we want price for
const tpls = defaultPreset ? defaultPreset._items.map(item => item._tpl) : [tpl];
const tpls = defaultPreset ? defaultPreset._items.map((item) => item._tpl) : [tpl];
// Get price of tpls
return this.itemHelper.getItemAndChildrenPrice(tpls);

View File

@ -52,7 +52,7 @@ export class ProfileHelper
for (const questId in questConditionId)
{
const conditionId = questConditionId[questId];
const profileQuest = pmcData.Quests.find(x => x.qid === questId);
const profileQuest = pmcData.Quests.find((x) => x.qid === questId);
// Find index of condition in array
const index = profileQuest.completedConditions.indexOf(conditionId);
@ -339,7 +339,7 @@ export class ProfileHelper
public removeSecureContainer(profile: IPmcData): IPmcData
{
const items = profile.Inventory.items;
const secureContainer = items.find(x => x.slotId === "SecuredContainer");
const secureContainer = items.find((x) => x.slotId === "SecuredContainer");
if (secureContainer)
{
// Find and remove container + children
@ -349,7 +349,7 @@ export class ProfileHelper
);
// Remove child items + secure container
profile.Inventory.items = items.filter(x => !childItemsInSecureContainer.includes(x._id));
profile.Inventory.items = items.filter((x) => !childItemsInSecureContainer.includes(x._id));
}
return profile;
@ -393,7 +393,7 @@ export class ProfileHelper
return false;
}
return !!profile.aki.receivedGifts.find(x => x.giftId === giftId);
return !!profile.aki.receivedGifts.find((x) => x.giftId === giftId);
}
/**
@ -403,7 +403,7 @@ export class ProfileHelper
*/
public incrementStatCounter(counters: CounterKeyValue[], keyToIncrement: string): void
{
const stat = counters.find(x => x.Key.includes(keyToIncrement));
const stat = counters.find((x) => x.Key.includes(keyToIncrement));
if (stat)
{
stat.Value++;
@ -424,7 +424,7 @@ export class ProfileHelper
return false;
}
const profileSkill = profileSkills.find(x => x.Id === skillType);
const profileSkill = profileSkills.find((x) => x.Id === skillType);
if (!profileSkill)
{
this.logger.warning(`Unable to check for elite skill ${skillType}, not found in profile`);
@ -466,7 +466,7 @@ export class ProfileHelper
return;
}
const profileSkill = profileSkills.find(profileSkill => profileSkill.Id === skill);
const profileSkill = profileSkills.find((profileSkill) => profileSkill.Id === skill);
if (!profileSkill)
{
this.logger.error(this.localisationService.getText("quest-no_skill_found", skill));
@ -499,7 +499,7 @@ export class ProfileHelper
*/
public getSkillFromProfile(pmcData: IPmcData, skill: SkillTypes): Common
{
const skillToReturn = pmcData.Skills.Common.find(commonSkill => commonSkill.Id === skill);
const skillToReturn = pmcData.Skills.Common.find((commonSkill) => commonSkill.Id === skill);
if (!skillToReturn)
{
this.logger.warning(`Profile ${pmcData.sessionId} does not have a skill named: ${skill}`);
@ -527,7 +527,7 @@ export class ProfileHelper
public addStashRowsBonusToProfile(sessionId: string, rowsToAdd: number): void
{
const profile = this.getPmcProfile(sessionId);
const existingBonus = profile.Bonuses.find(bonus => bonus.type === BonusType.STASH_ROWS);
const existingBonus = profile.Bonuses.find((bonus) => bonus.type === BonusType.STASH_ROWS);
if (!existingBonus)
{
profile.Bonuses.push({

View File

@ -11,7 +11,6 @@ import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
import { Common, IQuestStatus } from "@spt-aki/models/eft/common/tables/IBotBase";
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
import { IQuest, IQuestCondition, IQuestReward } from "@spt-aki/models/eft/common/tables/IQuest";
import { IRepeatableQuest } from "@spt-aki/models/eft/common/tables/IRepeatableQuests";
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
import { IAcceptQuestRequestData } from "@spt-aki/models/eft/quests/IAcceptQuestRequestData";
import { IFailQuestRequestData } from "@spt-aki/models/eft/quests/IFailQuestRequestData";
@ -69,7 +68,7 @@ export class QuestHelper
*/
public getQuestStatus(pmcData: IPmcData, questId: string): QuestStatus
{
const quest = pmcData.Quests?.find(q => q.qid === questId);
const quest = pmcData.Quests?.find((q) => q.qid === questId);
return quest ? quest.status : QuestStatus.Locked;
}
@ -150,7 +149,7 @@ export class QuestHelper
}
// This calculates how much progress we have in the skill's starting level
let startingLevelProgress = profileSkill.Progress % 100 * ((currentLevel + 1) / 10);
let startingLevelProgress = (profileSkill.Progress % 100) * ((currentLevel + 1) / 10);
// The code below assumes a 1/10th progress skill amount
let remainingProgress = progressAmount / 10;
@ -164,7 +163,7 @@ export class QuestHelper
const currentLevelRemainingProgress = (currentLevel + 1) * 10 - startingLevelProgress;
this.logger.debug(`currentLevelRemainingProgress: ${currentLevelRemainingProgress}`);
const progressToAdd = Math.min(remainingProgress, currentLevelRemainingProgress);
const adjustedProgressToAdd = 10 / (currentLevel + 1) * progressToAdd;
const adjustedProgressToAdd = (10 / (currentLevel + 1)) * progressToAdd;
this.logger.debug(`Progress To Add: ${progressToAdd} Adjusted for level: ${adjustedProgressToAdd}`);
// Add the progress amount adjusted by level
@ -286,10 +285,13 @@ export class QuestHelper
// Is root item, fix stacks
if (rewardItem._id === questReward.target)
{ // Is base reward item
{
// Is base reward item
if (
rewardItem.parentId !== undefined && rewardItem.parentId === "hideout" // Has parentId of hideout
&& rewardItem.upd !== undefined && rewardItem.upd.StackObjectsCount !== undefined // Has upd with stackobject count
rewardItem.parentId !== undefined
&& rewardItem.parentId === "hideout" // Has parentId of hideout
&& rewardItem.upd !== undefined
&& rewardItem.upd.StackObjectsCount !== undefined // Has upd with stackobject count
&& rewardItem.upd.StackObjectsCount > 1 // More than 1 item in stack
)
{
@ -353,7 +355,7 @@ export class QuestHelper
questReward.items = presetAndMods;
// Find root item and set its stack count
const rootItem = questReward.items.find(item => item._id === newRootId);
const rootItem = questReward.items.find((item) => item._id === newRootId);
// Remap target id to the new presets root id
questReward.target = rootItem._id;
@ -385,7 +387,7 @@ export class QuestHelper
{
// Iterate over all rewards with the desired status, flatten out items that have a type of Item
const questRewards = quest.rewards[QuestStatus[status]].flatMap((reward: IQuestReward) =>
(reward.type === "Item" ? this.processReward(reward) : []),
reward.type === "Item" ? this.processReward(reward) : [],
);
return questRewards;
@ -404,7 +406,7 @@ export class QuestHelper
): IQuestStatus
{
const currentTimestamp = this.timeUtil.getTimestamp();
const existingQuest = pmcData.Quests.find(q => q.qid === acceptedQuest.qid);
const existingQuest = pmcData.Quests.find((q) => q.qid === acceptedQuest.qid);
if (existingQuest)
{
// Quest exists, update its status
@ -436,7 +438,7 @@ export class QuestHelper
this.logger.error(`Quest: ${acceptedQuest.qid} of type: ${acceptedQuest.type} not found`);
}
const waitTime = questDbData?.conditions.AvailableForStart.find(x => x.availableAfter > 0);
const waitTime = questDbData?.conditions.AvailableForStart.find((x) => x.availableAfter > 0);
if (waitTime && acceptedQuest.type !== "repeatable")
{
// Quest should be put into 'pending' state
@ -463,7 +465,7 @@ export class QuestHelper
{
// Get quest acceptance data from profile
const profile: IPmcData = this.profileHelper.getPmcProfile(sessionID);
const startedQuestInProfile = profile.Quests.find(profileQuest => profileQuest.qid === startedQuestId);
const startedQuestInProfile = profile.Quests.find((profileQuest) => profileQuest.qid === startedQuestId);
// Get quests that
const eligibleQuests = this.getQuestsFromDb().filter((quest) =>
@ -472,9 +474,11 @@ export class QuestHelper
// e.g. Quest A passed in, quest B is looped over and has requirement of A to be started, include it
const acceptedQuestCondition = quest.conditions.AvailableForStart.find((x) =>
{
return x.conditionType === "Quest"
return (
x.conditionType === "Quest"
&& x.target?.includes(startedQuestId)
&& x.status?.includes(QuestStatus.Started);
&& x.status?.includes(QuestStatus.Started)
);
});
// Not found, skip quest
@ -512,8 +516,10 @@ export class QuestHelper
}
// Include if quest found in profile and is started or ready to hand in
return startedQuestInProfile
&& [QuestStatus.Started, QuestStatus.AvailableForFinish].includes(startedQuestInProfile.status);
return (
startedQuestInProfile
&& [QuestStatus.Started, QuestStatus.AvailableForFinish].includes(startedQuestInProfile.status)
);
});
return this.getQuestsWithOnlyLevelRequirementStartCondition(eligibleQuests);
@ -551,15 +557,15 @@ export class QuestHelper
public failedUnlocked(failedQuestId: string, sessionId: string): IQuest[]
{
const profile = this.profileHelper.getPmcProfile(sessionId);
const profileQuest = profile.Quests.find(x => x.qid === failedQuestId);
const profileQuest = profile.Quests.find((x) => x.qid === failedQuestId);
const quests = this.getQuestsFromDb().filter((q) =>
{
const acceptedQuestCondition = q.conditions.AvailableForStart.find((c) =>
{
return c.conditionType === "Quest"
&& c.target.includes(failedQuestId)
&& c.status[0] === QuestStatus.Fail;
return (
c.conditionType === "Quest" && c.target.includes(failedQuestId) && c.status[0] === QuestStatus.Fail
);
});
if (!acceptedQuestCondition)
@ -595,7 +601,7 @@ export class QuestHelper
if (this.paymentHelper.isMoneyTpl(reward.items[0]._tpl))
{
reward.items[0].upd.StackObjectsCount += Math.round(
reward.items[0].upd.StackObjectsCount * multiplier / 100,
(reward.items[0].upd.StackObjectsCount * multiplier) / 100,
);
}
}
@ -621,7 +627,7 @@ export class QuestHelper
output: IItemEventRouterResponse,
): void
{
const inventoryItemIndex = pmcData.Inventory.items.findIndex(item => item._id === itemId);
const inventoryItemIndex = pmcData.Inventory.items.findIndex((item) => item._id === itemId);
if (inventoryItemIndex < 0)
{
this.logger.error(this.localisationService.getText("quest-item_not_found_in_inventory", itemId));
@ -692,8 +698,8 @@ export class QuestHelper
public getQuestWithOnlyLevelRequirementStartCondition(quest: IQuest): IQuest
{
const updatedQuest = this.cloner.clone(quest);
updatedQuest.conditions.AvailableForStart = updatedQuest.conditions.AvailableForStart.filter(q =>
q.conditionType === "Level",
updatedQuest.conditions.AvailableForStart = updatedQuest.conditions.AvailableForStart.filter(
(q) => q.conditionType === "Level",
);
return updatedQuest;
@ -734,9 +740,9 @@ export class QuestHelper
const quest = this.getQuestFromDb(failRequest.qid, pmcData);
// Merge all daily/weekly/scav daily quests into one array and look for the matching quest by id
const matchingRepeatableQuest = pmcData.RepeatableQuests.flatMap(repeatableType =>
repeatableType.activeQuests,
).find(activeQuest => activeQuest._id === failRequest.qid);
const matchingRepeatableQuest = pmcData.RepeatableQuests.flatMap(
(repeatableType) => repeatableType.activeQuests,
).find((activeQuest) => activeQuest._id === failRequest.qid);
// Quest found and no repeatable found
if (quest && !matchingRepeatableQuest)
@ -783,7 +789,7 @@ export class QuestHelper
// Check daily/weekly objects
for (const repeatableType of pmcData.RepeatableQuests)
{
quest = <IQuest><unknown>repeatableType.activeQuests.find(x => x._id === questId);
quest = <IQuest>(<unknown>repeatableType.activeQuests.find((x) => x._id === questId));
if (quest)
{
break;
@ -805,7 +811,9 @@ export class QuestHelper
// blank or is a guid, use description instead
const startedMessageText = this.getQuestLocaleIdFromDb(startedMessageTextId);
if (
!startedMessageText || startedMessageText.trim() === "" || startedMessageText.toLowerCase() === "test"
!startedMessageText
|| startedMessageText.trim() === ""
|| startedMessageText.toLowerCase() === "test"
|| startedMessageText.length === 24
)
{
@ -835,7 +843,7 @@ export class QuestHelper
public updateQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void
{
// Find quest in profile, update status to desired status
const questToUpdate = pmcData.Quests.find(quest => quest.qid === questId);
const questToUpdate = pmcData.Quests.find((quest) => quest.qid === questId);
if (questToUpdate)
{
questToUpdate.status = newQuestState;
@ -851,7 +859,7 @@ export class QuestHelper
*/
public resetQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void
{
const questToUpdate = pmcData.Quests.find(quest => quest.qid === questId);
const questToUpdate = pmcData.Quests.find((quest) => quest.qid === questId);
if (questToUpdate)
{
const currentTimestamp = this.timeUtil.getTimestamp();
@ -994,9 +1002,10 @@ export class QuestHelper
{
// Get hideout crafts and find those that match by areatype/required level/end product tpl - hope for just one match
const hideoutProductions = this.databaseServer.getTables().hideout.production;
const matchingProductions = hideoutProductions.filter(x =>
const matchingProductions = hideoutProductions.filter(
(x) =>
x.areaType === Number.parseInt(craftUnlockReward.traderId)
&& x.requirements.some(x => x.requiredLevel === craftUnlockReward.loyaltyLevel)
&& x.requirements.some((x) => x.requiredLevel === craftUnlockReward.loyaltyLevel)
&& x.endProduct === craftUnlockReward.items[0]._tpl,
);
@ -1027,7 +1036,7 @@ export class QuestHelper
protected getQuestMoneyRewardBonus(pmcData: IPmcData): number
{
// Check player has intel center
const moneyRewardBonuses = pmcData.Bonuses.filter(x => x.type === "QuestMoneyReward");
const moneyRewardBonuses = pmcData.Bonuses.filter((x) => x.type === "QuestMoneyReward");
if (!moneyRewardBonuses)
{
return 0;
@ -1061,15 +1070,15 @@ export class QuestHelper
const result: Record<string, string> = {};
for (const questId of questIds)
{
const questInDb = allQuests.find(x => x._id === questId);
const questInDb = allQuests.find((x) => x._id === questId);
if (!questInDb)
{
this.logger.debug(`Unable to find quest: ${questId} in db, cannot get 'FindItem' condition, skipping`);
continue;
}
const condition = questInDb.conditions.AvailableForFinish.find(c =>
c.conditionType === "FindItem" && c?.target?.includes(itemTpl),
const condition = questInDb.conditions.AvailableForFinish.find(
(c) => c.conditionType === "FindItem" && c?.target?.includes(itemTpl),
);
if (condition)
{
@ -1095,7 +1104,7 @@ export class QuestHelper
{
// Quest from db matches quests in profile, skip
const questData = quests[questIdKey];
if (pmcProfile.Quests.find(x => x.qid === questData._id))
if (pmcProfile.Quests.find((x) => x.qid === questData._id))
{
continue;
}
@ -1115,10 +1124,10 @@ export class QuestHelper
availableAfter: 0,
};
if (pmcProfile.Quests.some(x => x.qid === questIdKey))
if (pmcProfile.Quests.some((x) => x.qid === questIdKey))
{
// Update existing
const existingQuest = pmcProfile.Quests.find(x => x.qid === questIdKey);
const existingQuest = pmcProfile.Quests.find((x) => x.qid === questIdKey);
existingQuest.status = questRecordToAdd.status;
existingQuest.statusTimers = questRecordToAdd.statusTimers;
}
@ -1132,7 +1141,7 @@ export class QuestHelper
public findAndRemoveQuestFromArrayIfExists(questId: string, quests: IQuestStatus[]): void
{
const pmcQuestToReplaceStatus = quests.find(quest => quest.qid === questId);
const pmcQuestToReplaceStatus = quests.find((quest) => quest.qid === questId);
if (pmcQuestToReplaceStatus)
{
quests.splice(quests.indexOf(pmcQuestToReplaceStatus), 1);
@ -1155,7 +1164,7 @@ export class QuestHelper
return false;
}
return quest.conditions.Fail.some(condition => condition.target?.includes(completedQuestId));
return quest.conditions.Fail.some((condition) => condition.target?.includes(completedQuestId));
});
}
}

View File

@ -156,7 +156,7 @@ export class RagfairHelper
for (let item of items)
{
item = this.itemHelper.fixItemStackCount(item);
const isChild = items.find(it => it._id === item.parentId);
const isChild = items.find((it) => it._id === item.parentId);
if (!isChild)
{

View File

@ -14,7 +14,6 @@ import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEve
import { IAkiProfile, ISystemData } from "@spt-aki/models/eft/profile/IAkiProfile";
import { IRagfairOffer } from "@spt-aki/models/eft/ragfair/IRagfairOffer";
import { ISearchRequestData, OfferOwnerType } from "@spt-aki/models/eft/ragfair/ISearchRequestData";
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
import { MemberCategory } from "@spt-aki/models/enums/MemberCategory";
import { MessageType } from "@spt-aki/models/enums/MessageType";
@ -185,7 +184,7 @@ export class RagfairOfferHelper
const lockedOffers = this.getLoyaltyLockedOffers(possibleOffers, pmcData);
// Exclude locked offers + above loyalty locked offers if at least 1 was found
const availableOffers = possibleOffers.filter(x => !(x.locked || lockedOffers.includes(x._id)));
const availableOffers = possibleOffers.filter((x) => !(x.locked || lockedOffers.includes(x._id)));
if (availableOffers.length > 0)
{
possibleOffers = availableOffers;
@ -220,8 +219,8 @@ export class RagfairOfferHelper
*/
public traderOfferItemQuestLocked(offer: IRagfairOffer, traderAssorts: Record<string, ITraderAssort>): boolean
{
return offer.items?.some(i =>
traderAssorts[offer.user.id].barter_scheme[i._id]?.some(bs1 => bs1?.some(bs2 => bs2.sptQuestLocked)),
return offer.items?.some((i) =>
traderAssorts[offer.user.id].barter_scheme[i._id]?.some((bs1) => bs1?.some((bs2) => bs2.sptQuestLocked)),
);
}
@ -248,15 +247,15 @@ export class RagfairOfferHelper
protected traderBuyRestrictionReached(offer: IRagfairOffer): boolean
{
const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(offer.user.id).items;
const assortData = traderAssorts.find(x => x._id === offer.items[0]._id);
const assortData = traderAssorts.find((x) => x._id === offer.items[0]._id);
// No trader assort data
if (!assortData)
{
this.logger.warning(
`Unable to find trader: ${offer.user.nickname} assort for item: ${
this.itemHelper.getItemName(offer.items[0]._tpl)
} ${offer.items[0]._tpl}, cannot check if buy restriction reached`,
`Unable to find trader: ${offer.user.nickname} assort for item: ${this.itemHelper.getItemName(
offer.items[0]._tpl,
)} ${offer.items[0]._tpl}, cannot check if buy restriction reached`,
);
return false;
}
@ -333,7 +332,7 @@ export class RagfairOfferHelper
this.increaseProfileRagfairRating(
this.saveServer.getProfile(sessionID),
offer.summaryCost / totalItemsCount * boughtAmount,
(offer.summaryCost / totalItemsCount) * boughtAmount,
);
this.completeOffer(sessionID, offer, boughtAmount);
@ -361,7 +360,7 @@ export class RagfairOfferHelper
return;
}
profile.characters.pmc.RagfairInfo.rating
+= ragfairConfig.ratingIncreaseCount / ragfairConfig.ratingSumForIncrease * amountToIncrementBy;
+= (ragfairConfig.ratingIncreaseCount / ragfairConfig.ratingSumForIncrease) * amountToIncrementBy;
}
/**
@ -389,7 +388,7 @@ export class RagfairOfferHelper
protected deleteOfferById(sessionID: string, offerId: string): void
{
const profileRagfairInfo = this.saveServer.getProfile(sessionID).characters.pmc.RagfairInfo;
const index = profileRagfairInfo.offers.findIndex(o => o._id === offerId);
const index = profileRagfairInfo.offers.findIndex((o) => o._id === offerId);
profileRagfairInfo.offers.splice(index, 1);
// Also delete from ragfair
@ -416,7 +415,7 @@ export class RagfairOfferHelper
else
{
offer.items[0].upd.StackObjectsCount -= boughtAmount;
const rootItems = offer.items.filter(i => i.parentId === "hideout");
const rootItems = offer.items.filter((i) => i.parentId === "hideout");
rootItems.splice(0, 1);
let removeCount = boughtAmount;
@ -446,9 +445,9 @@ export class RagfairOfferHelper
for (const id of idsToRemove)
{
const newIds = offer.items.filter(i =>
!idsToRemove.includes(i._id) && idsToRemove.includes(i.parentId),
).map(i => i._id);
const newIds = offer.items
.filter((i) => !idsToRemove.includes(i._id) && idsToRemove.includes(i.parentId))
.map((i) => i._id);
if (newIds.length > 0)
{
foundNewItems = true;
@ -459,7 +458,7 @@ export class RagfairOfferHelper
if (idsToRemove.length > 0)
{
offer.items = offer.items.filter(i => !idsToRemove.includes(i._id));
offer.items = offer.items.filter((i) => !idsToRemove.includes(i._id));
}
}
@ -684,7 +683,7 @@ export class RagfairOfferHelper
if (this.itemHelper.armorItemCanHoldMods(offerRootItem._tpl))
{
const offerRootTemplate = this.itemHelper.getItem(offerRootItem._tpl)[1];
const requiredPlateCount = offerRootTemplate._props.Slots?.filter(item => item._required)?.length;
const requiredPlateCount = offerRootTemplate._props.Slots?.filter((item) => item._required)?.length;
return offer.items.length > requiredPlateCount;
}
@ -724,7 +723,7 @@ export class RagfairOfferHelper
// Performing a required search and offer doesn't have requirement for item
if (
searchRequest.neededSearchId
&& !offer.requirements.some(requirement => requirement._tpl === searchRequest.neededSearchId)
&& !offer.requirements.some((requirement) => requirement._tpl === searchRequest.neededSearchId)
)
{
return false;
@ -782,7 +781,7 @@ export class RagfairOfferHelper
public isDisplayableOfferThatNeedsItem(searchRequest: ISearchRequestData, offer: IRagfairOffer): boolean
{
if (offer.requirements.some(requirement => requirement._tpl === searchRequest.neededSearchId))
if (offer.requirements.some((requirement) => requirement._tpl === searchRequest.neededSearchId))
{
return true;
}
@ -799,7 +798,11 @@ export class RagfairOfferHelper
{
// thanks typescript, undefined assertion is not returnable since it
// tries to return a multitype object
return item.upd.MedKit || item.upd.Repairable || item.upd.Resource || item.upd.FoodDrink || item.upd.Key
return item.upd.MedKit
|| item.upd.Repairable
|| item.upd.Resource
|| item.upd.FoodDrink
|| item.upd.Key
|| item.upd.RepairKit
? true
: false;

View File

@ -43,7 +43,7 @@ export class RagfairSellHelper
const baseSellChancePercent = sellConfig.base * qualityMultiplier;
// Modfier gets applied twice to either penalize or incentivize over/under pricing (Probably a cleaner way to do this)
const sellModifier = averageOfferPriceRub / playerListedPriceRub * sellConfig.sellMultiplier;
const sellModifier = (averageOfferPriceRub / playerListedPriceRub) * sellConfig.sellMultiplier;
let sellChance = Math.round(baseSellChancePercent * sellModifier * sellModifier ** 3 + 10); // Power of 3
// Adjust sell chance if below config value
@ -72,7 +72,8 @@ export class RagfairSellHelper
const startTime = this.timeUtil.getTimestamp();
// Get a time in future to stop simulating sell chances at
const endTime = startTime
const endTime
= startTime
+ this.timeUtil.getHoursAsSeconds(
this.databaseServer.getTables().globals.config.RagFair.offerDurationTimeInHour,
);

View File

@ -106,7 +106,8 @@ export class RagfairServerHelper
// Don't include damaged ammo packs
if (
this.ragfairConfig.dynamic.blacklist.damagedAmmoPacks && itemDetails[1]._parent === BaseClasses.AMMO_BOX
this.ragfairConfig.dynamic.blacklist.damagedAmmoPacks
&& itemDetails[1]._parent === BaseClasses.AMMO_BOX
&& itemDetails[1]._name.includes("_damaged")
)
{
@ -217,7 +218,7 @@ export class RagfairServerHelper
this.randomUtil.getInt(config.stackablePercent.min, config.stackablePercent.max),
);
return Math.round(maxStackCount / 100 * stackPercent);
return Math.round((maxStackCount / 100) * stackPercent);
}
/**

View File

@ -31,8 +31,8 @@ export class RepeatableQuestHelper
repeatableConfig: IRepeatableQuestConfig,
): IEliminationConfig
{
return repeatableConfig.questConfig.Elimination.find(x =>
pmcLevel >= x.levelRange.min && pmcLevel <= x.levelRange.max,
return repeatableConfig.questConfig.Elimination.find(
(x) => pmcLevel >= x.levelRange.min && pmcLevel <= x.levelRange.max,
);
}

View File

@ -23,7 +23,7 @@ export class SecureContainerHelper
*/
public getSecureContainerItems(items: Item[]): string[]
{
const secureContainer = items.find(x => x.slotId === "SecuredContainer");
const secureContainer = items.find((x) => x.slotId === "SecuredContainer");
// No container found, drop out
if (!secureContainer)
@ -34,6 +34,6 @@ export class SecureContainerHelper
const itemsInSecureContainer = this.itemHelper.findAndReturnChildrenByItems(items, secureContainer._id);
// Return all items returned and exclude the secure container item itself
return itemsInSecureContainer.filter(x => x !== secureContainer._id);
return itemsInSecureContainer.filter((x) => x !== secureContainer._id);
}
}

View File

@ -43,8 +43,8 @@ export class TradeHelper
@inject("InventoryHelper") protected inventoryHelper: InventoryHelper,
@inject("RagfairServer") protected ragfairServer: RagfairServer,
@inject("TraderAssortHelper") protected traderAssortHelper: TraderAssortHelper,
@inject("TraderPurchasePersisterService") protected traderPurchasePersisterService:
TraderPurchasePersisterService,
@inject("TraderPurchasePersisterService")
protected traderPurchasePersisterService: TraderPurchasePersisterService,
@inject("ConfigServer") protected configServer: ConfigServer,
@inject("RecursiveCloner") protected cloner: ICloner,
)
@ -79,7 +79,7 @@ export class TradeHelper
const allOffers = this.ragfairServer.getOffers();
// We store ragfair offerid in buyRequestData.item_id
const offerWithItem = allOffers.find(x => x._id === buyRequestData.item_id);
const offerWithItem = allOffers.find((x) => x._id === buyRequestData.item_id);
const itemPurchased = offerWithItem.items[0];
// Ensure purchase does not exceed trader item limit
@ -105,7 +105,7 @@ export class TradeHelper
// Get raw offer from ragfair, clone to prevent altering offer itself
const allOffers = this.ragfairServer.getOffers();
const offerWithItemCloned = this.cloner.clone(allOffers.find(x => x._id === buyRequestData.item_id));
const offerWithItemCloned = this.cloner.clone(allOffers.find((x) => x._id === buyRequestData.item_id));
offerItems = offerWithItemCloned.items;
}
else if (buyRequestData.tid === Traders.FENCE)
@ -114,7 +114,7 @@ export class TradeHelper
{
// Update assort/flea item values
const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(buyRequestData.tid).items;
const itemPurchased = traderAssorts.find(assort => assort._id === buyRequestData.item_id);
const itemPurchased = traderAssorts.find((assort) => assort._id === buyRequestData.item_id);
// Decrement trader item count
itemPurchased.upd.StackObjectsCount -= buyCount;
@ -123,7 +123,7 @@ export class TradeHelper
};
const fenceItems = this.fenceService.getRawFenceAssorts().items;
const rootItemIndex = fenceItems.findIndex(item => item._id === buyRequestData.item_id);
const rootItemIndex = fenceItems.findIndex((item) => item._id === buyRequestData.item_id);
if (rootItemIndex === -1)
{
this.logger.debug(`Tried to buy item ${buyRequestData.item_id} from fence that no longer exists`);
@ -142,7 +142,7 @@ export class TradeHelper
{
// Update assort/flea item values
const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(buyRequestData.tid).items;
const itemPurchased = traderAssorts.find(x => x._id === buyRequestData.item_id);
const itemPurchased = traderAssorts.find((x) => x._id === buyRequestData.item_id);
// Ensure purchase does not exceed trader item limit
const assortHasBuyRestrictions = this.itemHelper.hasBuyRestrictions(itemPurchased);
@ -260,7 +260,7 @@ export class TradeHelper
const itemIdToFind = itemToBeRemoved.id.replace(/\s+/g, ""); // Strip out whitespace
// Find item in player inventory, or show error to player if not found
const matchingItemInInventory = profileWithItemsToSell.Inventory.items.find(x => x._id === itemIdToFind);
const matchingItemInInventory = profileWithItemsToSell.Inventory.items.find((x) => x._id === itemIdToFind);
if (!matchingItemInInventory)
{
const errorMessage = `Unable to sell item ${itemToBeRemoved.id}, cannot be found in player inventory`;

View File

@ -40,8 +40,8 @@ export class TraderAssortHelper
@inject("RagfairOfferGenerator") protected ragfairOfferGenerator: RagfairOfferGenerator,
@inject("TraderAssortService") protected traderAssortService: TraderAssortService,
@inject("LocalisationService") protected localisationService: LocalisationService,
@inject("TraderPurchasePersisterService") protected traderPurchasePersisterService:
TraderPurchasePersisterService,
@inject("TraderPurchasePersisterService")
protected traderPurchasePersisterService: TraderPurchasePersisterService,
@inject("TraderHelper") protected traderHelper: TraderHelper,
@inject("FenceService") protected fenceService: FenceService,
@inject("ConfigServer") protected configServer: ConfigServer,
@ -95,7 +95,7 @@ export class TraderAssortHelper
for (const assortId in assortPurchasesfromTrader)
{
// Find assort we want to update current buy count of
const assortToAdjust = traderClone.assort.items.find(x => x._id === assortId);
const assortToAdjust = traderClone.assort.items.find((x) => x._id === assortId);
if (!assortToAdjust)
{
this.logger.debug(
@ -147,7 +147,7 @@ export class TraderAssortHelper
protected resetBuyRestrictionCurrentValue(assortItems: Item[]): void
{
// iterate over root items
for (const assort of assortItems.filter(item => item.slotId === "hideout"))
for (const assort of assortItems.filter((item) => item.slotId === "hideout"))
{
// no value to adjust
if (!assort.upd.BuyRestrictionCurrent)

View File

@ -108,7 +108,7 @@ export class TraderHelper
}
// Find specific assort in traders data
const purchasedAssort = traderAssorts.items.find(item => item._id === assortId);
const purchasedAssort = traderAssorts.items.find((item) => item._id === assortId);
if (!purchasedAssort)
{
this.logger.debug(`No assort ${assortId} on trader: ${traderId} found`);
@ -239,7 +239,8 @@ export class TraderHelper
if (
loyalty.minLevel <= pmcData.Info.Level
&& loyalty.minSalesSum <= pmcData.TradersInfo[traderID].salesSum
&& loyalty.minStanding <= pmcData.TradersInfo[traderID].standing && targetLevel < 4
&& loyalty.minStanding <= pmcData.TradersInfo[traderID].standing
&& targetLevel < 4
)
{
// level reached
@ -270,7 +271,7 @@ export class TraderHelper
*/
public getTraderUpdateSeconds(traderId: string): number
{
const traderDetails = this.traderConfig.updateTime.find(x => x.traderId === traderId);
const traderDetails = this.traderConfig.updateTime.find((x) => x.traderId === traderId);
if (!traderDetails || traderDetails.seconds.min === undefined || traderDetails.seconds.max === undefined)
{
this.logger.warning(
@ -280,7 +281,8 @@ export class TraderHelper
}),
);
this.traderConfig.updateTime.push( // create temporary entry to prevent logger spam
this.traderConfig.updateTime.push(
// create temporary entry to prevent logger spam
{
traderId: traderId,
seconds: { min: this.traderConfig.updateTimeDefault, max: this.traderConfig.updateTimeDefault },
@ -397,13 +399,14 @@ export class TraderHelper
}
// Get all item assorts that have parentid of hideout (base item and not a mod of other item)
for (const item of traderAssorts.items.filter(x => x.parentId === "hideout"))
for (const item of traderAssorts.items.filter((x) => x.parentId === "hideout"))
{
// Get barter scheme (contains cost of item)
const barterScheme = traderAssorts.barter_scheme[item._id][0][0];
// Convert into roubles
const roubleAmount = barterScheme._tpl === Money.ROUBLES
const roubleAmount
= barterScheme._tpl === Money.ROUBLES
? barterScheme.count
: this.handbookHelper.inRUB(barterScheme.count, barterScheme._tpl);
@ -478,7 +481,7 @@ export class TraderHelper
*/
public getTraderById(traderId: string): Traders
{
const keys = Object.keys(Traders).filter(x => Traders[x] === traderId);
const keys = Object.keys(Traders).filter((x) => Traders[x] === traderId);
if (keys.length === 0)
{
@ -523,7 +526,7 @@ export class TraderHelper
*/
public traderEnumHasKey(key: string): boolean
{
return Object.keys(Traders).some(x => x === key);
return Object.keys(Traders).some((x) => x === key);
}
/**
@ -533,6 +536,6 @@ export class TraderHelper
*/
public traderEnumHasValue(traderId: string): boolean
{
return Object.values(Traders).some(x => x === traderId);
return Object.values(Traders).some((x) => x === traderId);
}
}

View File

@ -5,6 +5,6 @@ export class UtilityHelper
{
public arrayIntersect<T>(a: T[], b: T[]): T[]
{
return a.filter(x => b.includes(x));
return a.filter((x) => b.includes(x));
}
}

View File

@ -58,7 +58,9 @@ export class BundleLoader
public addBundles(modpath: string): void
{
const bundleManifestArr = this.jsonUtil.deserialize<BundleManifest>(this.vfs.readFile(`${modpath}bundles.json`)).manifest;
const bundleManifestArr = this.jsonUtil.deserialize<BundleManifest>(
this.vfs.readFile(`${modpath}bundles.json`),
).manifest;
for (const bundleManifest of bundleManifestArr)
{

View File

@ -69,11 +69,13 @@ export class ModTypeCheck
*/
public isPostV3Compatible(mod: any): boolean
{
return this.isPreAkiLoad(mod)
return (
this.isPreAkiLoad(mod)
|| this.isPostAkiLoad(mod)
|| this.isPostDBAkiLoad(mod)
|| this.isPreAkiLoadAsync(mod)
|| this.isPostAkiLoadAsync(mod)
|| this.isPostDBAkiLoadAsync(mod);
|| this.isPostDBAkiLoadAsync(mod)
);
}
}

View File

@ -93,10 +93,10 @@ export class PreAkiModLoader implements IModLoader
for (const modName in modsGroupedByName)
{
const modDatas = modsGroupedByName[modName];
const modVersions = modDatas.map(x => x.version);
const modVersions = modDatas.map((x) => x.version);
const highestVersion = maxSatisfying(modVersions, "*");
const chosenVersion = modDatas.find(x => x.name === modName && x.version === highestVersion);
const chosenVersion = modDatas.find((x) => x.name === modName && x.version === highestVersion);
if (!chosenVersion)
{
continue;
@ -174,7 +174,8 @@ export class PreAkiModLoader implements IModLoader
// if the mod has library dependencies check if these dependencies are bundled in the server, if not install them
if (
modToValidate.dependencies && Object.keys(modToValidate.dependencies).length > 0
modToValidate.dependencies
&& Object.keys(modToValidate.dependencies).length > 0
&& !this.vfs.exists(`${this.basepath}${modFolderName}/node_modules`)
)
{
@ -267,7 +268,7 @@ export class PreAkiModLoader implements IModLoader
for (const mod of modPackageData.values())
{
const name = `${mod.author}-${mod.name}`;
grouppedMods.set(name, [...grouppedMods.get(name) ?? [], mod]);
grouppedMods.set(name, [...(grouppedMods.get(name) ?? []), mod]);
// if there's more than one entry for a given mod it means there's at least 2 mods with the same author and name trying to load.
if (grouppedMods.get(name).length > 1 && !this.skippedMods.has(name))
@ -641,7 +642,7 @@ export class PreAkiModLoader implements IModLoader
const modIsCalledSrc = modName.toLowerCase() === "src";
const modIsCalledDb = modName.toLowerCase() === "db";
const hasBepinExFolderStructure = this.vfs.exists(`${modPath}/plugins`);
const containsDll = this.vfs.getFiles(`${modPath}`).find(x => x.includes(".dll"));
const containsDll = this.vfs.getFiles(`${modPath}`).find((x) => x.includes(".dll"));
if (modIsCalledSrc || modIsCalledDb || modIsCalledUser)
{
@ -691,7 +692,8 @@ export class PreAkiModLoader implements IModLoader
if ("main" in config)
{
if (config.main.split(".").pop() !== "js")
{ // expects js file as entry
{
// expects js file as entry
this.logger.error(this.localisationService.getText("modloader-main_property_not_js", modName));
issue = true;
}

View File

@ -1,3 +1,2 @@
export interface IEmptyRequestData
{
}
{}

View File

@ -386,9 +386,9 @@ export interface Productive
ProductionTime?: number
GivenItemsInStart?: string[]
Interrupted?: boolean
Code?: string;
Decoded?: boolean;
AvailableForFinish?: boolean;
Code?: string
Decoded?: boolean
AvailableForFinish?: boolean
/** Used in hideout production.json */
needFuelForAllProductionTime?: boolean
/** Used when sending data to client */
@ -459,8 +459,7 @@ export interface Notes
}
export interface CarExtractCounts
{
}
{}
export enum SurvivorClass
{

View File

@ -1,14 +1,11 @@
export interface IAcceptFriendRequestData extends IBaseFriendRequest
{
}
{}
export interface ICancelFriendRequestData extends IBaseFriendRequest
{
}
{}
export interface IDeclineFriendRequestData extends IBaseFriendRequest
{
}
{}
export interface IBaseFriendRequest
{

View File

@ -1,5 +1,5 @@
export interface IAddUserGroupMailRequest
{
dialogId: string;
uid: string;
dialogId: string
uid: string
}

View File

@ -1,5 +1,5 @@
export interface IChangeGroupMailOwnerRequest
{
dialogId: string;
uid: string;
dialogId: string
uid: string
}

View File

@ -1,5 +1,5 @@
export interface ICreateGroupMailRequest
{
Name: string;
Users: string[];
Name: string
Users: string[]
}

View File

@ -1,5 +1,5 @@
export interface IRemoveUserGroupMailRequest
{
dialogId: string;
uid: string;
dialogId: string
uid: string
}

View File

@ -17,8 +17,7 @@ export interface IQteData
area: HideoutAreas
areaLevel: number
quickTimeEvents: IQuickTimeEvent[]
requirements:
(
requirements: (
| IAreaRequirement
| IItemRequirement
| ITraderUnlockRequirement

View File

@ -1,8 +1,7 @@
import { IBaseInteractionRequestData } from "@spt-aki/models/eft/common/request/IBaseInteractionRequestData";
export interface IInventoryBaseActionRequestData extends IBaseInteractionRequestData
{
}
{}
export interface To
{

View File

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

View File

@ -1,6 +1,4 @@
import { IWsNotificationEvent } from "@spt-aki/models/eft/ws/IWsNotificationEvent";
export interface IWsPing extends IWsNotificationEvent
{
}
{}

View File

@ -1,5 +1,5 @@
export enum MemberCategory // player type
{
export enum MemberCategory
{ // player type
DEFAULT = 0,
DEVELOPER = 1,
UNIQUE_ID = 2,

View File

@ -10,5 +10,5 @@ export enum QuestRewardType
TRADER_STANDING_RESET = "TraderStandingReset",
TRADER_STANDING_RESTORE = "TraderStandingRestore",
STASH_ROWS = "StashRows",
ACHIEVEMENT = "Achievement"
ACHIEVEMENT = "Achievement",
}

View File

@ -61,8 +61,10 @@ export const Listen = (basePath: string) =>
{
const routesHandles = this.handlers[req.method];
return Object.keys(this.handlers).some(meth => meth === req.method)
&& Object.keys(routesHandles).some(route => new RegExp(route).test(req.url));
return (
Object.keys(this.handlers).some((meth) => meth === req.method)
&& Object.keys(routesHandles).some((route) => new RegExp(route).test(req.url))
);
};
// The actual handle method dispatches the request to the registered handlers
@ -81,7 +83,7 @@ export const Listen = (basePath: string) =>
routes.sort((routeA, routeB) => routeB.length - routeA.length);
// Filter to select valid routes but only use the first element since it's the most precise
const validRoutes = routes.filter(handlerKey => new RegExp(handlerKey).test(route));
const validRoutes = routes.filter((handlerKey) => new RegExp(handlerKey).test(route));
if (validRoutes.length > 0)
{
routesHandles[validRoutes[0]](sessionID, req, resp);

View File

@ -5,7 +5,11 @@ export class ExhaustableArray<T> implements IExhaustableArray<T>
{
private pool: T[];
constructor(private itemPool: T[], private randomUtil: RandomUtil, private cloner: ICloner)
constructor(
private itemPool: T[],
private randomUtil: RandomUtil,
private cloner: ICloner,
)
{
this.pool = this.cloner.clone(itemPool);
}

View File

@ -47,7 +47,7 @@ export class HttpRouter
}
// TODO: Temporary hack to change ItemEventRouter response sessionID binding to what client expects
if (wrapper.output?.includes("\"profileChanges\":{"))
if (wrapper.output?.includes('"profileChanges":{'))
{
wrapper.output = wrapper.output.replace(sessionID, sessionID);
}

View File

@ -34,7 +34,7 @@ export class ItemEventRouter
{
const pmcData = this.profileHelper.getPmcProfile(sessionID);
const eventRouter = this.itemEventRouters.find(r => r.canHandle(body.Action));
const eventRouter = this.itemEventRouters.find((r) => r.canHandle(body.Action));
if (eventRouter)
{
this.logger.debug(`event: ${body.Action}`);

View File

@ -13,7 +13,8 @@ export class HealthSaveLoadRouter extends SaveLoadRouter
public override handleLoad(profile: IAkiProfile): IAkiProfile
{
if (!profile.vitality)
{ // Occurs on newly created profiles
{
// Occurs on newly created profiles
profile.vitality = { health: null, effects: null };
}
profile.vitality.health = {

View File

@ -26,9 +26,10 @@ export class NotifySerializer extends Serializer
* Take our array of JSON message objects and cast them to JSON strings, so that they can then
* be sent to client as NEWLINE separated strings... yup.
*/
this.notifierController.notifyAsync(tmpSessionID).then((messages: any) =>
messages.map((message: any) => this.jsonUtil.serialize(message)).join("\n"),
).then(text => this.httpServerHelper.sendTextJson(resp, text));
this.notifierController
.notifyAsync(tmpSessionID)
.then((messages: any) => messages.map((message: any) => this.jsonUtil.serialize(message)).join("\n"))
.then((text) => this.httpServerHelper.sendTextJson(resp, text));
}
public override canHandle(route: string): boolean

View File

@ -160,7 +160,12 @@ export class MatchStaticRouter extends StaticRouter
),
new RouteAction(
"/client/match/group/invite/decline",
async (url: string, info: any, sessionID: string, output: string): Promise<IGetBodyResponseData<any>> =>
async (
url: string,
info: any,
sessionID: string,
output: string,
): Promise<IGetBodyResponseData<any>> =>
{
return this.matchCallbacks.declineGroupInvite(url, info, sessionID);
},

View File

@ -60,14 +60,24 @@ export class ProfileStaticRouter extends StaticRouter
),
new RouteAction(
"/client/game/profile/nickname/change",
async (url: string, info: any, sessionID: string, output: string): Promise<IGetBodyResponseData<any>> =>
async (
url: string,
info: any,
sessionID: string,
output: string,
): Promise<IGetBodyResponseData<any>> =>
{
return this.profileCallbacks.changeNickname(url, info, sessionID);
},
),
new RouteAction(
"/client/game/profile/nickname/validate",
async (url: string, info: any, sessionID: string, output: string): Promise<IGetBodyResponseData<any>> =>
async (
url: string,
info: any,
sessionID: string,
output: string,
): Promise<IGetBodyResponseData<any>> =>
{
return this.profileCallbacks.validateNickname(url, info, sessionID);
},

View File

@ -1,6 +1,5 @@
import { inject, injectable } from "tsyringe";
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
import { ICoreConfig } from "@spt-aki/models/spt/config/ICoreConfig";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { VFS } from "@spt-aki/utils/VFS";

View File

@ -95,10 +95,12 @@ export class HttpServer
}
else
{
this.logger.info(this.localisationService.getText("client_request_ip", {
this.logger.info(
this.localisationService.getText("client_request_ip", {
ip: clientIp,
url: req.url.replaceAll("/", "\\"), // Localisation service escapes `/` into hex code `&#x2f;`
}));
}),
);
}
}
}
@ -125,9 +127,11 @@ export class HttpServer
return undefined;
}
return remoteAddress.startsWith("127.0.0")
return (
remoteAddress.startsWith("127.0.0")
|| remoteAddress.startsWith("192.168.")
|| remoteAddress.startsWith("localhost");
|| remoteAddress.startsWith("localhost")
);
}
protected getCookies(req: IncomingMessage): Record<string, string>

View File

@ -79,7 +79,7 @@ export class RagfairServer
*/
public getUpdateableTraders(): string[]
{
return Object.keys(this.ragfairConfig.traders).filter(x => this.ragfairConfig.traders[x]);
return Object.keys(this.ragfairConfig.traders).filter((x) => this.ragfairConfig.traders[x]);
}
public getAllActiveCategories(
@ -98,7 +98,7 @@ export class RagfairServer
public hideOffer(offerId: string): void
{
const offers = this.ragfairOfferService.getOffers();
const offer = offers.find(x => x._id === offerId);
const offer = offers.find((x) => x._id === offerId);
if (!offer)
{

View File

@ -21,8 +21,7 @@ export class AkiHttpListener implements IHttpListener
@inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil,
@inject("LocalisationService") protected localisationService: LocalisationService,
)
{
}
{}
public canHandle(_: string, req: IncomingMessage): boolean
{
@ -153,7 +152,7 @@ export class AkiHttpListener 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(null, 404, `UNHANDLED RESPONSE: ${req.url}`));
}
return output;
}
@ -180,18 +179,28 @@ export class AkiHttpListener implements IHttpListener
class RequestData
{
constructor(public url: string, public headers: IncomingHttpHeaders, public data?: any)
constructor(
public url: string,
public headers: IncomingHttpHeaders,
public data?: any,
)
{}
}
class Request
{
constructor(public type: string, public req: RequestData)
constructor(
public type: string,
public req: RequestData,
)
{}
}
class Response
{
constructor(public type: string, public response: any)
constructor(
public type: string,
public response: any,
)
{}
}

View File

@ -99,7 +99,10 @@ export class BotEquipmentFilterService
* @param equipmentChanges Changes to apply
* @param baseValues data to update
*/
protected adjustChances(equipmentChanges: Record<string, number>, baseValues: EquipmentChances | ModsChances): void
protected adjustChances(
equipmentChanges: Record<string, number>,
baseValues: EquipmentChances | ModsChances,
): void
{
if (!equipmentChanges)
{
@ -173,15 +176,16 @@ export class BotEquipmentFilterService
// No equipment blacklist found, skip
if (
!blacklistDetailsForBot || Object.keys(blacklistDetailsForBot).length === 0
!blacklistDetailsForBot
|| Object.keys(blacklistDetailsForBot).length === 0
|| !blacklistDetailsForBot.blacklist
)
{
return null;
}
return blacklistDetailsForBot.blacklist.find(x =>
playerLevel >= x.levelRange.min && playerLevel <= x.levelRange.max,
return blacklistDetailsForBot.blacklist.find(
(x) => playerLevel >= x.levelRange.min && playerLevel <= x.levelRange.max,
);
}
@ -201,8 +205,8 @@ export class BotEquipmentFilterService
return null;
}
return botEquipmentConfig.whitelist.find(x =>
playerLevel >= x.levelRange.min && playerLevel <= x.levelRange.max,
return botEquipmentConfig.whitelist.find(
(x) => playerLevel >= x.levelRange.min && playerLevel <= x.levelRange.max,
);
}
@ -218,15 +222,16 @@ export class BotEquipmentFilterService
// No config found, skip
if (
!botEquipmentConfig || Object.keys(botEquipmentConfig).length === 0
!botEquipmentConfig
|| Object.keys(botEquipmentConfig).length === 0
|| !botEquipmentConfig.weightingAdjustmentsByBotLevel
)
{
return null;
}
return botEquipmentConfig.weightingAdjustmentsByBotLevel.find(x =>
botLevel >= x.levelRange.min && botLevel <= x.levelRange.max,
return botEquipmentConfig.weightingAdjustmentsByBotLevel.find(
(x) => botLevel >= x.levelRange.min && botLevel <= x.levelRange.max,
);
}
@ -236,21 +241,25 @@ export class BotEquipmentFilterService
* @param playerlevel Level of bot
* @returns Weighting adjustments for bot items
*/
protected getBotWeightingAdjustmentsByPlayerLevel(botRole: string, playerlevel: number): WeightingAdjustmentDetails
protected getBotWeightingAdjustmentsByPlayerLevel(
botRole: string,
playerlevel: number,
): WeightingAdjustmentDetails
{
const botEquipmentConfig = this.botEquipmentConfig[botRole];
// No config found, skip
if (
!botEquipmentConfig || Object.keys(botEquipmentConfig).length === 0
!botEquipmentConfig
|| Object.keys(botEquipmentConfig).length === 0
|| !botEquipmentConfig.weightingAdjustmentsByPlayerLevel
)
{
return null;
}
return botEquipmentConfig.weightingAdjustmentsByPlayerLevel.find(x =>
playerlevel >= x.levelRange.min && playerlevel <= x.levelRange.max,
return botEquipmentConfig.weightingAdjustmentsByPlayerLevel.find(
(x) => playerlevel >= x.levelRange.min && playerlevel <= x.levelRange.max,
);
}

View File

@ -91,7 +91,7 @@ export class BotEquipmentModPoolService
}
// only add item to pool if it doesnt already exist
if (!pool[item._id][slot._name].some(x => x === itemToAdd))
if (!pool[item._id][slot._name].some((x) => x === itemToAdd))
{
pool[item._id][slot._name].push(itemToAdd);
@ -185,8 +185,8 @@ export class BotEquipmentModPoolService
*/
protected generateWeaponPool(): void
{
const weapons = Object.values(this.databaseServer.getTables().templates.items).filter(x =>
x._type === "Item" && this.itemHelper.isOfBaseclass(x._id, BaseClasses.WEAPON),
const weapons = Object.values(this.databaseServer.getTables().templates.items).filter(
(x) => x._type === "Item" && this.itemHelper.isOfBaseclass(x._id, BaseClasses.WEAPON),
);
this.generatePool(weapons, "weapon");
@ -199,7 +199,8 @@ export class BotEquipmentModPoolService
*/
protected generateGearPool(): void
{
const gear = Object.values(this.databaseServer.getTables().templates.items).filter(x =>
const gear = Object.values(this.databaseServer.getTables().templates.items).filter(
(x) =>
x._type === "Item"
&& this.itemHelper.isOfBaseclasses(x._id, [
BaseClasses.ARMORED_EQUIPMENT,

View File

@ -79,7 +79,7 @@ export class BotGenerationCacheService
*/
public getUsedBot(profileId: string): IBotBase
{
return this.activeBotsInRaid.find(x => x._id === profileId);
return this.activeBotsInRaid.find((x) => x._id === profileId);
}
/**

View File

@ -90,7 +90,7 @@ export class BotWeaponModLimitService
{
// If weapon already has a longer ranged scope on it, allow ncstar to be spawned
if (
weapon.some(x =>
weapon.some((x) =>
this.itemHelper.isOfBaseclasses(x._tpl, [
BaseClasses.ASSAULT_SCOPE,
BaseClasses.OPTIC_SCOPE,
@ -121,7 +121,7 @@ export class BotWeaponModLimitService
// Mod is a mount that can hold only scopes and limit is reached (dont want to add empty mounts if limit is reached)
if (
this.itemHelper.isOfBaseclass(modTemplate._id, BaseClasses.MOUNT)
&& modTemplate._props.Slots.some(x => x._name === "mod_scope")
&& modTemplate._props.Slots.some((x) => x._name === "mod_scope")
&& modTemplate._props.Slots.length === 1
&& modLimits.scope.count >= modLimits.scopeMax
)
@ -144,7 +144,7 @@ export class BotWeaponModLimitService
// Mod is a mount that can hold only flashlights ad limit is reached (dont want to add empty mounts if limit is reached)
if (
this.itemHelper.isOfBaseclass(modTemplate._id, BaseClasses.MOUNT)
&& modTemplate._props.Slots.some(x => x._name === "mod_flashlight")
&& modTemplate._props.Slots.some((x) => x._name === "mod_flashlight")
&& modTemplate._props.Slots.length === 1
&& modLimits.scope.count >= modLimits.scopeMax
)

View File

@ -73,7 +73,7 @@ export class CustomLocationWaveService
const location: ILocationBase = this.databaseServer.getTables().locations[mapKey].base;
for (const bossWave of bossWavesToApply[mapKey])
{
if (location.BossLocationSpawn.find(x => x.sptId === bossWave.sptId))
if (location.BossLocationSpawn.find((x) => x.sptId === bossWave.sptId))
{
// Already exists, skip
continue;
@ -90,7 +90,7 @@ export class CustomLocationWaveService
const location: ILocationBase = this.databaseServer.getTables().locations[mapKey].base;
for (const normalWave of normalWavesToApply[mapKey])
{
if (location.waves.find(x => x.sptId === normalWave.sptId))
if (location.waves.find((x) => x.sptId === normalWave.sptId))
{
// Already exists, skip
continue;

View File

@ -388,23 +388,28 @@ export class FenceService
* @param newFenceAssorts Assorts to fold into existing fence assorts
* @param existingFenceAssorts Current fence assorts new assorts will be added to
*/
protected updateFenceAssorts(newFenceAssorts: ICreateFenceAssortsResult, existingFenceAssorts: ITraderAssort): void
protected updateFenceAssorts(
newFenceAssorts: ICreateFenceAssortsResult,
existingFenceAssorts: ITraderAssort,
): void
{
for (const itemWithChildren of newFenceAssorts.sptItems)
{
// Find the root item
const newRootItem = itemWithChildren.find(item => item.slotId === "hideout");
const newRootItem = itemWithChildren.find((item) => item.slotId === "hideout");
if (!newRootItem)
{
const firstItem = itemWithChildren.find(x => x);
this.logger.error(`Unable to process fence assort as root item is missing, ${firstItem?._tpl}, skipping`);
const firstItem = itemWithChildren.find((x) => x);
this.logger.error(
`Unable to process fence assort as root item is missing, ${firstItem?._tpl}, skipping`,
);
continue;
}
// Find a matching root item with same tpl in existing assort
const existingRootItem = existingFenceAssorts.items.find(item =>
item._tpl === newRootItem._tpl && item.slotId === "hideout",
const existingRootItem = existingFenceAssorts.items.find(
(item) => item._tpl === newRootItem._tpl && item.slotId === "hideout",
);
// Check if same type of item exists + its on list of item types to always stack
@ -453,8 +458,8 @@ export class FenceService
*/
protected incrementPartialRefreshTime(): void
{
this.nextPartialRefreshTimestamp = this.timeUtil.getTimestamp()
+ this.traderConfig.fence.partialRefreshTimeSeconds;
this.nextPartialRefreshTimestamp
= this.timeUtil.getTimestamp() + this.traderConfig.fence.partialRefreshTimeSeconds;
}
/**
@ -468,8 +473,8 @@ export class FenceService
generationValues: IGenerationAssortValues,
): IGenerationAssortValues
{
const allRootItems = assortItems.filter(item => item.slotId === "hideout");
const rootPresetItems = allRootItems.filter(item => item?.upd?.sptPresetId);
const allRootItems = assortItems.filter((item) => item.slotId === "hideout");
const rootPresetItems = allRootItems.filter((item) => item?.upd?.sptPresetId);
// Get count of weapons
const currentWeaponPresetCount = rootPresetItems.reduce((count, item) =>
@ -507,7 +512,7 @@ export class FenceService
{
if (assort?.items?.length > 0)
{
const rootItems = assort.items.filter(item => item.slotId === "hideout");
const rootItems = assort.items.filter((item) => item.slotId === "hideout");
for (let index = 0; index < itemCountToReplace; index++)
{
this.removeRandomItemFromAssorts(assort, rootItems);
@ -735,8 +740,8 @@ export class FenceService
): void
{
const priceLimits = this.traderConfig.fence.itemCategoryRoublePriceLimit;
const assortRootItems = baseFenceAssortClone.items.filter(item =>
item.parentId === "hideout" && !item.upd?.sptPresetId,
const assortRootItems = baseFenceAssortClone.items.filter(
(item) => item.parentId === "hideout" && !item.upd?.sptPresetId,
);
for (let i = 0; i < assortCount; i++)
@ -806,7 +811,8 @@ export class FenceService
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
{
// Decrement loop counter so another items gets added
i--;
existingItemThatMatches.upd.StackObjectsCount++;
@ -843,12 +849,18 @@ export class FenceService
* @param itemsWithChildren Items to search through
* @returns Matching assort item
*/
protected getMatchingItem(rootItemBeingAdded: Item, itemDbDetails: ITemplateItem, itemsWithChildren: Item[][]): Item
protected getMatchingItem(
rootItemBeingAdded: Item,
itemDbDetails: ITemplateItem,
itemsWithChildren: Item[][],
): Item
{
// Get matching root items
const matchingItems = itemsWithChildren.filter(itemWithChildren =>
itemWithChildren.find(item => item._tpl === rootItemBeingAdded._tpl && item.parentId === "hideout"),
).flatMap(x => x);
const matchingItems = itemsWithChildren
.filter((itemWithChildren) =>
itemWithChildren.find((item) => item._tpl === rootItemBeingAdded._tpl && item.parentId === "hideout"),
)
.flatMap((x) => x);
if (matchingItems.length === 0)
{
// Nothing matches by tpl and is root item, exit early
@ -998,8 +1010,8 @@ export class FenceService
let weaponPresetsAddedCount = 0;
if (desiredWeaponPresetsCount > 0)
{
const weaponPresetRootItems = baseFenceAssort.items.filter(item =>
item.upd?.sptPresetId && this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.WEAPON),
const weaponPresetRootItems = baseFenceAssort.items.filter(
(item) => item.upd?.sptPresetId && this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.WEAPON),
);
while (weaponPresetsAddedCount < desiredWeaponPresetsCount)
{
@ -1021,7 +1033,8 @@ export class FenceService
// Check chosen item is below price cap
const priceLimitRouble = this.traderConfig.fence.itemCategoryRoublePriceLimit[rootItemDb._parent];
const itemPrice = this.handbookHelper.getTemplatePriceForItems(presetWithChildrenClone)
const itemPrice
= this.handbookHelper.getTemplatePriceForItems(presetWithChildrenClone)
* this.itemHelper.getItemQualityModifierForOfferItems(presetWithChildrenClone);
if (priceLimitRouble)
{
@ -1043,10 +1056,14 @@ export class FenceService
// Set assort price
// Must be careful to use correct id as the item has had its IDs regenerated
assorts.barter_scheme[presetWithChildrenClone[0]._id] = [[{
assorts.barter_scheme[presetWithChildrenClone[0]._id] = [
[
{
_tpl: "5449016a4bdc2d6f028b456f",
count: Math.round(itemPrice),
}]];
},
],
];
assorts.loyal_level_items[presetWithChildrenClone[0]._id] = loyaltyLevel;
weaponPresetsAddedCount++;
@ -1059,8 +1076,8 @@ export class FenceService
return;
}
const equipmentPresetRootItems = baseFenceAssort.items.filter(item =>
item.upd?.sptPresetId && this.itemHelper.armorItemCanHoldMods(item._tpl),
const equipmentPresetRootItems = baseFenceAssort.items.filter(
(item) => item.upd?.sptPresetId && this.itemHelper.armorItemCanHoldMods(item._tpl),
);
while (equipmentPresetsAddedCount < desiredEquipmentPresetsCount)
{
@ -1081,7 +1098,8 @@ export class FenceService
// Check chosen item is below price cap
const priceLimitRouble = this.traderConfig.fence.itemCategoryRoublePriceLimit[rootItemDb._parent];
const itemPrice = this.handbookHelper.getTemplatePriceForItems(presetWithChildrenClone)
const itemPrice
= this.handbookHelper.getTemplatePriceForItems(presetWithChildrenClone)
* this.itemHelper.getItemQualityModifierForOfferItems(presetWithChildrenClone);
if (priceLimitRouble)
{
@ -1103,10 +1121,14 @@ export class FenceService
// Set assort price
// Must be careful to use correct id as the item has had its IDs regenerated
assorts.barter_scheme[presetWithChildrenClone[0]._id] = [[{
assorts.barter_scheme[presetWithChildrenClone[0]._id] = [
[
{
_tpl: "5449016a4bdc2d6f028b456f",
count: Math.round(itemPrice),
}]];
},
],
];
assorts.loyal_level_items[presetWithChildrenClone[0]._id] = loyaltyLevel;
equipmentPresetsAddedCount++;
@ -1128,7 +1150,7 @@ export class FenceService
}
// Check for and adjust soft insert durability values
const requiredSlots = itemDbDetails._props.Slots.filter(slot => slot._required);
const requiredSlots = itemDbDetails._props.Slots.filter((slot) => slot._required);
const hasRequiredSlots = requiredSlots.length > 0;
if (hasRequiredSlots)
{
@ -1147,8 +1169,8 @@ export class FenceService
}
// Find items mod to apply dura changes to
const modItemToAdjust = armor.find(mod =>
mod.slotId.toLowerCase() === requiredSlot._name.toLowerCase(),
const modItemToAdjust = armor.find(
(mod) => mod.slotId.toLowerCase() === requiredSlot._name.toLowerCase(),
);
this.itemHelper.addUpdObjectToItem(modItemToAdjust);
@ -1170,14 +1192,15 @@ export class FenceService
&& modItemToAdjust.slotId === "mod_equipment_000"
&& modItemToAdjust.upd.Repairable.Durability < modItemDbDetails._props.MaxDurability
)
{ // Is damaged
{
// Is damaged
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)
@ -1203,7 +1226,7 @@ export class FenceService
);
// Find items mod to apply dura changes to
const modItemToAdjust = armor.find(mod => mod.slotId.toLowerCase() === plateSlot._name.toLowerCase());
const modItemToAdjust = armor.find((mod) => mod.slotId.toLowerCase() === plateSlot._name.toLowerCase());
this.itemHelper.addUpdObjectToItem(modItemToAdjust);
if (!modItemToAdjust.upd.Repairable)
@ -1341,7 +1364,8 @@ export class FenceService
if (
(itemDetails._parent === BaseClasses.ARMORED_EQUIPMENT
|| itemDetails._parent === BaseClasses.FACECOVER
|| itemDetails._parent === BaseClasses.ARMOR_PLATE) && itemDetails._props.MaxDurability > 0
|| itemDetails._parent === BaseClasses.ARMOR_PLATE)
&& itemDetails._props.MaxDurability > 0
)
{
const values = this.getRandomisedArmorDurabilityValues(
@ -1357,12 +1381,12 @@ 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,
@ -1414,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,
@ -1462,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);
}
@ -1482,7 +1506,7 @@ export class FenceService
return fenceSettings.Levels["0"];
}
const fenceLevels = Object.keys(fenceSettings.Levels).map(value => Number.parseInt(value));
const fenceLevels = Object.keys(fenceSettings.Levels).map((value) => Number.parseInt(value));
const minLevel = Math.min(...fenceLevels);
const maxLevel = Math.max(...fenceLevels);
const pmcFenceLevel = Math.floor(pmcFenceInfo.standing);
@ -1508,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(`Offer with id: ${assortId} not found`);
@ -1540,12 +1564,12 @@ export class FenceService
const itemWithChildrenToRemove = this.itemHelper.findAndReturnChildrenAsItems(assorts, assortId);
for (const itemToRemove of itemWithChildrenToRemove)
{
let indexToRemove = assorts.findIndex(item => item._id === itemToRemove._id);
let indexToRemove = assorts.findIndex((item) => item._id === itemToRemove._id);
// No offer found in main assort, check discount items
if (indexToRemove === -1)
{
indexToRemove = this.fenceDiscountAssort.items.findIndex(item => item._id === itemToRemove._id);
indexToRemove = this.fenceDiscountAssort.items.findIndex((item) => item._id === itemToRemove._id);
this.fenceDiscountAssort.items.splice(indexToRemove, 1);
if (indexToRemove === -1)

View File

@ -120,7 +120,9 @@ export class InsuranceService
MessageType.NPC_TRADER,
this.randomUtil.getArrayValue(dialogueTemplates.insuranceStart),
null,
this.timeUtil.getHoursAsSeconds(this.databaseServer.getTables().globals.config.Insurance.MaxStorageTimeInHour),
this.timeUtil.getHoursAsSeconds(
this.databaseServer.getTables().globals.config.Insurance.MaxStorageTimeInHour,
),
systemData,
);
@ -151,7 +153,7 @@ export class InsuranceService
for (const insuredItem of this.getInsurance(sessionId)[traderId])
{
// Find insured items parent
const insuredItemsParent = insuredItems.find(x => x._id === insuredItem.parentId);
const insuredItemsParent = insuredItems.find((x) => x._id === insuredItem.parentId);
if (!insuredItemsParent)
{
// Remove location + set slotId of insured items parent
@ -179,9 +181,9 @@ export class InsuranceService
return this.timeUtil.getTimestamp() + this.insuranceConfig.returnTimeOverrideSeconds;
}
const insuranceReturnTimeBonus = pmcData.Bonuses.find(b => b.type === BonusType.INSURANCE_RETURN_TIME);
const insuranceReturnTimeBonusPercent = 1.0
- (insuranceReturnTimeBonus ? Math.abs(insuranceReturnTimeBonus.value) : 0) / 100;
const insuranceReturnTimeBonus = pmcData.Bonuses.find((b) => b.type === BonusType.INSURANCE_RETURN_TIME);
const insuranceReturnTimeBonusPercent
= 1.0 - (insuranceReturnTimeBonus ? Math.abs(insuranceReturnTimeBonus.value) : 0) / 100;
const traderMinReturnAsSeconds = trader.insurance.min_return_hour * TimeUtil.ONE_HOUR_AS_SECONDS;
const traderMaxReturnAsSeconds = trader.insurance.max_return_hour * TimeUtil.ONE_HOUR_AS_SECONDS;
@ -256,7 +258,7 @@ export class InsuranceService
itemToReturnToPlayer: this.getInsuredItemDetails(
pmcData,
preRaidItem,
offraidData.insurance?.find(insuranceItem => insuranceItem.id === insuredItem.itemId),
offraidData.insurance?.find((insuranceItem) => insuranceItem.id === insuredItem.itemId),
),
traderId: insuredItem.tid,
sessionID: sessionID,
@ -268,10 +270,13 @@ export class InsuranceService
if (this.itemHelper.itemHasSlots(preRaidItem._tpl))
{
// Get IDs of all soft insert child items on armor from pre raid gear data
const softInsertChildIds = preRaidGear.filter(item =>
const softInsertChildIds = preRaidGear
.filter(
(item) =>
item.parentId === preRaidItem._id
&& this.itemHelper.getSoftInsertSlotIds().includes(item.slotId.toLowerCase()),
).map(x => x._id);
)
.map((x) => x._id);
// Add all items found above to return data
for (const softInsertChildModId of softInsertChildIds)
@ -280,9 +285,9 @@ export class InsuranceService
pmcData: pmcData,
itemToReturnToPlayer: this.getInsuredItemDetails(
pmcData,
preRaidGear.find(item => item._id === softInsertChildModId),
offraidData.insurance?.find(insuranceItem =>
insuranceItem.id === softInsertChildModId,
preRaidGear.find((item) => item._id === softInsertChildModId),
offraidData.insurance?.find(
(insuranceItem) => insuranceItem.id === softInsertChildModId,
),
),
traderId: insuredItem.tid,

View File

@ -1,6 +1,5 @@
import { inject, injectable } from "tsyringe";
import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem";
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
@ -39,7 +38,7 @@ export class ItemBaseClassService
return;
}
const filteredDbItems = Object.values(this.items).filter(x => x._type === "Item");
const filteredDbItems = Object.values(this.items).filter((x) => x._type === "Item");
for (const item of filteredDbItems)
{
const itemIdToUpdate = item._id;
@ -111,7 +110,7 @@ export class ItemBaseClassService
}
}
return this.itemBaseClassesCache[itemTpl].some(x => baseClasses.includes(x));
return this.itemBaseClassesCache[itemTpl].some((x) => baseClasses.includes(x));
}
/**

View File

@ -1,7 +1,6 @@
import path from "node:path";
import { I18n } from "i18n";
import { inject, injectable } from "tsyringe";
import { ILocaleConfig } from "@spt-aki/models/spt/config/ILocaleConfig";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import { LocaleService } from "@spt-aki/services/LocaleService";
@ -66,7 +65,7 @@ export class LocalisationService
*/
public getRandomTextThatMatchesPartialKey(partialKey: string): string
{
const filteredKeys = Object.keys(this.databaseServer.getTables().locales.server.en).filter(x =>
const filteredKeys = Object.keys(this.databaseServer.getTables().locales.server.en).filter((x) =>
x.startsWith(partialKey),
);
const chosenKey = this.randomUtil.getArrayValue(filteredKeys);

View File

@ -365,9 +365,8 @@ export class MailSendService
hasRewards: false, // The default dialog message has no rewards, can be added later via addRewardItemsToMessage()
rewardCollected: false, // The default dialog message has no rewards, can be added later via addRewardItemsToMessage()
systemData: messageDetails.systemData ? messageDetails.systemData : undefined, // Used by ragfair / localised messages that need "location" or "time"
profileChangeEvents: messageDetails.profileChangeEvents?.length === 0
? messageDetails.profileChangeEvents
: undefined, // no one knows, its never been used in any dumps
profileChangeEvents:
messageDetails.profileChangeEvents?.length === 0 ? messageDetails.profileChangeEvents : undefined, // no one knows, its never been used in any dumps
};
// Clean up empty system data
@ -412,7 +411,10 @@ export class MailSendService
* @param messageDetails
* @returns Sanitised items
*/
protected processItemsBeforeAddingToMail(dialogType: MessageType, messageDetails: ISendMessageDetails): MessageItems
protected processItemsBeforeAddingToMail(
dialogType: MessageType,
messageDetails: ISendMessageDetails,
): MessageItems
{
const db = this.databaseServer.getTables().templates.items;
@ -512,7 +514,7 @@ export class MailSendService
}
// Find first item with slotId that indicates its a 'base' item
let item = items.find(x => ["hideout", "main"].includes(x.slotId));
let item = items.find((x) => ["hideout", "main"].includes(x.slotId));
if (item)
{
return item;
@ -520,7 +522,7 @@ export class MailSendService
// Not a singlular item + no items have a hideout/main slotid
// Look for first item without parent id
item = items.find(x => !x.parentId);
item = items.find((x) => !x.parentId);
if (item)
{
return item;

View File

@ -58,7 +58,7 @@ export class PaymentService
for (const index in request.scheme_items)
{
// Find the corresponding item in the player's inventory.
const item = pmcData.Inventory.items.find(i => i._id === request.scheme_items[index].id);
const item = pmcData.Inventory.items.find((i) => i._id === request.scheme_items[index].id);
if (item !== undefined)
{
if (!this.paymentHelper.isMoneyTpl(item._tpl))
@ -396,7 +396,7 @@ export class PaymentService
*/
protected isInStash(itemId: string, inventoryItems: Item[], playerStashId: string): boolean
{
const itemParent = inventoryItems.find(x => x._id === itemId);
const itemParent = inventoryItems.find((x) => x._id === itemId);
if (itemParent)
{

View File

@ -229,7 +229,7 @@ export class PmcChatResponseService
const keyBase = isVictim ? "pmcresponse-victim_" : "pmcresponse-killer_";
const keys = this.localisationService.getKeys();
return keys.filter(x => x.startsWith(`${keyBase}${keyType}`));
return keys.filter((x) => x.startsWith(`${keyBase}${keyType}`));
}
/**
@ -240,7 +240,7 @@ export class PmcChatResponseService
{
const keys = this.localisationService.getKeys();
return keys.filter(x => x.startsWith("pmcresponse-suffix"));
return keys.filter((x) => x.startsWith("pmcresponse-suffix"));
}
/**

View File

@ -87,10 +87,10 @@ export class ProfileFixerService
this.reorderHideoutAreasWithResouceInputs(pmcProfile);
if (
pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.GENERATOR).slots.length
pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.GENERATOR).slots.length
< 6
+ this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots
.Generator.Slots
+ this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots.Generator
.Slots
)
{
this.logger.debug("Updating generator area slots to a size of 6 + hideout management skill");
@ -104,7 +104,7 @@ export class ProfileFixerService
}
if (
pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.WATER_COLLECTOR).slots.length
pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WATER_COLLECTOR).slots.length
< 1
+ this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots
.WaterCollector.Slots
@ -121,7 +121,7 @@ export class ProfileFixerService
}
if (
pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.AIR_FILTERING).slots.length
pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.AIR_FILTERING).slots.length
< 3
+ this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots
.AirFilteringUnit.Slots
@ -139,7 +139,7 @@ export class ProfileFixerService
// BTC Farm doesnt have extra slots for hideout management, but we still check for modded stuff!!
if (
pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.BITCOIN_FARM).slots.length
pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.BITCOIN_FARM).slots.length
< 50
+ this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots
.BitcoinFarm.Slots
@ -172,7 +172,7 @@ export class ProfileFixerService
protected addMissingGunStandContainerImprovements(pmcProfile: IPmcData): void
{
const weaponStandArea = pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.WEAPON_STAND);
const weaponStandArea = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WEAPON_STAND);
if (!weaponStandArea || weaponStandArea.level === 0)
{
// No stand in profile or its level 0, skip
@ -180,8 +180,8 @@ export class ProfileFixerService
}
const db = this.databaseServer.getTables();
const hideoutStandAreaDb = db.hideout.areas.find(x => x.type === HideoutAreas.WEAPON_STAND);
const hideoutStandSecondaryAreaDb = db.hideout.areas.find(x => x.parentArea === hideoutStandAreaDb._id);
const hideoutStandAreaDb = db.hideout.areas.find((x) => x.type === HideoutAreas.WEAPON_STAND);
const hideoutStandSecondaryAreaDb = db.hideout.areas.find((x) => x.parentArea === hideoutStandAreaDb._id);
const stageCurrentAt = hideoutStandAreaDb.stages[weaponStandArea.level];
const hideoutStandStashId = pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND];
const hideoutSecondaryStashId = pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND_SECONDARY];
@ -195,7 +195,7 @@ export class ProfileFixerService
= hideoutStandSecondaryAreaDb._id;
// Add stash item to profile
const gunStandStashItem = pmcProfile.Inventory.items.find(x => x._id === hideoutStandAreaDb._id);
const gunStandStashItem = pmcProfile.Inventory.items.find((x) => x._id === hideoutStandAreaDb._id);
if (gunStandStashItem)
{
gunStandStashItem._tpl = stageCurrentAt.container;
@ -212,8 +212,8 @@ export class ProfileFixerService
}
// Add secondary stash item to profile
const gunStandStashSecondaryItem = pmcProfile.Inventory.items.find(x =>
x._id === hideoutStandSecondaryAreaDb._id,
const gunStandStashSecondaryItem = pmcProfile.Inventory.items.find(
(x) => x._id === hideoutStandSecondaryAreaDb._id,
);
if (gunStandStashItem)
{
@ -236,12 +236,12 @@ export class ProfileFixerService
return;
}
let stashItem = pmcProfile.Inventory.items?.find(x => x._id === hideoutStandAreaDb._id);
let stashItem = pmcProfile.Inventory.items?.find((x) => x._id === hideoutStandAreaDb._id);
if (!stashItem)
{
// Stand inventory stash item doesnt exist, add it
pmcProfile.Inventory.items.push({ _id: hideoutStandAreaDb._id, _tpl: stageCurrentAt.container });
stashItem = pmcProfile.Inventory.items?.find(x => x._id === hideoutStandAreaDb._id);
stashItem = pmcProfile.Inventory.items?.find((x) => x._id === hideoutStandAreaDb._id);
}
// `hideoutAreaStashes` has value related stash inventory items tpl doesnt match what's expected
@ -254,12 +254,12 @@ export class ProfileFixerService
stashItem._tpl = stageCurrentAt.container;
}
let stashSecondaryItem = pmcProfile.Inventory.items?.find(x => x._id === hideoutStandSecondaryAreaDb._id);
let stashSecondaryItem = pmcProfile.Inventory.items?.find((x) => x._id === hideoutStandSecondaryAreaDb._id);
if (!stashSecondaryItem)
{
// Stand inventory stash item doesnt exist, add it
pmcProfile.Inventory.items.push({ _id: hideoutStandSecondaryAreaDb._id, _tpl: stageCurrentAt.container });
stashSecondaryItem = pmcProfile.Inventory.items?.find(x => x._id === hideoutStandSecondaryAreaDb._id);
stashSecondaryItem = pmcProfile.Inventory.items?.find((x) => x._id === hideoutStandSecondaryAreaDb._id);
}
// `hideoutAreaStashes` has value related stash inventory items tpl doesnt match what's expected
@ -275,7 +275,7 @@ export class ProfileFixerService
protected addMissingHallOfFameContainerImprovements(pmcProfile: IPmcData): void
{
const placeOfFameArea = pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.PLACE_OF_FAME);
const placeOfFameArea = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.PLACE_OF_FAME);
if (!placeOfFameArea || placeOfFameArea.level === 0)
{
// No place of fame in profile or its level 0, skip
@ -283,7 +283,7 @@ export class ProfileFixerService
}
const db = this.databaseServer.getTables();
const placeOfFameAreaDb = db.hideout.areas.find(area => area.type === HideoutAreas.PLACE_OF_FAME);
const placeOfFameAreaDb = db.hideout.areas.find((area) => area.type === HideoutAreas.PLACE_OF_FAME);
if (!placeOfFameAreaDb)
{
return;
@ -298,7 +298,7 @@ export class ProfileFixerService
pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.PLACE_OF_FAME] = placeOfFameAreaDb._id;
// Add stash item to profile
const placeOfFameStashItem = pmcProfile.Inventory.items.find(x => x._id === placeOfFameAreaDb._id);
const placeOfFameStashItem = pmcProfile.Inventory.items.find((x) => x._id === placeOfFameAreaDb._id);
if (placeOfFameStashItem)
{
placeOfFameStashItem._tpl = stageCurrentlyAt.container;
@ -317,12 +317,12 @@ export class ProfileFixerService
return;
}
let stashItem = pmcProfile.Inventory.items?.find(x => x._id === placeOfFameAreaDb._id);
let stashItem = pmcProfile.Inventory.items?.find((x) => x._id === placeOfFameAreaDb._id);
if (!stashItem)
{
// Stand inventory stash item doesnt exist, add it
pmcProfile.Inventory.items.push({ _id: placeOfFameAreaDb._id, _tpl: stageCurrentlyAt.container });
stashItem = pmcProfile.Inventory.items?.find(x => x._id === placeOfFameAreaDb._id);
stashItem = pmcProfile.Inventory.items?.find((x) => x._id === placeOfFameAreaDb._id);
}
// `hideoutAreaStashes` has value related stash inventory items tpl doesnt match what's expected
@ -339,10 +339,10 @@ export class ProfileFixerService
protected ensureGunStandLevelsMatch(pmcProfile: IPmcData): void
{
// only proceed if stand is level 1 or above
const gunStandParent = pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.WEAPON_STAND);
const gunStandParent = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WEAPON_STAND);
if (gunStandParent && gunStandParent.level > 0)
{
const gunStandChild = pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.WEAPON_STAND_SECONDARY);
const gunStandChild = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WEAPON_STAND_SECONDARY);
if (gunStandChild && gunStandParent.level !== gunStandChild.level)
{
this.logger.success("Upgraded gun stand levels to match");
@ -362,7 +362,7 @@ export class ProfileFixerService
protected addMissingHideoutWallAreas(pmcProfile: IPmcData): void
{
if (!pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.WEAPON_STAND))
if (!pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WEAPON_STAND))
{
pmcProfile.Hideout.Areas.push({
type: 24,
@ -376,7 +376,7 @@ export class ProfileFixerService
});
}
if (!pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.WEAPON_STAND_SECONDARY))
if (!pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WEAPON_STAND_SECONDARY))
{
pmcProfile.Hideout.Areas.push({
type: 25,
@ -473,14 +473,14 @@ export class ProfileFixerService
// Only check if profile has repeatable quests
if (pmcProfile.RepeatableQuests && activeRepeatableQuests.length > 0)
{
const existsInActiveRepeatableQuests = activeRepeatableQuests.some(quest =>
quest._id === taskConditionCounter.sourceId,
const existsInActiveRepeatableQuests = activeRepeatableQuests.some(
(quest) => quest._id === taskConditionCounter.sourceId,
);
const existsInQuests = pmcProfile.Quests.some(quest =>
quest.qid === taskConditionCounter.sourceId,
const existsInQuests = pmcProfile.Quests.some(
(quest) => quest.qid === taskConditionCounter.sourceId,
);
const isAchievementTracker = achievements.some(quest =>
quest.id === taskConditionCounter.sourceId,
const isAchievementTracker = achievements.some(
(quest) => quest.id === taskConditionCounter.sourceId,
);
// If task conditions id is neither in activeQuests, quests or achievements - it's stale and should be cleaned up
@ -565,12 +565,12 @@ export class ProfileFixerService
continue;
}
if (quest.status && Number.isNaN(Number.parseInt(<string><unknown>quest.status)))
if (quest.status && Number.isNaN(Number.parseInt(<string>(<unknown>quest.status))))
{
fixes[quest.status] = (fixes[quest.status] ?? 0) + 1;
const newQuestStatus = QuestStatus[quest.status];
quest.status = <QuestStatus><unknown>newQuestStatus;
quest.status = <QuestStatus>(<unknown>newQuestStatus);
}
for (const statusTimer in quest.statusTimers)
@ -594,16 +594,18 @@ export class ProfileFixerService
if (Object.keys(fixes).length > 0)
{
this.logger.debug(
`Updated quests values: ${Object.entries(fixes).map(([k, v]) => `(${k}: ${v} times)`).join(", ")}`,
`Updated quests values: ${Object.entries(fixes)
.map(([k, v]) => `(${k}: ${v} times)`)
.join(", ")}`,
);
}
if (Object.keys(timerFixes).length > 0)
{
this.logger.debug(
`Updated statusTimers values: ${
Object.entries(timerFixes).map(([k, v]) => `(${k}: ${v} times)`).join(", ")
}`,
`Updated statusTimers values: ${Object.entries(timerFixes)
.map(([k, v]) => `(${k}: ${v} times)`)
.join(", ")}`,
);
}
}
@ -616,8 +618,12 @@ export class ProfileFixerService
for (const currentRepeatable of pmcProfile.RepeatableQuests)
{
if (
!(currentRepeatable.changeRequirement
&& currentRepeatable.activeQuests.every(x => typeof x.changeCost !== "undefined" && typeof x.changeStandingCost !== "undefined"))
!(
currentRepeatable.changeRequirement
&& currentRepeatable.activeQuests.every(
(x) => typeof x.changeCost !== "undefined" && typeof x.changeStandingCost !== "undefined",
)
)
)
{
repeatablesCompatible = false;
@ -642,10 +648,10 @@ export class ProfileFixerService
*/
protected addMissingWallImprovements(pmcProfile: IPmcData): void
{
const profileWallArea = pmcProfile.Hideout.Areas.find(x => x.type === HideoutAreas.EMERGENCY_WALL);
const wallDb = this.databaseServer.getTables().hideout.areas.find(x =>
x.type === HideoutAreas.EMERGENCY_WALL,
);
const profileWallArea = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.EMERGENCY_WALL);
const wallDb = this.databaseServer
.getTables()
.hideout.areas.find((x) => x.type === HideoutAreas.EMERGENCY_WALL);
if (profileWallArea.level > 0)
{
@ -693,13 +699,13 @@ export class ProfileFixerService
}
// Only slots with location index
area.slots = area.slots.filter(x => "locationIndex" in x);
area.slots = area.slots.filter((x) => "locationIndex" in x);
// Only slots that:
// Have an item property and it has at least one item in it
// Or
// Have no item property
area.slots = area.slots.filter(x => ("item" in x && x.item?.length > 0) || !("item" in x));
area.slots = area.slots.filter((x) => ("item" in x && x.item?.length > 0) || !("item" in x));
}
}
@ -718,7 +724,7 @@ export class ProfileFixerService
for (const areaId of areasToCheck)
{
const area = pmcProfile.Hideout.Areas.find(area => area.type === areaId);
const area = pmcProfile.Hideout.Areas.find((area) => area.type === areaId);
if (!area)
{
this.logger.debug(`unable to sort: ${area.type} (${areaId}) slots, no area found`);
@ -749,7 +755,7 @@ export class ProfileFixerService
pmcProfile: IPmcData,
): void
{
const area = pmcProfile.Hideout.Areas.find(x => x.type === areaType);
const area = pmcProfile.Hideout.Areas.find((x) => x.type === areaType);
area.slots = this.addObjectsToArray(emptyItemCount, area.slots);
}
@ -757,7 +763,7 @@ export class ProfileFixerService
{
for (let i = 0; i < count; i++)
{
if (!slots.find(x => x.locationIndex === i))
if (!slots.find((x) => x.locationIndex === i))
{
slots.push({ locationIndex: i });
}
@ -795,7 +801,7 @@ export class ProfileFixerService
}
// Iterate over area levels, check for bonuses, add if needed
const dbArea = dbHideoutAreas.find(x => x.type === areaType);
const dbArea = dbHideoutAreas.find((x) => x.type === areaType);
if (!dbArea)
{
continue;
@ -840,22 +846,22 @@ export class ProfileFixerService
// match by id first, used by "TextBonus" bonuses
if (bonus.id)
{
return profileBonuses.find(x => x.id === bonus.id);
return profileBonuses.find((x) => x.id === bonus.id);
}
if (bonus.type === BonusType.STASH_SIZE)
{
return profileBonuses.find(x => x.type === bonus.type && x.templateId === bonus.templateId);
return profileBonuses.find((x) => x.type === bonus.type && x.templateId === bonus.templateId);
}
if (bonus.type === BonusType.ADDITIONAL_SLOTS)
{
return profileBonuses.find(x =>
x.type === bonus.type && x.value === bonus.value && x.visible === bonus.visible,
return profileBonuses.find(
(x) => x.type === bonus.type && x.value === bonus.value && x.visible === bonus.visible,
);
}
return profileBonuses.find(x => x.type === bonus.type && x.value === bonus.value);
return profileBonuses.find((x) => x.type === bonus.type && x.value === bonus.value);
}
/**
@ -870,7 +876,7 @@ export class ProfileFixerService
// Get items placed in root of stash
// TODO: extend to other areas / sub items
const inventoryItemsToCheck = pmcProfile.Inventory.items.filter(item =>
const inventoryItemsToCheck = pmcProfile.Inventory.items.filter((item) =>
["hideout", "main"].includes(item.slotId),
);
if (inventoryItemsToCheck)
@ -952,7 +958,10 @@ export class ProfileFixerService
if (this.coreConfig.fixes.removeModItemsFromProfile)
{
dialog.messages.splice(dialog.messages.findIndex(x => x._id === message._id), 1);
dialog.messages.splice(
dialog.messages.findIndex((x) => x._id === message._id),
1,
);
this.logger.warning(
`Item: ${item._tpl} has resulted in the deletion of message: ${message._id} from dialog ${dialogId}`,
);
@ -991,7 +1000,7 @@ export class ProfileFixerService
`Non-default quest: ${activeQuest._id} from trader: ${activeQuest.traderId} removed from RepeatableQuests list in profile`,
);
repeatable.activeQuests.splice(
repeatable.activeQuests.findIndex(x => x._id === activeQuest._id),
repeatable.activeQuests.findIndex((x) => x._id === activeQuest._id),
1,
);
}
@ -1016,7 +1025,7 @@ export class ProfileFixerService
`Non-default quest: ${activeQuest._id} from trader: ${activeQuest.traderId} removed from RepeatableQuests list in profile`,
);
repeatable.activeQuests.splice(
repeatable.activeQuests.findIndex(x => x._id === activeQuest._id),
repeatable.activeQuests.findIndex((x) => x._id === activeQuest._id),
1,
);
}
@ -1081,7 +1090,10 @@ export class ProfileFixerService
* @param itemsDb The items database to use for item lookup
* @returns True if the build should be removed from the build list, false otherwise
*/
protected shouldRemoveMagazineBuild(magazineBuild: IMagazineBuild, itemsDb: Record<string, ITemplateItem>): boolean
protected shouldRemoveMagazineBuild(
magazineBuild: IMagazineBuild,
itemsDb: Record<string, ITemplateItem>,
): boolean
{
for (const item of magazineBuild.Items)
{
@ -1141,7 +1153,7 @@ export class ProfileFixerService
if (itemAJson === itemBJson)
{
// Both items match, we can safely delete one
const indexOfItemToRemove = pmcProfile.Inventory.items.findIndex(x => x._id === key);
const indexOfItemToRemove = pmcProfile.Inventory.items.findIndex((x) => x._id === key);
pmcProfile.Inventory.items.splice(indexOfItemToRemove, 1);
this.logger.warning(`Deleted duplicate item: ${key}`);
}
@ -1149,10 +1161,10 @@ export class ProfileFixerService
{
// Items are different, replace ID with unique value
// Only replace ID if items have no children, we dont want orphaned children
const itemsHaveChildren = pmcProfile.Inventory.items.some(x => x.parentId === key);
const itemsHaveChildren = pmcProfile.Inventory.items.some((x) => x.parentId === key);
if (!itemsHaveChildren)
{
const itemToAdjustId = pmcProfile.Inventory.items.find(x => x._id === key);
const itemToAdjustId = pmcProfile.Inventory.items.find((x) => x._id === key);
itemToAdjustId._id = this.hashUtil.generate();
this.logger.warning(`Replace duplicate item Id: ${key} with ${itemToAdjustId._id}`);
}
@ -1160,7 +1172,7 @@ export class ProfileFixerService
}
// Iterate over all inventory items
for (const item of pmcProfile.Inventory.items.filter(x => x.slotId))
for (const item of pmcProfile.Inventory.items.filter((x) => x.slotId))
{
if (!item.upd)
{
@ -1193,35 +1205,38 @@ export class ProfileFixerService
if (!customizationDb[pmcProfile.Customization.Head])
{
const defaultHead = playerIsUsec
? customizationDbArray.find(x => x._name === "DefaultUsecHead")
: customizationDbArray.find(x => x._name === "DefaultBearHead");
? customizationDbArray.find((x) => x._name === "DefaultUsecHead")
: customizationDbArray.find((x) => x._name === "DefaultBearHead");
pmcProfile.Customization.Head = defaultHead._id;
}
// check Body
if (!customizationDb[pmcProfile.Customization.Body])
{
const defaultBody = pmcProfile.Info.Side.toLowerCase() === "usec"
? customizationDbArray.find(x => x._name === "DefaultUsecBody")
: customizationDbArray.find(x => x._name === "DefaultBearBody");
const defaultBody
= pmcProfile.Info.Side.toLowerCase() === "usec"
? customizationDbArray.find((x) => x._name === "DefaultUsecBody")
: customizationDbArray.find((x) => x._name === "DefaultBearBody");
pmcProfile.Customization.Body = defaultBody._id;
}
// check Hands
if (!customizationDb[pmcProfile.Customization.Hands])
{
const defaultHands = pmcProfile.Info.Side.toLowerCase() === "usec"
? customizationDbArray.find(x => x._name === "DefaultUsecHands")
: customizationDbArray.find(x => x._name === "DefaultBearHands");
const defaultHands
= pmcProfile.Info.Side.toLowerCase() === "usec"
? customizationDbArray.find((x) => x._name === "DefaultUsecHands")
: customizationDbArray.find((x) => x._name === "DefaultBearHands");
pmcProfile.Customization.Hands = defaultHands._id;
}
// check Hands
if (!customizationDb[pmcProfile.Customization.Feet])
{
const defaultFeet = pmcProfile.Info.Side.toLowerCase() === "usec"
? customizationDbArray.find(x => x._name === "DefaultUsecFeet")
: customizationDbArray.find(x => x._name === "DefaultBearFeet");
const defaultFeet
= pmcProfile.Info.Side.toLowerCase() === "usec"
? customizationDbArray.find((x) => x._name === "DefaultUsecFeet")
: customizationDbArray.find((x) => x._name === "DefaultBearFeet");
pmcProfile.Customization.Feet = defaultFeet._id;
}
}
@ -1266,7 +1281,7 @@ export class ProfileFixerService
// Get all areas from templates/profiles.json
for (const area of profileTemplate.character.Hideout.Areas)
{
if (!pmcProfile.Hideout.Areas.find(x => x.type === area.type))
if (!pmcProfile.Hideout.Areas.find((x) => x.type === area.type))
{
pmcProfile.Hideout.Areas.push(area);
this.logger.debug(`Added missing hideout area ${area.type} to profile`);
@ -1300,10 +1315,10 @@ export class ProfileFixerService
// biome-ignore lint/suspicious/noGlobalIsNan: <value can be a valid string, Number.IsNaN() would ignore it>
if (isNaN(fullProfile.characters.pmc.aid) || !fullProfile.info.aid)
{
fullProfile.characters.pmc.sessionId = <string><unknown>fullProfile.characters.pmc.aid;
fullProfile.characters.pmc.sessionId = <string>(<unknown>fullProfile.characters.pmc.aid);
fullProfile.characters.pmc.aid = this.hashUtil.generateAccountId();
fullProfile.characters.scav.sessionId = <string><unknown>fullProfile.characters.pmc.sessionId;
fullProfile.characters.scav.sessionId = <string>(<unknown>fullProfile.characters.pmc.sessionId);
fullProfile.characters.scav.aid = fullProfile.characters.pmc.aid;
fullProfile.info.aid = fullProfile.characters.pmc.aid;
@ -1329,7 +1344,7 @@ export class ProfileFixerService
// Clear stats object
fullProfile.characters.pmc.Stats = { Eft: null };
fullProfile.characters.pmc.Stats.Eft = <any><unknown>statsCopy;
fullProfile.characters.pmc.Stats.Eft = <any>(<unknown>statsCopy);
}
}
@ -1355,8 +1370,8 @@ export class ProfileFixerService
for (const stageIndex in area.stages)
{
const stageInfo = area.stages[stageIndex];
const matchingBonus = stageInfo.bonuses.find(x =>
x.templateId === bonus.templateId && x.type === bonus.type,
const matchingBonus = stageInfo.bonuses.find(
(x) => x.templateId === bonus.templateId && x.type === bonus.type,
);
if (matchingBonus)
{
@ -1425,7 +1440,7 @@ export class ProfileFixerService
for (let i = profileQuests.length - 1; i >= 0; i--)
{
if (!(quests[profileQuests[i].qid] || repeatableQuests.find(x => x._id === profileQuests[i].qid)))
if (!(quests[profileQuests[i].qid] || repeatableQuests.find((x) => x._id === profileQuests[i].qid)))
{
profileQuests.splice(i, 1);
this.logger.success("Successfully removed orphaned quest that doesnt exist in our quest data");

View File

@ -28,7 +28,8 @@ export class RagfairCategoriesService
): Record<string, number>
{
// Get offers valid for search request, then reduce them down to just the counts
return offers.filter((offer) =>
return offers
.filter((offer) =>
{
const isTraderOffer = offer.user.memberType === MemberCategory.TRADER;
@ -61,7 +62,8 @@ export class RagfairCategoriesService
// Passed checks, its a valid offer to process
return true;
}).reduce((acc, offer) =>
})
.reduce((acc, offer) =>
{
const itemTpl = offer.items[0]._tpl;
// Increment the category or add if doesnt exist

View File

@ -94,7 +94,7 @@ export class RagfairLinkedItemService
applyLinkedItems: (items: string[]) => void,
): void
{
const cylinderMod = cylinder._props.Slots.find(x => x._name === "mod_magazine");
const cylinderMod = cylinder._props.Slots.find((x) => x._name === "mod_magazine");
if (cylinderMod)
{
// Get the first cylinder filter tpl

View File

@ -2,7 +2,6 @@ import { inject, injectable } from "tsyringe";
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
import { RagfairServerHelper } from "@spt-aki/helpers/RagfairServerHelper";
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
import { IRagfairOffer } from "@spt-aki/models/eft/ragfair/IRagfairOffer";
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
import { IRagfairConfig } from "@spt-aki/models/spt/config/IRagfairConfig";
@ -251,7 +250,7 @@ export class RagfairOfferService
const pmcId = String(playerOffer.user.id);
const profile = this.profileHelper.getProfileByPmcId(pmcId);
const offerinProfileIndex = profile.RagfairInfo.offers.findIndex(o => o._id === playerOffer._id);
const offerinProfileIndex = profile.RagfairInfo.offers.findIndex((o) => o._id === playerOffer._id);
if (offerinProfileIndex === -1)
{
this.logger.warning(

View File

@ -73,11 +73,9 @@ export class RagfairPriceService implements OnLoad
*/
public generateStaticPrices(): void
{
for (
const item of Object.values(this.databaseServer.getTables().templates.items).filter(x =>
x._type === "Item",
)
)
for (const item of Object.values(this.databaseServer.getTables().templates.items).filter(
(x) => x._type === "Item",
))
{
this.prices.static[item._id] = Math.round(this.handbookHelper.getTemplatePrice(item._id));
}
@ -195,7 +193,7 @@ export class RagfairPriceService implements OnLoad
*/
protected getPriceDifference(a: number, b: number): number
{
return 100 * a / (a + b);
return (100 * a) / (a + b);
}
/**
@ -239,7 +237,10 @@ export class RagfairPriceService implements OnLoad
price += this.getDynamicItemPrice(item._tpl, desiredCurrency, item, offerItems, isPackOffer);
// Check if the item is a weapon preset.
if (item?.upd?.sptPresetId && this.presetHelper.isPresetBaseClass(item.upd.sptPresetId, BaseClasses.WEAPON))
if (
item?.upd?.sptPresetId
&& this.presetHelper.isPresetBaseClass(item.upd.sptPresetId, BaseClasses.WEAPON)
)
{
// This is a weapon preset, which has it's own price calculation that takes into account the mods in the
// preset. Since we've already calculated the price for the preset entire preset in
@ -365,7 +366,7 @@ export class RagfairPriceService implements OnLoad
price: number,
): number
{
const itemHandbookPrice = handbookPrices.find(handbookItem => handbookItem.Id === itemTpl);
const itemHandbookPrice = handbookPrices.find((handbookItem) => handbookItem.Id === itemTpl);
if (!itemHandbookPrice)
{
return price;
@ -423,7 +424,8 @@ export class RagfairPriceService implements OnLoad
// Only adjust price if difference is > a percent AND item price passes threshold set in config
if (
priceDifferencePercent > this.ragfairConfig.dynamic.offerAdjustment.maxPriceDifferenceBelowHandbookPercent
priceDifferencePercent
> this.ragfairConfig.dynamic.offerAdjustment.maxPriceDifferenceBelowHandbookPercent
&& itemPrice >= this.ragfairConfig.dynamic.offerAdjustment.priceThreshholdRub
)
{
@ -467,8 +469,8 @@ export class RagfairPriceService implements OnLoad
}
// Get mods on current gun not in default preset
const newOrReplacedModsInPresetVsDefault = weaponWithChildren.filter(x =>
!presetResult.preset._items.some(y => y._tpl === x._tpl),
const newOrReplacedModsInPresetVsDefault = weaponWithChildren.filter(
(x) => !presetResult.preset._items.some((y) => y._tpl === x._tpl),
);
// Add up extra mods price
@ -483,8 +485,8 @@ export class RagfairPriceService implements OnLoad
if (newOrReplacedModsInPresetVsDefault.length >= 1)
{
// Add up cost of mods replaced
const modsReplacedByNewMods = newOrReplacedModsInPresetVsDefault.filter(x =>
presetResult.preset._items.some(y => y.slotId === x.slotId),
const modsReplacedByNewMods = newOrReplacedModsInPresetVsDefault.filter((x) =>
presetResult.preset._items.some((y) => y.slotId === x.slotId),
);
// Add up replaced mods price
@ -536,17 +538,13 @@ export class RagfairPriceService implements OnLoad
if (nonDefaultPresets.length === 1)
{
this.logger.debug(
`Item Id: ${weapon._tpl} has no default encyclopedia entry but only one preset (${
nonDefaultPresets[0]._name
}), choosing preset (${nonDefaultPresets[0]._name})`,
`Item Id: ${weapon._tpl} has no default encyclopedia entry but only one preset (${nonDefaultPresets[0]._name}), choosing preset (${nonDefaultPresets[0]._name})`,
);
}
else
{
this.logger.debug(
`Item Id: ${weapon._tpl} has no default encyclopedia entry, choosing first preset (${
nonDefaultPresets[0]._name
}) of ${nonDefaultPresets.length}`,
`Item Id: ${weapon._tpl} has no default encyclopedia entry, choosing first preset (${nonDefaultPresets[0]._name}) of ${nonDefaultPresets.length}`,
);
}

View File

@ -70,8 +70,8 @@ export class RagfairTaxService
const requirementsPrice = requirementsValue * (sellInOnePiece ? 1 : offerItemCount);
const itemTaxMult = this.databaseServer.getTables().globals.config.RagFair.communityItemTax / 100.0;
const requirementTaxMult = this.databaseServer.getTables().globals.config.RagFair.communityRequirementTax
/ 100.0;
const requirementTaxMult
= this.databaseServer.getTables().globals.config.RagFair.communityRequirementTax / 100.0;
let itemPriceMult = Math.log10(itemWorth / requirementsPrice);
let requirementPriceMult = Math.log10(requirementsPrice / itemWorth);
@ -88,11 +88,11 @@ export class RagfairTaxService
itemPriceMult = 4 ** itemPriceMult;
requirementPriceMult = 4 ** requirementPriceMult;
const hideoutFleaTaxDiscountBonus = pmcData.Bonuses.find(b => b.type === BonusType.RAGFAIR_COMMISSION);
const hideoutFleaTaxDiscountBonus = pmcData.Bonuses.find((b) => b.type === BonusType.RAGFAIR_COMMISSION);
const taxDiscountPercent = hideoutFleaTaxDiscountBonus ? Math.abs(hideoutFleaTaxDiscountBonus.value) : 0;
const tax = itemWorth * itemTaxMult * itemPriceMult
+ requirementsPrice * requirementTaxMult * requirementPriceMult;
const tax
= itemWorth * itemTaxMult * itemPriceMult + requirementsPrice * requirementTaxMult * requirementPriceMult;
const discountedTax = tax * (1.0 - taxDiscountPercent / 100.0);
const itemComissionMult = itemTemplate._props.RagFairCommissionModifier
? itemTemplate._props.RagFairCommissionModifier
@ -123,7 +123,8 @@ export class RagfairTaxService
// In client, all item slots are traversed and any items contained within have their values added
if (isRootItem)
{ // Since we get a flat list of all child items, we only want to recurse from parent item
{
// Since we get a flat list of all child items, we only want to recurse from parent item
const itemChildren = this.itemHelper.findAndReturnChildrenAsItems(pmcData.Inventory.items, item._id);
if (itemChildren.length > 1)
{
@ -152,34 +153,36 @@ export class RagfairTaxService
if ("Key" in item.upd && itemTemplate._props.MaximumNumberOfUsage > 0)
{
worth = worth / itemTemplate._props.MaximumNumberOfUsage
worth
= (worth / itemTemplate._props.MaximumNumberOfUsage)
* (itemTemplate._props.MaximumNumberOfUsage - item.upd.Key.NumberOfUsages);
}
if ("Resource" in item.upd && itemTemplate._props.MaxResource > 0)
{
worth = worth * 0.1 + worth * 0.9 / itemTemplate._props.MaxResource * item.upd.Resource.Value;
worth = worth * 0.1 + ((worth * 0.9) / itemTemplate._props.MaxResource) * item.upd.Resource.Value;
}
if ("SideEffect" in item.upd && itemTemplate._props.MaxResource > 0)
{
worth = worth * 0.1 + worth * 0.9 / itemTemplate._props.MaxResource * item.upd.SideEffect.Value;
worth = worth * 0.1 + ((worth * 0.9) / itemTemplate._props.MaxResource) * item.upd.SideEffect.Value;
}
if ("MedKit" in item.upd && itemTemplate._props.MaxHpResource > 0)
{
worth = worth / itemTemplate._props.MaxHpResource * item.upd.MedKit.HpResource;
worth = (worth / itemTemplate._props.MaxHpResource) * item.upd.MedKit.HpResource;
}
if ("FoodDrink" in item.upd && itemTemplate._props.MaxResource > 0)
{
worth = worth / itemTemplate._props.MaxResource * item.upd.FoodDrink.HpPercent;
worth = (worth / itemTemplate._props.MaxResource) * item.upd.FoodDrink.HpPercent;
}
if ("Repairable" in item.upd && <number > itemTemplate._props.armorClass > 0)
{
const num2 = 0.01 * 0.0 ** item.upd.Repairable.MaxDurability;
worth = worth * (item.upd.Repairable.MaxDurability / itemTemplate._props.Durability - num2)
worth
= worth * (item.upd.Repairable.MaxDurability / itemTemplate._props.Durability - num2)
- Math.floor(
itemTemplate._props.RepairCost
* (item.upd.Repairable.MaxDurability - item.upd.Repairable.Durability),

View File

@ -80,7 +80,7 @@ export class RaidTimeAdjustmentService
{
// Remove waves that spawned before the player joined
const originalWaveCount = mapBase.waves.length;
mapBase.waves = mapBase.waves.filter(x => x.time_max > raidAdjustments.simulatedRaidStartSeconds);
mapBase.waves = mapBase.waves.filter((x) => x.time_max > raidAdjustments.simulatedRaidStartSeconds);
// Adjust wave min/max times to match new simulated start
for (const wave of mapBase.waves)

View File

@ -60,7 +60,7 @@ export class RepairService
traderId: string,
): RepairDetails
{
const itemToRepair = pmcData.Inventory.items.find(x => x._id === repairItemDetails._id);
const itemToRepair = pmcData.Inventory.items.find((x) => x._id === repairItemDetails._id);
if (itemToRepair === undefined)
{
throw new Error(`Item ${repairItemDetails._id} not found in profile inventory, unable to repair`);
@ -121,10 +121,12 @@ export class RepairService
): void
{
const options: IProcessBuyTradeRequestData = {
scheme_items: [{
scheme_items: [
{
id: "5449016a4bdc2d6f028b456f", // Rouble tpl
count: Math.round(repairCost),
}],
},
],
tid: traderId,
Action: "SptRepair",
type: "",
@ -184,8 +186,8 @@ export class RepairService
const isHeavyArmor = itemDetails[1]._props.ArmorType === "Heavy";
const vestSkillToLevel = isHeavyArmor ? SkillTypes.HEAVY_VESTS : SkillTypes.LIGHT_VESTS;
const pointsToAddToVestSkill = repairDetails.repairPoints
* this.repairConfig.armorKitSkillPointGainPerRepairPointMultiplier;
const pointsToAddToVestSkill
= repairDetails.repairPoints * this.repairConfig.armorKitSkillPointGainPerRepairPointMultiplier;
this.logger.debug(`Added: ${pointsToAddToVestSkill} ${vestSkillToLevel} skill`);
this.profileHelper.addSkillPointsToPlayer(pmcData, vestSkillToLevel, pointsToAddToVestSkill);
@ -205,8 +207,10 @@ export class RepairService
if (repairDetails.repairedByKit)
{
// Weapons/armor have different multipliers
const intRepairMultiplier
= this.itemHelper.isOfBaseclass(repairDetails.repairedItem._tpl, BaseClasses.WEAPON)
const intRepairMultiplier = this.itemHelper.isOfBaseclass(
repairDetails.repairedItem._tpl,
BaseClasses.WEAPON,
)
? this.repairConfig.repairKitIntellectGainMultiplier.weapon
: this.repairConfig.repairKitIntellectGainMultiplier.armor;
@ -302,7 +306,7 @@ export class RepairService
// Find and use repair kit defined in body
for (const repairKit of repairKits)
{
const repairKitInInventory = pmcData.Inventory.items.find(x => x._id === repairKit._id);
const repairKitInInventory = pmcData.Inventory.items.find((x) => x._id === repairKit._id);
const repairKitDetails = itemsDb[repairKitInInventory._tpl];
const repairKitReductionAmount = repairKit.count;
@ -336,8 +340,8 @@ export class RepairService
const globalRepairSettings = globals.config.RepairSettings;
const intellectRepairPointsPerLevel = globals.config.SkillsSettings.Intellect.RepairPointsCostReduction;
const profileIntellectLevel = this.profileHelper.getSkillFromProfile(pmcData, SkillTypes.INTELLECT)?.Progress
?? 0;
const profileIntellectLevel
= this.profileHelper.getSkillFromProfile(pmcData, SkillTypes.INTELLECT)?.Progress ?? 0;
const intellectPointReduction = intellectRepairPointsPerLevel * Math.trunc(profileIntellectLevel / 100);
if (isArmor)
@ -370,11 +374,11 @@ export class RepairService
*/
protected getBonusMultiplierValue(skillBonus: BonusType, pmcData: IPmcData): number
{
const bonusesMatched = pmcData?.Bonuses?.filter(b => b.type === skillBonus);
const bonusesMatched = pmcData?.Bonuses?.filter((b) => b.type === skillBonus);
let value = 1;
if (bonusesMatched != null)
{
const sumedPercentage = bonusesMatched.map(b => b.value).reduce((v1, v2) => v1 + v2, 0);
const sumedPercentage = bonusesMatched.map((b) => b.value).reduce((v1, v2) => v1 + v2, 0);
value = 1 + sumedPercentage / 100;
}

View File

@ -342,7 +342,7 @@ export class SeasonalEventService
}
// Get non-christmas items
const nonChristmasTpls = Object.keys(containerItems).filter(tpl => !christmasItems.includes(tpl));
const nonChristmasTpls = Object.keys(containerItems).filter((tpl) => !christmasItems.includes(tpl));
const intermediaryDict = {};
for (const tpl of nonChristmasTpls)
@ -368,7 +368,7 @@ export class SeasonalEventService
switch (eventType.toLowerCase())
{
case SeasonalEventType.HALLOWEEN.toLowerCase():
globalConfig.EventType = globalConfig.EventType.filter(x => x !== "None");
globalConfig.EventType = globalConfig.EventType.filter((x) => x !== "None");
globalConfig.EventType.push("Halloween");
globalConfig.EventType.push("HalloweenIllumination");
globalConfig.Health.ProfileHealthSettings.DefaultStimulatorBuff = "Buffs_Halloween";
@ -380,7 +380,7 @@ export class SeasonalEventService
this.adjustTraderIcons(eventType);
break;
case SeasonalEventType.CHRISTMAS.toLowerCase():
globalConfig.EventType = globalConfig.EventType.filter(x => x !== "None");
globalConfig.EventType = globalConfig.EventType.filter((x) => x !== "None");
globalConfig.EventType.push("Christmas");
this.addEventGearToBots(eventType);
this.addGifterBotToMaps();
@ -435,7 +435,7 @@ export class SeasonalEventService
{
const mapBosses: BossLocationSpawn[]
= this.databaseServer.getTables().locations[mapKey].base.BossLocationSpawn;
if (!mapBosses.find(x => x.BossName === boss.BossName))
if (!mapBosses.find((x) => x.BossName === boss.BossName))
{
this.databaseServer.getTables().locations[mapKey].base.BossLocationSpawn.push(...bossesToAdd);
}
@ -474,9 +474,11 @@ export class SeasonalEventService
break;
}
this.databaseImporter.loadImages(`${this.databaseImporter.getSptDataPath()}images/`, ["traders"], [
"/files/trader/avatar/",
]);
this.databaseImporter.loadImages(
`${this.databaseImporter.getSptDataPath()}images/`,
["traders"],
["/files/trader/avatar/"],
);
}
/**
@ -487,8 +489,9 @@ export class SeasonalEventService
const gifterBot = this.databaseServer.getTables().bots.types.gifter;
for (const difficulty in gifterBot.difficulty)
{
gifterBot.difficulty[difficulty].Patrol.ITEMS_TO_DROP = Object.keys(gifterBot.inventory.items.Backpack)
.join(", ");
gifterBot.difficulty[difficulty].Patrol.ITEMS_TO_DROP = Object.keys(
gifterBot.inventory.items.Backpack,
).join(", ");
}
}
@ -574,7 +577,7 @@ export class SeasonalEventService
{
const mapData: ILocation = maps[gifterMapSettings.map];
// Dont add gifter to map twice
if (mapData.base.BossLocationSpawn.some(boss => boss.BossName === "gifter"))
if (mapData.base.BossLocationSpawn.some((boss) => boss.BossName === "gifter"))
{
continue;
}

View File

@ -121,7 +121,7 @@ export class TraderPurchasePersisterService
for (const purchaseKey in profile.traderPurchases[traderId])
{
const traderUpdateDetails = this.traderConfig.updateTime.find(x => x.traderId === traderId);
const traderUpdateDetails = this.traderConfig.updateTime.find((x) => x.traderId === traderId);
if (!traderUpdateDetails)
{
this.logger.error(
@ -135,7 +135,8 @@ export class TraderPurchasePersisterService
}
const purchaseDetails = profile.traderPurchases[traderId][purchaseKey];
const resetTimeForItem = purchaseDetails.purchaseTimestamp
const resetTimeForItem
= purchaseDetails.purchaseTimestamp
+ this.randomUtil.getInt(traderUpdateDetails.seconds.min, traderUpdateDetails.seconds.max);
if (resetTimeForItem < this.timeUtil.getTimestamp())
{

View File

@ -46,7 +46,7 @@ export class TraderServicesService
{
for (const questId of service.requirements.completedQuests)
{
const quest = pmcData.Quests.find(x => x.qid === questId);
const quest = pmcData.Quests.find((x) => x.qid === questId);
if (!quest || quest.status !== QuestStatus.Success)
{
servicesToDelete.push(service.serviceType);
@ -57,7 +57,7 @@ export class TraderServicesService
}
// Clear any unavailable services from the list
traderServices = traderServices.filter(x => !servicesToDelete.includes(x.serviceType));
traderServices = traderServices.filter((x) => !servicesToDelete.includes(x.serviceType));
return traderServices;
}

View File

@ -2,7 +2,10 @@ import { DynamicRouter, RouteAction } from "@spt-aki/di/Router";
export class DynamicRouterMod extends DynamicRouter
{
public constructor(routes: RouteAction[], private topLevelRoute: string)
public constructor(
routes: RouteAction[],
private topLevelRoute: string,
)
{
super(routes);
}

View File

@ -7,8 +7,7 @@ export class HttpListenerMod implements IHttpListener
private canHandleOverride: (sessionId: string, req: IncomingMessage) => boolean,
private handleOverride: (sessionId: string, req: IncomingMessage, resp: ServerResponse) => void,
)
{
}
{}
public canHandle(sessionId: string, req: IncomingMessage): boolean
{

View File

@ -2,7 +2,10 @@ import { OnLoad } from "@spt-aki/di/OnLoad";
export class OnLoadMod implements OnLoad
{
public constructor(private onLoadOverride: () => void, private getRouteOverride: () => string)
public constructor(
private onLoadOverride: () => void,
private getRouteOverride: () => string,
)
{
// super();
}

View File

@ -6,8 +6,7 @@ export class OnUpdateMod implements OnUpdate
private onUpdateOverride: (timeSinceLastRun: number) => boolean,
private getRouteOverride: () => string,
)
{
}
{}
public async onUpdate(timeSinceLastRun: number): Promise<boolean>
{

View File

@ -7,7 +7,11 @@ export class OnUpdateModService
constructor(protected container: DependencyContainer)
{}
public registerOnUpdate(name: string, onUpdate: (timeSinceLastRun: number) => boolean, getRoute: () => string): void
public registerOnUpdate(
name: string,
onUpdate: (timeSinceLastRun: number) => boolean,
getRoute: () => string,
): void
{
this.container.register(name, { useValue: new OnUpdateMod(onUpdate, getRoute) });
this.container.registerType("OnUpdate", name);

View File

@ -2,7 +2,10 @@ import { RouteAction, StaticRouter } from "@spt-aki/di/Router";
export class StaticRouterMod extends StaticRouter
{
public constructor(routes: RouteAction[], private topLevelRoute: string)
public constructor(
routes: RouteAction[],
private topLevelRoute: string,
)
{
super(routes);
}

View File

@ -42,7 +42,7 @@ export class CompareUtil
{
return false;
}
return arr1.every(vOf1 => arr2.find(vOf2 => this.recursiveCompare(vOf1, vOf2)));
return arr1.every((vOf1) => arr2.find((vOf2) => this.recursiveCompare(vOf1, vOf2)));
}
for (const propOf1 in v1)
{

View File

@ -107,9 +107,8 @@ export class DatabaseImporter implements OnLoad
(fileWithPath: string, data: string) => this.onReadValidate(fileWithPath, data),
);
const validation = this.valid === VaildationResult.FAILED || this.valid === VaildationResult.NOT_FOUND
? "."
: "";
const validation
= this.valid === VaildationResult.FAILED || this.valid === VaildationResult.NOT_FOUND ? "." : "";
this.logger.info(`${this.localisationService.getText("importing_database_finish")}${validation}`);
this.databaseServer.setTables(dataToImport);
}

View File

@ -7,13 +7,13 @@ import { HttpServerHelper } from "@spt-aki/helpers/HttpServerHelper";
export class HttpFileUtil
{
constructor(@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper)
{
}
{}
public sendFile(resp: ServerResponse, filePath: string): void
{
const pathSlic = filePath.split("/");
const type = this.httpServerHelper.getMimeText(pathSlic[pathSlic.length - 1].split(".").at(-1))
const type
= this.httpServerHelper.getMimeText(pathSlic[pathSlic.length - 1].split(".").at(-1))
|| this.httpServerHelper.getMimeText("txt");
const fileStream = fs.createReadStream(filePath);

View File

@ -17,12 +17,12 @@ export class HttpResponseUtil
protected clearString(s: string): any
{
return s.replace(/[\b]/g, "").replace(/[\f]/g, "").replace(/[\n]/g, "")
return s
.replace(/[\b]/g, "")
.replace(/[\f]/g, "")
.replace(/[\n]/g, "")
.replace(/[\r]/g, "")
.replace(
/[\t]/g,
"",
);
.replace(/[\t]/g, "");
}
/**

View File

@ -8,7 +8,10 @@ import { VFS } from "@spt-aki/utils/VFS";
@injectable()
export class ImporterUtil
{
constructor(@inject("VFS") protected vfs: VFS, @inject("JsonUtil") protected jsonUtil: JsonUtil)
constructor(
@inject("VFS") protected vfs: VFS,
@inject("JsonUtil") protected jsonUtil: JsonUtil,
)
{}
/**
@ -55,7 +58,7 @@ export class ImporterUtil
// set all loadRecursive to be executed asynchronously
const resEntries = Object.entries(result);
const resResolved = await Promise.all(resEntries.map(ent => ent[1]));
const resResolved = await Promise.all(resEntries.map((ent) => ent[1]));
for (let resIdx = 0; resIdx < resResolved.length; resIdx++)
{
resEntries[resIdx][1] = resResolved[resIdx];
@ -70,9 +73,13 @@ export class ImporterUtil
* @param filepath Path to folder with files
* @returns
*/
public loadRecursive<T>(filepath: string, onReadCallback: (fileWithPath: string, data: string) => void = () =>
{}, onObjectDeserialized: (fileWithPath: string, object: any) => void = () =>
{}): T
public loadRecursive<T>(
filepath: string,
onReadCallback: (fileWithPath: string, data: string) => void = () =>
{},
onObjectDeserialized: (fileWithPath: string, object: any) => void = () =>
{},
): T
{
const result = {} as T;
@ -123,14 +130,14 @@ export class ImporterUtil
const files = this.vfs.getFiles(filepath);
const directories = this.vfs.getDirs(filepath);
directoriesToRead.enqueueAll(directories.map(d => `${filepath}${d}`));
filesToProcess.enqueueAll(files.map(f => new VisitNode(filepath, f)));
directoriesToRead.enqueueAll(directories.map((d) => `${filepath}${d}`));
filesToProcess.enqueueAll(files.map((f) => new VisitNode(filepath, f)));
while (directoriesToRead.length !== 0)
{
const directory = directoriesToRead.dequeue();
filesToProcess.enqueueAll(this.vfs.getFiles(directory).map(f => new VisitNode(`${directory}/`, f)));
directoriesToRead.enqueueAll(this.vfs.getDirs(directory).map(d => `${directory}/${d}`));
filesToProcess.enqueueAll(this.vfs.getFiles(directory).map((f) => new VisitNode(`${directory}/`, f)));
directoriesToRead.enqueueAll(this.vfs.getDirs(directory).map((d) => `${directory}/${d}`));
}
while (filesToProcess.length !== 0)
@ -140,11 +147,14 @@ export class ImporterUtil
{
const filePathAndName = `${fileNode.filePath}${fileNode.fileName}`;
promises.push(
this.vfs.readFileAsync(filePathAndName).then(async (fileData) =>
this.vfs
.readFileAsync(filePathAndName)
.then(async (fileData) =>
{
onReadCallback(filePathAndName, fileData);
return this.jsonUtil.deserializeWithCacheCheckAsync<any>(fileData, filePathAndName);
}).then(async (fileDeserialized) =>
})
.then(async (fileDeserialized) =>
{
onObjectDeserialized(filePathAndName, fileDeserialized);
const strippedFilePath = this.vfs.stripExtension(filePathAndName).replace(filepath, "");
@ -154,7 +164,7 @@ export class ImporterUtil
}
}
await Promise.all(promises).catch(e => console.error(e));
await Promise.all(promises).catch((e) => console.error(e));
return result;
}
@ -186,6 +196,9 @@ export class ImporterUtil
class VisitNode
{
constructor(public filePath: string, public fileName: string)
constructor(
public filePath: string,
public fileName: string,
)
{}
}

View File

@ -178,7 +178,8 @@ export class JsonUtil
{
const { data, changed } = fixJson(jsonString);
if (changed)
{ // data invalid, return it
{
// data invalid, return it
this.logger.error(`${filePath} - Detected faulty json, please fix your json file using VSCodium`);
}
else

View File

@ -39,7 +39,7 @@ export class MathUtil
*/
public arrayProd(values: number[], factor: number): number[]
{
return values.map(x => x * factor);
return values.map((x) => x * factor);
}
/**
@ -49,7 +49,7 @@ export class MathUtil
*/
public arrayAdd(values: number[], summand: number): number[]
{
return values.map(x => x + summand);
return values.map((x) => x + summand);
}
/**
@ -101,7 +101,7 @@ export class MathUtil
{
if (xp >= x[i] && xp <= x[i + 1])
{
return y[i] + (xp - x[i]) * (y[i + 1] - y[i]) / (x[i + 1] - x[i]);
return y[i] + ((xp - x[i]) * (y[i + 1] - y[i])) / (x[i + 1] - x[i]);
}
}
}

View File

@ -25,7 +25,7 @@ export class ObjectId
let hexString = "";
for (let i = 0; i < byteArray.length; i++)
{
hexString += `0${(byteArray[i] & 0xFF).toString(16)}`.slice(-2);
hexString += `0${(byteArray[i] & 0xff).toString(16)}`.slice(-2);
}
return hexString;
}
@ -42,16 +42,16 @@ export class ObjectId
const objectIdBinary = Buffer.alloc(12);
objectIdBinary[3] = time & 0xff;
objectIdBinary[2] = time >> 8 & 0xff;
objectIdBinary[1] = time >> 16 & 0xff;
objectIdBinary[0] = time >> 24 & 0xff;
objectIdBinary[2] = (time >> 8) & 0xff;
objectIdBinary[1] = (time >> 16) & 0xff;
objectIdBinary[0] = (time >> 24) & 0xff;
objectIdBinary[4] = this.randomBytes[0];
objectIdBinary[5] = this.randomBytes[1];
objectIdBinary[6] = this.randomBytes[2];
objectIdBinary[7] = this.randomBytes[3];
objectIdBinary[8] = this.randomBytes[4];
objectIdBinary[9] = counter >> 16 & 0xff;
objectIdBinary[10] = counter >> 8 & 0xff;
objectIdBinary[9] = (counter >> 16) & 0xff;
objectIdBinary[10] = (counter >> 8) & 0xff;
objectIdBinary[11] = counter & 0xff;
return this.toHexString(objectIdBinary);

View File

@ -7,7 +7,10 @@ export class RagfairOfferHolder
protected offersByTemplate: Map<string, Map<string, IRagfairOffer>>;
protected offersByTrader: Map<string, Map<string, IRagfairOffer>>;
constructor(protected maxOffersPerTemplate: number, protected ragfairServerHelper: RagfairServerHelper)
constructor(
protected maxOffersPerTemplate: number,
protected ragfairServerHelper: RagfairServerHelper,
)
{
this.offersById = new Map();
this.offersByTemplate = new Map();
@ -122,7 +125,7 @@ export class RagfairOfferHolder
*/
public getStaleOffers(time: number): Array<IRagfairOffer>
{
return this.getOffers().filter(o => this.isStale(o, time));
return this.getOffers().filter((o) => this.isStale(o, time));
}
protected addOfferByTemplates(template: string, offer: IRagfairOffer): void

View File

@ -20,7 +20,11 @@ import { MathUtil } from "@spt-aki/utils/MathUtil";
*/
export class ProbabilityObjectArray<K, V = undefined> extends Array<ProbabilityObject<K, V>>
{
constructor(private mathUtil: MathUtil, private cloner: ICloner, ...items: ProbabilityObject<K, V>[])
constructor(
private mathUtil: MathUtil,
private cloner: ICloner,
...items: ProbabilityObject<K, V>[]
)
{
super();
this.push(...items);
@ -69,7 +73,7 @@ export class ProbabilityObjectArray<K, V = undefined> extends Array<ProbabilityO
*/
drop(key: K): ProbabilityObjectArray<K, V>
{
return this.filter(r => r.key !== key);
return this.filter((r) => r.key !== key);
}
/**
@ -79,7 +83,7 @@ export class ProbabilityObjectArray<K, V = undefined> extends Array<ProbabilityO
*/
data(key: K): V
{
return this.filter(r => r.key === key)[0]?.data;
return this.filter((r) => r.key === key)[0]?.data;
}
/**
@ -94,7 +98,7 @@ export class ProbabilityObjectArray<K, V = undefined> extends Array<ProbabilityO
*/
probability(key: K): number
{
return this.filter(r => r.key === key)[0].relativeProbability;
return this.filter((r) => r.key === key)[0].relativeProbability;
}
/**
@ -108,7 +112,7 @@ export class ProbabilityObjectArray<K, V = undefined> extends Array<ProbabilityO
*/
maxProbability(): number
{
return Math.max(...this.map(x => x.relativeProbability));
return Math.max(...this.map((x) => x.relativeProbability));
}
/**
@ -122,7 +126,7 @@ export class ProbabilityObjectArray<K, V = undefined> extends Array<ProbabilityO
*/
minProbability(): number
{
return Math.min(...this.map(x => x.relativeProbability));
return Math.min(...this.map((x) => x.relativeProbability));
}
/**
@ -140,19 +144,22 @@ export class ProbabilityObjectArray<K, V = undefined> extends Array<ProbabilityO
return [];
}
const { probArray, keyArray } = this.reduce((acc, x) =>
const { probArray, keyArray } = this.reduce(
(acc, x) =>
{
acc.probArray.push(x.relativeProbability);
acc.keyArray.push(x.key);
return acc;
}, { probArray: [], keyArray: [] });
},
{ probArray: [], keyArray: [] },
);
let probCumsum = this.cumulativeProbability(probArray);
const drawnKeys = [];
for (let i = 0; i < count; i++)
{
const rand = Math.random();
const randomIndex = probCumsum.findIndex(x => x > rand);
const randomIndex = probCumsum.findIndex((x) => x > rand);
// We cannot put Math.random() directly in the findIndex because then it draws anew for each of its iteration
if (replacement || locklist.includes(keyArray[randomIndex]))
{
@ -204,9 +211,11 @@ export class ProbabilityObject<K, V = undefined>
@injectable()
export class RandomUtil
{
constructor(@inject("RecursiveCloner") protected cloner: ICloner, @inject("WinstonLogger") protected logger: ILogger)
{
}
constructor(
@inject("RecursiveCloner") protected cloner: ICloner,
@inject("WinstonLogger") protected logger: ILogger,
)
{}
public getInt(min: number, max: number): number
{
@ -232,7 +241,7 @@ export class RandomUtil
public getPercentOfValue(percent: number, number: number, toFixed = 2): number
{
return Number.parseFloat((percent * number / 100).toFixed(toFixed));
return Number.parseFloat(((percent * number) / 100).toFixed(toFixed));
}
/**
@ -446,8 +455,7 @@ export class RandomUtil
do
{
num = boundedGaussian(biasedMin, biasedMax, n);
}
while (num < min || num > max);
} while (num < min || num > max);
return num;
}

View File

@ -112,8 +112,8 @@ export class TimeUtil
public getTimestampOfNextHour(): number
{
const now = new Date();
const millisecondsUntilNextHour = (60 - now.getMinutes()) * 60 * 1000 - now.getSeconds() * 1000
- now.getMilliseconds();
const millisecondsUntilNextHour
= (60 - now.getMinutes()) * 60 * 1000 - now.getSeconds() * 1000 - now.getMilliseconds();
return (now.getTime() + millisecondsUntilNextHour) / 1000;
}
}

View File

@ -121,7 +121,7 @@ export class VFS
const files = this.getFiles(filepath);
const dirs = this.getDirs(filepath);
if (!await this.existsAsync(target))
if (!(await this.existsAsync(target)))
{
await this.createDirAsync(`${target}/`);
}
@ -194,7 +194,7 @@ export class VFS
{
const options = append ? { flag: "a" } : { flag: "w" };
if (!await this.exists(filepath))
if (!(await this.exists(filepath)))
{
await this.createDir(filepath);
await this.writeFilePromisify(filepath, "");
@ -332,7 +332,7 @@ export class VFS
public async minifyAllJsonInDirRecursive(filepath: string): Promise<void>
{
const files = this.getFiles(filepath).filter(item => this.getFileExtension(item) === "json");
const files = this.getFiles(filepath).filter((item) => this.getFileExtension(item) === "json");
for (const file of files)
{
const filePathAndName = path.join(filepath, file);
@ -349,7 +349,7 @@ export class VFS
public async minifyAllJsonInDirRecursiveAsync(filepath: string): Promise<void>
{
const files = this.getFiles(filepath).filter(item => this.getFileExtension(item) === "json");
const files = this.getFiles(filepath).filter((item) => this.getFileExtension(item) === "json");
for (const file of files)
{
const filePathAndName = path.join(filepath, file);

View File

@ -154,7 +154,8 @@ export class Watermark
const result = [];
// Calculate size, add 10% for spacing to the right
const longestLength = this.text.reduce((a, b) =>
const longestLength
= this.text.reduce((a, b) =>
{
return a.length > b.length ? a : b;
}).length * 1.1;

View File

@ -29,7 +29,7 @@ export class RecursiveCloner implements ICloner
{
// biome-ignore lint/suspicious/noExplicitAny: used for clone
const objArr = obj as Array<any>;
return objArr.map(v => this.clone(v)) as T;
return objArr.map((v) => this.clone(v)) as T;
}
const newObj = {};

View File

@ -1,5 +1,9 @@
export class LinkedListNode<T>
{
constructor(public value: T, public prev?: LinkedListNode<T>, public next?: LinkedListNode<T>)
constructor(
public value: T,
public prev?: LinkedListNode<T>,
public next?: LinkedListNode<T>,
)
{}
}

View File

@ -133,7 +133,11 @@ export abstract class AbstractWinstonLogger implements ILogger
await this.asyncQueue.waitFor(command);
}
public async log(data: string | Error | Record<string, unknown>, color: string, backgroundColor = ""): Promise<void>
public async log(
data: string | Error | Record<string, unknown>,
color: string,
backgroundColor = "",
): Promise<void>
{
const textColor = `${color} ${backgroundColor}`.trimEnd();
const tmpLogger = createLogger({