Formatting for services.

This commit is contained in:
Refringe 2023-11-13 11:13:25 -05:00
parent ca9ab9bcc8
commit 8576929404
No known key found for this signature in database
GPG Key ID: 64E03E5F892C6F9E
47 changed files with 1325 additions and 739 deletions

View File

@ -3,16 +3,20 @@ import { inject, injectable } from "tsyringe";
import { BotHelper } from "@spt-aki/helpers/BotHelper"; import { BotHelper } from "@spt-aki/helpers/BotHelper";
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper"; import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
import { import {
EquipmentChances, Generation, EquipmentChances,
Generation,
GenerationData, GenerationData,
IBotType, IBotType,
ModsChances ModsChances,
} from "@spt-aki/models/eft/common/tables/IBotType"; } from "@spt-aki/models/eft/common/tables/IBotType";
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes"; import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
import { BotGenerationDetails } from "@spt-aki/models/spt/bots/BotGenerationDetails"; import { BotGenerationDetails } from "@spt-aki/models/spt/bots/BotGenerationDetails";
import { import {
AdjustmentDetails, EquipmentFilterDetails, EquipmentFilters, IBotConfig, AdjustmentDetails,
WeightingAdjustmentDetails EquipmentFilterDetails,
EquipmentFilters,
IBotConfig,
WeightingAdjustmentDetails,
} from "@spt-aki/models/spt/config/IBotConfig"; } from "@spt-aki/models/spt/config/IBotConfig";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { ConfigServer } from "@spt-aki/servers/ConfigServer"; import { ConfigServer } from "@spt-aki/servers/ConfigServer";
@ -27,7 +31,7 @@ export class BotEquipmentFilterService
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("BotHelper") protected botHelper: BotHelper, @inject("BotHelper") protected botHelper: BotHelper,
@inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("ProfileHelper") protected profileHelper: ProfileHelper,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); this.botConfig = this.configServer.getConfig(ConfigTypes.BOT);
@ -41,17 +45,25 @@ export class BotEquipmentFilterService
* @param botLevel Level of the bot * @param botLevel Level of the bot
* @param botGenerationDetails details on how to generate a bot * @param botGenerationDetails details on how to generate a bot
*/ */
public filterBotEquipment(sessionId: string, baseBotNode: IBotType, botLevel: number, botGenerationDetails: BotGenerationDetails): void public filterBotEquipment(
sessionId: string,
baseBotNode: IBotType,
botLevel: number,
botGenerationDetails: BotGenerationDetails,
): void
{ {
const pmcProfile = this.profileHelper.getPmcProfile(sessionId); const pmcProfile = this.profileHelper.getPmcProfile(sessionId);
const botRole = (botGenerationDetails.isPmc) const botRole = (botGenerationDetails.isPmc) ?
? "pmc" "pmc" :
: botGenerationDetails.role; botGenerationDetails.role;
const botEquipmentBlacklist = this.getBotEquipmentBlacklist(botRole, botLevel); const botEquipmentBlacklist = this.getBotEquipmentBlacklist(botRole, botLevel);
const botEquipmentWhitelist = this.getBotEquipmentWhitelist(botRole, botLevel); const botEquipmentWhitelist = this.getBotEquipmentWhitelist(botRole, botLevel);
const botWeightingAdjustments = this.getBotWeightingAdjustments(botRole, botLevel); const botWeightingAdjustments = this.getBotWeightingAdjustments(botRole, botLevel);
const botWeightingAdjustmentsByPlayerLevel = this.getBotWeightingAdjustmentsByPlayerLevel(botRole, pmcProfile.Info.Level); const botWeightingAdjustmentsByPlayerLevel = this.getBotWeightingAdjustmentsByPlayerLevel(
botRole,
pmcProfile.Info.Level,
);
const botEquipConfig = this.botConfig.equipment[botRole]; const botEquipConfig = this.botConfig.equipment[botRole];
const randomisationDetails = this.botHelper.getBotRandomizationDetails(botLevel, botEquipConfig); const randomisationDetails = this.botHelper.getBotRandomizationDetails(botLevel, botEquipConfig);
@ -107,7 +119,10 @@ export class BotEquipmentFilterService
* @param generationChanges Changes to apply * @param generationChanges Changes to apply
* @param baseBotGeneration dictionary to update * @param baseBotGeneration dictionary to update
*/ */
protected adjustGenerationChances(generationChanges: Record<string, GenerationData>, baseBotGeneration: Generation): void protected adjustGenerationChances(
generationChanges: Record<string, GenerationData>,
baseBotGeneration: Generation,
): void
{ {
if (!generationChanges) if (!generationChanges)
{ {
@ -159,12 +174,17 @@ export class BotEquipmentFilterService
const blacklistDetailsForBot = this.botEquipmentConfig[botRole]; const blacklistDetailsForBot = this.botEquipmentConfig[botRole];
// No equipment blacklist found, skip // No equipment blacklist found, skip
if (!blacklistDetailsForBot || Object.keys(blacklistDetailsForBot).length === 0 || !blacklistDetailsForBot.blacklist) if (
!blacklistDetailsForBot || Object.keys(blacklistDetailsForBot).length === 0 ||
!blacklistDetailsForBot.blacklist
)
{ {
return null; 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
);
} }
/** /**
@ -183,7 +203,9 @@ export class BotEquipmentFilterService
return null; 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
);
} }
/** /**
@ -197,12 +219,17 @@ export class BotEquipmentFilterService
const botEquipmentConfig = this.botEquipmentConfig[botRole]; const botEquipmentConfig = this.botEquipmentConfig[botRole];
// No config found, skip // No config found, skip
if (!botEquipmentConfig || Object.keys(botEquipmentConfig).length === 0 || !botEquipmentConfig.weightingAdjustmentsByBotLevel) if (
!botEquipmentConfig || Object.keys(botEquipmentConfig).length === 0 ||
!botEquipmentConfig.weightingAdjustmentsByBotLevel
)
{ {
return null; 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
);
} }
/** /**
@ -216,12 +243,17 @@ export class BotEquipmentFilterService
const botEquipmentConfig = this.botEquipmentConfig[botRole]; const botEquipmentConfig = this.botEquipmentConfig[botRole];
// No config found, skip // No config found, skip
if (!botEquipmentConfig || Object.keys(botEquipmentConfig).length === 0 || !botEquipmentConfig.weightingAdjustmentsByPlayerLevel) if (
!botEquipmentConfig || Object.keys(botEquipmentConfig).length === 0 ||
!botEquipmentConfig.weightingAdjustmentsByPlayerLevel
)
{ {
return null; 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
);
} }
/** /**
@ -231,7 +263,11 @@ export class BotEquipmentFilterService
* @param blacklist equipment blacklist * @param blacklist equipment blacklist
* @returns Filtered bot file * @returns Filtered bot file
*/ */
protected filterEquipment(baseBotNode: IBotType, blacklist: EquipmentFilterDetails, whitelist: EquipmentFilterDetails): void protected filterEquipment(
baseBotNode: IBotType,
blacklist: EquipmentFilterDetails,
whitelist: EquipmentFilterDetails,
): void
{ {
if (whitelist) if (whitelist)
{ {
@ -247,7 +283,9 @@ export class BotEquipmentFilterService
} }
// Filter equipment slot items to just items in whitelist // Filter equipment slot items to just items in whitelist
baseBotNode.inventory.equipment[equipmentSlotKey] = Object.keys(botEquipment).filter((tpl) => whitelistEquipmentForSlot.includes(tpl)).reduce( (res, key) => (res[key] = botEquipment[key], res), {} ); baseBotNode.inventory.equipment[equipmentSlotKey] = Object.keys(botEquipment).filter((tpl) =>
whitelistEquipmentForSlot.includes(tpl)
).reduce((res, key) => (res[key] = botEquipment[key], res), {});
} }
return; return;
@ -267,7 +305,9 @@ export class BotEquipmentFilterService
} }
// Filter equipment slot items to just items not in blacklist // Filter equipment slot items to just items not in blacklist
baseBotNode.inventory.equipment[equipmentSlotKey] = Object.keys(botEquipment).filter((tpl) => !equipmentSlotBlacklist.includes(tpl)).reduce( (res, key) => (res[key] = botEquipment[key], res), {} ); baseBotNode.inventory.equipment[equipmentSlotKey] = Object.keys(botEquipment).filter((tpl) =>
!equipmentSlotBlacklist.includes(tpl)
).reduce((res, key) => (res[key] = botEquipment[key], res), {});
} }
} }
} }
@ -280,7 +320,11 @@ export class BotEquipmentFilterService
* @param whitelist equipment on this list should be used exclusively * @param whitelist equipment on this list should be used exclusively
* @returns Filtered bot file * @returns Filtered bot file
*/ */
protected filterCartridges(baseBotNode: IBotType, blacklist: EquipmentFilterDetails, whitelist: EquipmentFilterDetails): void protected filterCartridges(
baseBotNode: IBotType,
blacklist: EquipmentFilterDetails,
whitelist: EquipmentFilterDetails,
): void
{ {
if (whitelist) if (whitelist)
{ {
@ -296,7 +340,9 @@ export class BotEquipmentFilterService
} }
// Filter caliber slot items to just items in whitelist // Filter caliber slot items to just items in whitelist
baseBotNode.inventory.Ammo[ammoCaliberKey] = Object.keys(botAmmo).filter((tpl) => whitelist.cartridge[ammoCaliberKey].includes(tpl)).reduce( (res, key) => (res[key] = botAmmo[key], res), {} ); baseBotNode.inventory.Ammo[ammoCaliberKey] = Object.keys(botAmmo).filter((tpl) =>
whitelist.cartridge[ammoCaliberKey].includes(tpl)
).reduce((res, key) => (res[key] = botAmmo[key], res), {});
} }
return; return;
@ -316,7 +362,9 @@ export class BotEquipmentFilterService
} }
// Filter cartridge slot items to just items not in blacklist // Filter cartridge slot items to just items not in blacklist
baseBotNode.inventory.Ammo[ammoCaliberKey] = Object.keys(botAmmo).filter((tpl) => !cartridgeCaliberBlacklist.includes(tpl)).reduce( (res, key) => (res[key] = botAmmo[key], res), {} ); baseBotNode.inventory.Ammo[ammoCaliberKey] = Object.keys(botAmmo).filter((tpl) =>
!cartridgeCaliberBlacklist.includes(tpl)
).reduce((res, key) => (res[key] = botAmmo[key], res), {});
} }
} }
} }
@ -326,7 +374,11 @@ export class BotEquipmentFilterService
* @param weightingAdjustments Weighting change to apply to bot * @param weightingAdjustments Weighting change to apply to bot
* @param botItemPool Bot item dictionary to adjust * @param botItemPool Bot item dictionary to adjust
*/ */
protected adjustWeighting(weightingAdjustments: AdjustmentDetails, botItemPool: Record<string, any>, showEditWarnings = true): void protected adjustWeighting(
weightingAdjustments: AdjustmentDetails,
botItemPool: Record<string, any>,
showEditWarnings = true,
): void
{ {
if (!weightingAdjustments) if (!weightingAdjustments)
{ {
@ -361,12 +413,13 @@ export class BotEquipmentFilterService
{ {
if (showEditWarnings) if (showEditWarnings)
{ {
this.logger.warning(`Tried to edit a non-existent item for slot: ${poolAdjustmentKey} ${itemToEditKey}`); this.logger.warning(
`Tried to edit a non-existent item for slot: ${poolAdjustmentKey} ${itemToEditKey}`,
);
} }
} }
} }
} }
} }
} }
} }

View File

@ -28,7 +28,7 @@ export class BotEquipmentModPoolService
@inject("ItemHelper") protected itemHelper: ItemHelper, @inject("ItemHelper") protected itemHelper: ItemHelper,
@inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); this.botConfig = this.configServer.getConfig(ConfigTypes.BOT);
@ -48,12 +48,17 @@ export class BotEquipmentModPoolService
} }
// Get weapon or gear pool // Get weapon or gear pool
const pool = (poolType === "weapon" ? this.weaponModPool : this.gearModPool); const pool = poolType === "weapon" ? this.weaponModPool : this.gearModPool;
for (const item of items) for (const item of items)
{ {
if (!item._props) if (!item._props)
{ {
this.logger.error(this.localisationService.getText("bot-item_missing_props_property", {itemTpl: item._id, name: item._name})); this.logger.error(
this.localisationService.getText("bot-item_missing_props_property", {
itemTpl: item._id,
name: item._name,
}),
);
continue; continue;
} }
@ -87,7 +92,7 @@ export class BotEquipmentModPoolService
} }
// only add item to pool if it doesnt already exist // 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); pool[item._id][slot._name].push(itemToAdd);
@ -181,7 +186,9 @@ export class BotEquipmentModPoolService
*/ */
protected generateWeaponPool(): void 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"); this.generatePool(weapons, "weapon");
// Flag pool as being complete // Flag pool as being complete
@ -193,7 +200,9 @@ export class BotEquipmentModPoolService
*/ */
protected generateGearPool(): void protected generateGearPool(): void
{ {
const gear = Object.values(this.databaseServer.getTables().templates.items).filter(x => x._type === "Item" && this.itemHelper.isOfBaseclass(x._id, BaseClasses.ARMOREDEQUIPMENT)); const gear = Object.values(this.databaseServer.getTables().templates.items).filter((x) =>
x._type === "Item" && this.itemHelper.isOfBaseclass(x._id, BaseClasses.ARMOREDEQUIPMENT)
);
this.generatePool(gear, "gear"); this.generatePool(gear, "gear");
// Flag pool as being complete // Flag pool as being complete

View File

@ -17,9 +17,9 @@ export class BotGenerationCacheService
@inject("RandomUtil") protected randomUtil: RandomUtil, @inject("RandomUtil") protected randomUtil: RandomUtil,
@inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("JsonUtil") protected jsonUtil: JsonUtil,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("BotHelper") protected botHelper: BotHelper @inject("BotHelper") protected botHelper: BotHelper,
) )
{ } {}
/** /**
* Store array of bots in cache, shuffle results before storage * Store array of bots in cache, shuffle results before storage

View File

@ -24,7 +24,7 @@ export class BotLootCacheService
@inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("PMCLootGenerator") protected pmcLootGenerator: PMCLootGenerator, @inject("PMCLootGenerator") protected pmcLootGenerator: PMCLootGenerator,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService @inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService,
) )
{ {
this.clearCache(); this.clearCache();
@ -46,7 +46,12 @@ export class BotLootCacheService
* @param botJsonTemplate Base json db file for the bot having its loot generated * @param botJsonTemplate Base json db file for the bot having its loot generated
* @returns ITemplateItem array * @returns ITemplateItem array
*/ */
public getLootFromCache(botRole: string, isPmc: boolean, lootType: LootCacheType, botJsonTemplate: IBotType): ITemplateItem[] public getLootFromCache(
botRole: string,
isPmc: boolean,
lootType: LootCacheType,
botJsonTemplate: IBotType,
): ITemplateItem[]
{ {
if (!this.botRoleExistsInCache(botRole)) if (!this.botRoleExistsInCache(botRole))
{ {
@ -75,7 +80,13 @@ export class BotLootCacheService
case LootCacheType.STIM_ITEMS: case LootCacheType.STIM_ITEMS:
return this.lootCache[botRole].stimItems; return this.lootCache[botRole].stimItems;
default: default:
this.logger.error(this.localisationService.getText("bot-loot_type_not_found", {lootType: lootType, botRole: botRole, isPmc: isPmc})); this.logger.error(
this.localisationService.getText("bot-loot_type_not_found", {
lootType: lootType,
botRole: botRole,
isPmc: isPmc,
}),
);
break; break;
} }
} }
@ -154,61 +165,67 @@ export class BotLootCacheService
this.sortPoolByRagfairPrice(combinedPoolTemplates); this.sortPoolByRagfairPrice(combinedPoolTemplates);
// use whitelist if array has values, otherwise process above sorted pools // use whitelist if array has values, otherwise process above sorted pools
const specialLootItems = (botJsonTemplate.generation.items.specialItems.whitelist?.length > 0) const specialLootItems = (botJsonTemplate.generation.items.specialItems.whitelist?.length > 0) ?
? botJsonTemplate.generation.items.specialItems.whitelist.map(x => this.itemHelper.getItem(x)[1]) botJsonTemplate.generation.items.specialItems.whitelist.map((x) => this.itemHelper.getItem(x)[1]) :
: specialLootTemplates.filter(template => specialLootTemplates.filter((template) =>
!(this.isBulletOrGrenade(template._props) !(this.isBulletOrGrenade(template._props) ||
|| this.isMagazine(template._props))); this.isMagazine(template._props))
);
const healingItems = (botJsonTemplate.generation.items.healing.whitelist?.length > 0) const healingItems = (botJsonTemplate.generation.items.healing.whitelist?.length > 0) ?
? botJsonTemplate.generation.items.healing.whitelist.map(x => this.itemHelper.getItem(x)[1]) botJsonTemplate.generation.items.healing.whitelist.map((x) => this.itemHelper.getItem(x)[1]) :
: combinedPoolTemplates.filter(template => combinedPoolTemplates.filter((template) =>
this.isMedicalItem(template._props) this.isMedicalItem(template._props) &&
&& template._parent !== BaseClasses.STIMULATOR template._parent !== BaseClasses.STIMULATOR &&
&& template._parent !== BaseClasses.DRUGS); template._parent !== BaseClasses.DRUGS
);
const drugItems = (botJsonTemplate.generation.items.drugs.whitelist?.length > 0) const drugItems = (botJsonTemplate.generation.items.drugs.whitelist?.length > 0) ?
? botJsonTemplate.generation.items.drugs.whitelist.map(x => this.itemHelper.getItem(x)[1]) botJsonTemplate.generation.items.drugs.whitelist.map((x) => this.itemHelper.getItem(x)[1]) :
: combinedPoolTemplates.filter(template => combinedPoolTemplates.filter((template) =>
this.isMedicalItem(template._props) this.isMedicalItem(template._props) &&
&& template._parent === BaseClasses.DRUGS); template._parent === BaseClasses.DRUGS
);
const stimItems = (botJsonTemplate.generation.items.stims.whitelist?.length > 0) const stimItems = (botJsonTemplate.generation.items.stims.whitelist?.length > 0) ?
? botJsonTemplate.generation.items.stims.whitelist.map(x => this.itemHelper.getItem(x)[1]) botJsonTemplate.generation.items.stims.whitelist.map((x) => this.itemHelper.getItem(x)[1]) :
: combinedPoolTemplates.filter(template => combinedPoolTemplates.filter((template) =>
this.isMedicalItem(template._props) this.isMedicalItem(template._props) &&
&& template._parent === BaseClasses.STIMULATOR); template._parent === BaseClasses.STIMULATOR
);
const grenadeItems = (botJsonTemplate.generation.items.grenades.whitelist?.length > 0) const grenadeItems = (botJsonTemplate.generation.items.grenades.whitelist?.length > 0) ?
? botJsonTemplate.generation.items.grenades.whitelist.map(x => this.itemHelper.getItem(x)[1]) botJsonTemplate.generation.items.grenades.whitelist.map((x) => this.itemHelper.getItem(x)[1]) :
: combinedPoolTemplates.filter(template => combinedPoolTemplates.filter((template) => this.isGrenade(template._props));
this.isGrenade(template._props));
// Get loot items (excluding magazines, bullets, grenades and healing items) // Get loot items (excluding magazines, bullets, grenades and healing items)
const backpackLootItems = backpackLootTemplates.filter(template => const backpackLootItems = backpackLootTemplates.filter((template) =>
// biome-ignore lint/complexity/useSimplifiedLogicExpression: <explanation> // biome-ignore lint/complexity/useSimplifiedLogicExpression: <explanation>
!this.isBulletOrGrenade(template._props) !this.isBulletOrGrenade(template._props) &&
&& !this.isMagazine(template._props) !this.isMagazine(template._props) &&
//&& !this.isMedicalItem(template._props) // Disabled for now as followSanitar has a lot of med items as loot // && !this.isMedicalItem(template._props) // Disabled for now as followSanitar has a lot of med items as loot
&& !this.isGrenade(template._props)); !this.isGrenade(template._props)
);
// Get pocket loot // Get pocket loot
const pocketLootItems = pocketLootTemplates.filter(template => const pocketLootItems = pocketLootTemplates.filter((template) =>
// biome-ignore lint/complexity/useSimplifiedLogicExpression: <explanation> // biome-ignore lint/complexity/useSimplifiedLogicExpression: <explanation>
!this.isBulletOrGrenade(template._props) !this.isBulletOrGrenade(template._props) &&
&& !this.isMagazine(template._props) !this.isMagazine(template._props) &&
&& !this.isMedicalItem(template._props) !this.isMedicalItem(template._props) &&
&& !this.isGrenade(template._props) !this.isGrenade(template._props) &&
&& ("Height" in template._props) ("Height" in template._props) &&
&& ("Width" in template._props)); ("Width" in template._props)
);
// Get vest loot items // Get vest loot items
const vestLootItems = vestLootTemplates.filter(template => const vestLootItems = vestLootTemplates.filter((template) =>
// biome-ignore lint/complexity/useSimplifiedLogicExpression: <explanation> // biome-ignore lint/complexity/useSimplifiedLogicExpression: <explanation>
!this.isBulletOrGrenade(template._props) !this.isBulletOrGrenade(template._props) &&
&& !this.isMagazine(template._props) !this.isMagazine(template._props) &&
&& !this.isMedicalItem(template._props) !this.isMedicalItem(template._props) &&
&& !this.isGrenade(template._props)); !this.isGrenade(template._props)
);
this.lootCache[botRole].healingItems = healingItems; this.lootCache[botRole].healingItems = healingItems;
this.lootCache[botRole].drugItems = drugItems; this.lootCache[botRole].drugItems = drugItems;
@ -227,7 +244,12 @@ export class BotLootCacheService
*/ */
protected sortPoolByRagfairPrice(poolToSort: ITemplateItem[]): void protected sortPoolByRagfairPrice(poolToSort: ITemplateItem[]): void
{ {
poolToSort.sort((a, b) => this.compareByValue(this.ragfairPriceService.getFleaPriceForItem(a._id), this.ragfairPriceService.getFleaPriceForItem(b._id))); poolToSort.sort((a, b) =>
this.compareByValue(
this.ragfairPriceService.getFleaPriceForItem(a._id),
this.ragfairPriceService.getFleaPriceForItem(b._id),
)
);
} }
/** /**
@ -246,7 +268,7 @@ export class BotLootCacheService
const mergedItemPools = [...combinedItemPool, ...itemsToAdd]; const mergedItemPools = [...combinedItemPool, ...itemsToAdd];
// Save only unique array values // Save only unique array values
const uniqueResults = [... new Set([].concat(...mergedItemPools))]; const uniqueResults = [...new Set([].concat(...mergedItemPools))];
combinedItemPool.splice(0, combinedItemPool.length); combinedItemPool.splice(0, combinedItemPool.length);
combinedItemPool.push(...uniqueResults); combinedItemPool.push(...uniqueResults);
} }
@ -317,7 +339,7 @@ export class BotLootCacheService
grenadeItems: [], grenadeItems: [],
drugItems: [], drugItems: [],
healingItems: [], healingItems: [],
stimItems: [] stimItems: [],
}; };
} }
@ -355,5 +377,4 @@ export class BotLootCacheService
return 0; return 0;
} }
} }

View File

@ -32,7 +32,7 @@ export class BotWeaponModLimitService
constructor( constructor(
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("ConfigServer") protected configServer: ConfigServer, @inject("ConfigServer") protected configServer: ConfigServer,
@inject("ItemHelper") protected itemHelper: ItemHelper @inject("ItemHelper") protected itemHelper: ItemHelper,
) )
{ {
this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); this.botConfig = this.configServer.getConfig(ConfigTypes.BOT);
@ -48,10 +48,20 @@ export class BotWeaponModLimitService
return { return {
scope: {count: 0}, scope: {count: 0},
scopeMax: this.botConfig.equipment[botRole]?.weaponModLimits?.scopeLimit, scopeMax: this.botConfig.equipment[botRole]?.weaponModLimits?.scopeLimit,
scopeBaseTypes: [BaseClasses.OPTIC_SCOPE, BaseClasses.ASSAULT_SCOPE, BaseClasses.COLLIMATOR, BaseClasses.COMPACT_COLLIMATOR, BaseClasses.SPECIAL_SCOPE], scopeBaseTypes: [
BaseClasses.OPTIC_SCOPE,
BaseClasses.ASSAULT_SCOPE,
BaseClasses.COLLIMATOR,
BaseClasses.COMPACT_COLLIMATOR,
BaseClasses.SPECIAL_SCOPE,
],
flashlightLaser: {count: 0}, flashlightLaser: {count: 0},
flashlightLaserMax: this.botConfig.equipment[botRole]?.weaponModLimits?.lightLaserLimit, flashlightLaserMax: this.botConfig.equipment[botRole]?.weaponModLimits?.lightLaserLimit,
flashlgihtLaserBaseTypes: [BaseClasses.TACTICAL_COMBO, BaseClasses.FLASHLIGHT, BaseClasses.PORTABLE_RANGE_FINDER] flashlgihtLaserBaseTypes: [
BaseClasses.TACTICAL_COMBO,
BaseClasses.FLASHLIGHT,
BaseClasses.PORTABLE_RANGE_FINDER,
],
}; };
} }
@ -67,14 +77,28 @@ export class BotWeaponModLimitService
* @param modsParent The parent of the mod to be checked * @param modsParent The parent of the mod to be checked
* @returns true if over item limit * @returns true if over item limit
*/ */
public weaponModHasReachedLimit(botRole: string, modTemplate: ITemplateItem, modLimits: BotModLimits, modsParent: ITemplateItem, weapon: Item[]): boolean public weaponModHasReachedLimit(
botRole: string,
modTemplate: ITemplateItem,
modLimits: BotModLimits,
modsParent: ITemplateItem,
weapon: Item[],
): boolean
{ {
// If mod or mods parent is the NcSTAR MPR45 Backup mount, allow it as it looks cool // If mod or mods parent is the NcSTAR MPR45 Backup mount, allow it as it looks cool
const ncSTARTpl = "5649a2464bdc2d91118b45a8"; const ncSTARTpl = "5649a2464bdc2d91118b45a8";
if (modsParent._id === ncSTARTpl || modTemplate._id === ncSTARTpl) if (modsParent._id === ncSTARTpl || modTemplate._id === ncSTARTpl)
{ {
// If weapon already has a longer ranged scope on it, allow ncstar to be spawned // If weapon already has a longer ranged scope on it, allow ncstar to be spawned
if (weapon.some(x => this.itemHelper.isOfBaseclasses(x._tpl, [BaseClasses.ASSAULT_SCOPE, BaseClasses.OPTIC_SCOPE, BaseClasses.SPECIAL_SCOPE]))) if (
weapon.some((x) =>
this.itemHelper.isOfBaseclasses(x._tpl, [
BaseClasses.ASSAULT_SCOPE,
BaseClasses.OPTIC_SCOPE,
BaseClasses.SPECIAL_SCOPE,
])
)
)
{ {
return false; return false;
} }
@ -96,10 +120,12 @@ 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) // 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) if (
&& modTemplate._props.Slots.some(x => x._name === "mod_scope") this.itemHelper.isOfBaseclass(modTemplate._id, BaseClasses.MOUNT) &&
&& modTemplate._props.Slots.length === 1 modTemplate._props.Slots.some((x) => x._name === "mod_scope") &&
&& modLimits.scope.count >= modLimits.scopeMax) modTemplate._props.Slots.length === 1 &&
modLimits.scope.count >= modLimits.scopeMax
)
{ {
return true; return true;
} }
@ -108,14 +134,21 @@ export class BotWeaponModLimitService
const modIsLightOrLaser = this.itemHelper.isOfBaseclasses(modTemplate._id, modLimits.flashlgihtLaserBaseTypes); const modIsLightOrLaser = this.itemHelper.isOfBaseclasses(modTemplate._id, modLimits.flashlgihtLaserBaseTypes);
if (modIsLightOrLaser) if (modIsLightOrLaser)
{ {
return this.weaponModLimitReached(modTemplate._id, modLimits.flashlightLaser, modLimits.flashlightLaserMax, botRole); return this.weaponModLimitReached(
modTemplate._id,
modLimits.flashlightLaser,
modLimits.flashlightLaserMax,
botRole,
);
} }
// Mod is a mount that can hold only flashlights ad limit is reached (dont want to add empty mounts if limit is reached) // 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) if (
&& modTemplate._props.Slots.some(x => x._name === "mod_flashlight") this.itemHelper.isOfBaseclass(modTemplate._id, BaseClasses.MOUNT) &&
&& modTemplate._props.Slots.length === 1 modTemplate._props.Slots.some((x) => x._name === "mod_flashlight") &&
&& modLimits.scope.count >= modLimits.scopeMax) modTemplate._props.Slots.length === 1 &&
modLimits.scope.count >= modLimits.scopeMax
)
{ {
return true; return true;
} }
@ -131,8 +164,12 @@ export class BotWeaponModLimitService
* @param botRole role of bot we're checking weapon of * @param botRole role of bot we're checking weapon of
* @returns true if limit reached * @returns true if limit reached
*/ */
// eslint-disable-next-line @typescript-eslint/no-unused-vars protected weaponModLimitReached(
protected weaponModLimitReached(modTpl: string, currentCount: { count: number; }, maxLimit: number, botRole: string): boolean modTpl: string,
currentCount: {count: number;},
maxLimit: number,
botRole: string,
): boolean
{ {
// No value or 0 // No value or 0
if (!maxLimit) if (!maxLimit)
@ -143,7 +180,7 @@ export class BotWeaponModLimitService
// Has mod limit for bot type been reached // Has mod limit for bot type been reached
if (currentCount.count >= maxLimit) if (currentCount.count >= maxLimit)
{ {
//this.logger.debug(`[${botRole}] scope limit reached! tried to add ${modTpl} but scope count is ${currentCount.count}`); // this.logger.debug(`[${botRole}] scope limit reached! tried to add ${modTpl} but scope count is ${currentCount.count}`);
return true; return true;
} }

View File

@ -19,7 +19,7 @@ export class CustomLocationWaveService
@inject("RandomUtil") protected randomUtil: RandomUtil, @inject("RandomUtil") protected randomUtil: RandomUtil,
@inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("JsonUtil") protected jsonUtil: JsonUtil,
@inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION); this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION);
@ -76,13 +76,15 @@ export class CustomLocationWaveService
const location: ILocationBase = this.databaseServer.getTables().locations[mapKey].base; const location: ILocationBase = this.databaseServer.getTables().locations[mapKey].base;
for (const bossWave of bossWavesToApply[mapKey]) 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 // Already exists, skip
continue; continue;
} }
location.BossLocationSpawn.push(bossWave); location.BossLocationSpawn.push(bossWave);
this.logger.debug(`Added custom boss wave to ${mapKey} of type ${bossWave.BossName}, time: ${bossWave.Time}, chance: ${bossWave.BossChance}, zone: ${bossWave.BossZone}`); this.logger.debug(
`Added custom boss wave to ${mapKey} of type ${bossWave.BossName}, time: ${bossWave.Time}, chance: ${bossWave.BossChance}, zone: ${bossWave.BossZone}`,
);
} }
} }
@ -91,7 +93,7 @@ export class CustomLocationWaveService
const location: ILocationBase = this.databaseServer.getTables().locations[mapKey].base; const location: ILocationBase = this.databaseServer.getTables().locations[mapKey].base;
for (const normalWave of normalWavesToApply[mapKey]) 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 // Already exists, skip
continue; continue;

View File

@ -49,7 +49,7 @@ export class FenceService
@inject("PresetHelper") protected presetHelper: PresetHelper, @inject("PresetHelper") protected presetHelper: PresetHelper,
@inject("ItemFilterService") protected itemFilterService: ItemFilterService, @inject("ItemFilterService") protected itemFilterService: ItemFilterService,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER); this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER);
@ -88,13 +88,21 @@ export class FenceService
// Clone assorts so we can adjust prices before sending to client // Clone assorts so we can adjust prices before sending to client
const assort = this.jsonUtil.clone(this.fenceAssort); const assort = this.jsonUtil.clone(this.fenceAssort);
this.adjustAssortItemPrices(assort, this.getFenceInfo(pmcProfile).PriceModifier, this.traderConfig.fence.presetPriceMult); this.adjustAssortItemPrices(
assort,
this.getFenceInfo(pmcProfile).PriceModifier,
this.traderConfig.fence.presetPriceMult,
);
// merge normal fence assorts + discount assorts if player standing is large enough // merge normal fence assorts + discount assorts if player standing is large enough
if (pmcProfile.TradersInfo[Traders.FENCE].standing >= 6) if (pmcProfile.TradersInfo[Traders.FENCE].standing >= 6)
{ {
const discountAssort = this.jsonUtil.clone(this.fenceDiscountAssort); const discountAssort = this.jsonUtil.clone(this.fenceDiscountAssort);
this.adjustAssortItemPrices(discountAssort, this.traderConfig.fence.discountOptions.itemPriceMult, this.traderConfig.fence.discountOptions.presetPriceMult); this.adjustAssortItemPrices(
discountAssort,
this.traderConfig.fence.discountOptions.itemPriceMult,
this.traderConfig.fence.discountOptions.presetPriceMult,
);
const mergedAssorts = this.mergeAssorts(assort, discountAssort); const mergedAssorts = this.mergeAssorts(assort, discountAssort);
return mergedAssorts; return mergedAssorts;
@ -129,7 +137,7 @@ export class FenceService
* @param secondAssort assort #2 * @param secondAssort assort #2
* @returns merged assort * @returns merged assort
*/ */
protected mergeAssorts(firstAssort: ITraderAssort,secondAssort: ITraderAssort): ITraderAssort protected mergeAssorts(firstAssort: ITraderAssort, secondAssort: ITraderAssort): ITraderAssort
{ {
for (const itemId in secondAssort.barter_scheme) for (const itemId in secondAssort.barter_scheme)
{ {
@ -156,14 +164,19 @@ export class FenceService
* @param modifier value to multiply item price by * @param modifier value to multiply item price by
* @param presetModifier value to multiply preset price by * @param presetModifier value to multiply preset price by
*/ */
protected adjustItemPriceByModifier(item: Item, assort: ITraderAssort, modifier: number, presetModifier: number): void protected adjustItemPriceByModifier(
item: Item,
assort: ITraderAssort,
modifier: number,
presetModifier: number,
): void
{ {
// Is preset // Is preset
if (item.upd.sptPresetId) if (item.upd.sptPresetId)
{ {
if (assort.barter_scheme[item._id]) if (assort.barter_scheme[item._id])
{ {
assort.barter_scheme[item._id][0][0].count *= (modifier + presetModifier); assort.barter_scheme[item._id][0][0].count *= modifier + presetModifier;
} }
} }
else if (assort.barter_scheme[item._id]) else if (assort.barter_scheme[item._id])
@ -200,7 +213,9 @@ export class FenceService
public performPartialRefresh(): void public performPartialRefresh(): void
{ {
let itemCountToReplace = this.getCountOfItemsToReplace(this.traderConfig.fence.assortSize); let itemCountToReplace = this.getCountOfItemsToReplace(this.traderConfig.fence.assortSize);
const discountItemCountToReplace = this.getCountOfItemsToReplace(this.traderConfig.fence.discountOptions.assortSize); const discountItemCountToReplace = this.getCountOfItemsToReplace(
this.traderConfig.fence.discountOptions.assortSize,
);
// Iterate x times to remove items (only remove if assort has items) // Iterate x times to remove items (only remove if assort has items)
if (this.fenceAssort?.items?.length > 0) if (this.fenceAssort?.items?.length > 0)
@ -220,7 +235,6 @@ export class FenceService
} }
} }
itemCountToReplace = this.getCountOfItemsToGenerate(itemCountToReplace); itemCountToReplace = this.getCountOfItemsToGenerate(itemCountToReplace);
const newItems = this.createBaseTraderAssortItem(); const newItems = this.createBaseTraderAssortItem();
@ -253,7 +267,8 @@ export class FenceService
// Add loyalty items to fence discount assorts loyalty object // Add loyalty items to fence discount assorts loyalty object
for (const loyaltyItemKey in newDiscountItems.loyal_level_items) for (const loyaltyItemKey in newDiscountItems.loyal_level_items)
{ {
this.fenceDiscountAssort.loyal_level_items[loyaltyItemKey] = newDiscountItems.loyal_level_items[loyaltyItemKey]; this.fenceDiscountAssort.loyal_level_items[loyaltyItemKey] =
newDiscountItems.loyal_level_items[loyaltyItemKey];
} }
this.incrementPartialRefreshTime(); this.incrementPartialRefreshTime();
@ -264,7 +279,8 @@ export class FenceService
*/ */
protected incrementPartialRefreshTime(): void protected incrementPartialRefreshTime(): void
{ {
this.nextMiniRefreshTimestamp = this.timeUtil.getTimestamp() + this.traderConfig.fence.partialRefreshTimeSeconds; this.nextMiniRefreshTimestamp = this.timeUtil.getTimestamp() +
this.traderConfig.fence.partialRefreshTimeSeconds;
} }
/** /**
@ -278,14 +294,14 @@ export class FenceService
const desiredTotalCount = this.traderConfig.fence.assortSize; const desiredTotalCount = this.traderConfig.fence.assortSize;
const actualTotalCount = this.fenceAssort.items.reduce((count, item) => const actualTotalCount = this.fenceAssort.items.reduce((count, item) =>
{ {
return item.slotId === "hideout" return item.slotId === "hideout" ?
? count + 1 count + 1 :
: count; count;
}, 0); }, 0);
return actualTotalCount < desiredTotalCount return actualTotalCount < desiredTotalCount ?
? (desiredTotalCount - actualTotalCount) + existingItemCountToReplace (desiredTotalCount - actualTotalCount) + existingItemCountToReplace :
: existingItemCountToReplace; existingItemCountToReplace;
} }
/** /**
@ -295,9 +311,11 @@ export class FenceService
protected removeRandomItemFromAssorts(assort: ITraderAssort): void protected removeRandomItemFromAssorts(assort: ITraderAssort): void
{ {
// Only remove if assort has items // Only remove if assort has items
if (!assort.items.some(x => x.slotId === "hideout")) if (!assort.items.some((x) => x.slotId === "hideout"))
{ {
this.logger.warning("Unable to remove random assort from trader as they have no assorts with a slotid of `hideout`"); this.logger.warning(
"Unable to remove random assort from trader as they have no assorts with a slotid of `hideout`",
);
return; return;
} }
@ -308,12 +326,12 @@ export class FenceService
itemToRemove = this.randomUtil.getArrayValue(assort.items); itemToRemove = this.randomUtil.getArrayValue(assort.items);
} }
const indexOfItemToRemove = assort.items.findIndex(x => x._id === itemToRemove._id); const indexOfItemToRemove = assort.items.findIndex((x) => x._id === itemToRemove._id);
assort.items.splice(indexOfItemToRemove, 1); assort.items.splice(indexOfItemToRemove, 1);
// Clean up any mods if item removed was a weapon // Clean up any mods if item removed was a weapon
// TODO: also check for mods attached down the item chain // TODO: also check for mods attached down the item chain
assort.items = assort.items.filter(x => x.parentId !== itemToRemove._id); assort.items = assort.items.filter((x) => x.parentId !== itemToRemove._id);
delete assort.barter_scheme[itemToRemove._id]; delete assort.barter_scheme[itemToRemove._id];
delete assort.loyal_level_items[itemToRemove._id]; delete assort.loyal_level_items[itemToRemove._id];
@ -376,7 +394,7 @@ export class FenceService
barter_scheme: {}, barter_scheme: {},
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
loyal_level_items: {}, loyal_level_items: {},
nextResupply: this.getNextFenceUpdateTimestamp() nextResupply: this.getNextFenceUpdateTimestamp(),
}; };
} }
@ -400,7 +418,14 @@ export class FenceService
this.addPresets(randomisedPresetCount, defaultWeaponPresets, assorts, loyaltyLevel); this.addPresets(randomisedPresetCount, defaultWeaponPresets, assorts, loyaltyLevel);
} }
protected addItemAssorts(assortCount: number, fenceAssortIds: string[], assorts: ITraderAssort, fenceAssort: ITraderAssort, itemTypeCounts: Record<string, { current: number; max: number; }>, loyaltyLevel: number): void protected addItemAssorts(
assortCount: number,
fenceAssortIds: string[],
assorts: ITraderAssort,
fenceAssort: ITraderAssort,
itemTypeCounts: Record<string, {current: number; max: number;}>,
loyaltyLevel: number,
): void
{ {
const priceLimits = this.traderConfig.fence.itemCategoryRoublePriceLimit; const priceLimits = this.traderConfig.fence.itemCategoryRoublePriceLimit;
for (let i = 0; i < assortCount; i++) for (let i = 0; i < assortCount; i++)
@ -420,7 +445,7 @@ export class FenceService
// It's a normal non-preset item // It's a normal non-preset item
if (!itemIsPreset) if (!itemIsPreset)
{ {
const desiredAssort = fenceAssort.items[fenceAssort.items.findIndex(i => i._id === itemTpl)]; const desiredAssort = fenceAssort.items[fenceAssort.items.findIndex((i) => i._id === itemTpl)];
if (!desiredAssort) if (!desiredAssort)
{ {
this.logger.error(this.localisationService.getText("fence-unable_to_find_assort_by_id", itemTpl)); this.logger.error(this.localisationService.getText("fence-unable_to_find_assort_by_id", itemTpl));
@ -481,9 +506,9 @@ export class FenceService
if (this.itemHelper.isOfBaseclass(itemDbDetails._id, BaseClasses.AMMO)) if (this.itemHelper.isOfBaseclass(itemDbDetails._id, BaseClasses.AMMO))
{ {
// No override, use stack max size from item db // No override, use stack max size from item db
return itemDbDetails._props.StackMaxSize === 1 return itemDbDetails._props.StackMaxSize === 1 ?
? 1 1 :
: this.randomUtil.getInt(itemDbDetails._props.StackMinRandom, itemDbDetails._props.StackMaxRandom); this.randomUtil.getInt(itemDbDetails._props.StackMinRandom, itemDbDetails._props.StackMaxRandom);
} }
return 1; return 1;
@ -496,7 +521,12 @@ export class FenceService
* @param assorts object to add presets to * @param assorts object to add presets to
* @param loyaltyLevel loyalty level to requre item at * @param loyaltyLevel loyalty level to requre item at
*/ */
protected addPresets(desiredPresetCount: number, defaultWeaponPresets: Record<string, IPreset>, assorts: ITraderAssort, loyaltyLevel: number): void protected addPresets(
desiredPresetCount: number,
defaultWeaponPresets: Record<string, IPreset>,
assorts: ITraderAssort,
loyaltyLevel: number,
): void
{ {
let presetCount = 0; let presetCount = 0;
const presetKeys = Object.keys(defaultWeaponPresets); const presetKeys = Object.keys(defaultWeaponPresets);
@ -512,19 +542,22 @@ export class FenceService
} }
// Skip presets we've already added // Skip presets we've already added
if (assorts.items.some(i => i.upd && i.upd.sptPresetId === preset._id)) if (assorts.items.some((i) => i.upd && i.upd.sptPresetId === preset._id))
{ {
continue; continue;
} }
// Construct weapon + mods // Construct weapon + mods
const weaponAndMods: Item[] = this.itemHelper.replaceIDs(null, this.jsonUtil.clone(defaultWeaponPresets[preset._id]._items)); const weaponAndMods: Item[] = this.itemHelper.replaceIDs(
null,
this.jsonUtil.clone(defaultWeaponPresets[preset._id]._items),
);
this.removeRandomPartsOfWeapon(weaponAndMods); this.removeRandomPartsOfWeapon(weaponAndMods);
for (let i = 0; i < weaponAndMods.length; i++) for (let i = 0; i < weaponAndMods.length; i++)
{ {
const mod = weaponAndMods[i]; const mod = weaponAndMods[i];
//build root Item info // build root Item info
if (!("parentId" in mod)) if (!("parentId" in mod))
{ {
mod._id = weaponAndMods[0]._id; mod._id = weaponAndMods[0]._id;
@ -534,7 +567,7 @@ export class FenceService
UnlimitedCount: false, UnlimitedCount: false,
StackObjectsCount: 1, StackObjectsCount: 1,
BuyRestrictionCurrent: 0, BuyRestrictionCurrent: 0,
sptPresetId: preset._id // Store preset id here so we can check it later to prevent preset dupes sptPresetId: preset._id, // Store preset id here so we can check it later to prevent preset dupes
}; };
} }
} }
@ -556,7 +589,7 @@ export class FenceService
assorts.barter_scheme[weaponAndMods[0]._id] = [[]]; assorts.barter_scheme[weaponAndMods[0]._id] = [[]];
assorts.barter_scheme[weaponAndMods[0]._id][0][0] = { assorts.barter_scheme[weaponAndMods[0]._id][0][0] = {
_tpl: Money.ROUBLES, _tpl: Money.ROUBLES,
count: Math.round(rub) count: Math.round(rub),
}; };
assorts.loyal_level_items[weaponAndMods[0]._id] = loyaltyLevel; assorts.loyal_level_items[weaponAndMods[0]._id] = loyaltyLevel;
@ -625,8 +658,8 @@ export class FenceService
// Roll from 0 to 9999, then divide it by 100: 9999 = 99.99% // Roll from 0 to 9999, then divide it by 100: 9999 = 99.99%
const randomChance = this.randomUtil.getInt(0, 9999) / 100; const randomChance = this.randomUtil.getInt(0, 9999) / 100;
return randomChance > removalChance return randomChance > removalChance &&
&& !itemsBeingDeleted.includes(weaponMod._id); !itemsBeingDeleted.includes(weaponMod._id);
} }
/** /**
@ -638,7 +671,9 @@ export class FenceService
{ {
if (!itemDetails._props) if (!itemDetails._props)
{ {
this.logger.error(`Item ${itemDetails._name} lacks a _props field, unable to randomise item: ${itemToAdjust._id}`); this.logger.error(
`Item ${itemDetails._name} lacks a _props field, unable to randomise item: ${itemToAdjust._id}`,
);
return; return;
} }
@ -647,28 +682,30 @@ export class FenceService
if ("MaxHpResource" in itemDetails._props && itemDetails._props.MaxHpResource > 0) if ("MaxHpResource" in itemDetails._props && itemDetails._props.MaxHpResource > 0)
{ {
itemToAdjust.upd.MedKit = { itemToAdjust.upd.MedKit = {
HpResource: this.randomUtil.getInt(1, itemDetails._props.MaxHpResource) HpResource: this.randomUtil.getInt(1, itemDetails._props.MaxHpResource),
}; };
} }
// Randomise armor durability // Randomise armor durability
if ((itemDetails._parent === BaseClasses.ARMOR if (
|| itemDetails._parent === BaseClasses.HEADWEAR (itemDetails._parent === BaseClasses.ARMOR ||
|| itemDetails._parent === BaseClasses.VEST itemDetails._parent === BaseClasses.HEADWEAR ||
|| itemDetails._parent === BaseClasses.ARMOREDEQUIPMENT itemDetails._parent === BaseClasses.VEST ||
|| itemDetails._parent === BaseClasses.FACECOVER) itemDetails._parent === BaseClasses.ARMOREDEQUIPMENT ||
&& itemDetails._props.MaxDurability > 0) itemDetails._parent === BaseClasses.FACECOVER) &&
itemDetails._props.MaxDurability > 0
)
{ {
const armorMaxDurabilityLimits = this.traderConfig.fence.armorMaxDurabilityPercentMinMax; const armorMaxDurabilityLimits = this.traderConfig.fence.armorMaxDurabilityPercentMinMax;
const duraMin = (armorMaxDurabilityLimits.min / 100 * itemDetails._props.MaxDurability); const duraMin = armorMaxDurabilityLimits.min / 100 * itemDetails._props.MaxDurability;
const duraMax = (armorMaxDurabilityLimits.max / 100 * itemDetails._props.MaxDurability); const duraMax = armorMaxDurabilityLimits.max / 100 * itemDetails._props.MaxDurability;
const maxDurability = this.randomUtil.getInt(duraMin, duraMax); const maxDurability = this.randomUtil.getInt(duraMin, duraMax);
const durability = this.randomUtil.getInt(1, maxDurability); const durability = this.randomUtil.getInt(1, maxDurability);
itemToAdjust.upd.Repairable = { itemToAdjust.upd.Repairable = {
Durability: durability, Durability: durability,
MaxDurability: maxDurability MaxDurability: maxDurability,
}; };
return; return;
@ -678,15 +715,15 @@ export class FenceService
if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.WEAPON)) if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.WEAPON))
{ {
const presetMaxDurabilityLimits = this.traderConfig.fence.presetMaxDurabilityPercentMinMax; const presetMaxDurabilityLimits = this.traderConfig.fence.presetMaxDurabilityPercentMinMax;
const duraMin = (presetMaxDurabilityLimits.min / 100 * itemDetails._props.MaxDurability); const duraMin = presetMaxDurabilityLimits.min / 100 * itemDetails._props.MaxDurability;
const duraMax = (presetMaxDurabilityLimits.max / 100 * itemDetails._props.MaxDurability); const duraMax = presetMaxDurabilityLimits.max / 100 * itemDetails._props.MaxDurability;
const maxDurability = this.randomUtil.getInt(duraMin, duraMax); const maxDurability = this.randomUtil.getInt(duraMin, duraMax);
const durability = this.randomUtil.getInt(1, maxDurability); const durability = this.randomUtil.getInt(1, maxDurability);
itemToAdjust.upd.Repairable = { itemToAdjust.upd.Repairable = {
Durability: durability, Durability: durability,
MaxDurability: maxDurability MaxDurability: maxDurability,
}; };
return; return;
@ -695,17 +732,20 @@ export class FenceService
if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.REPAIR_KITS)) if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.REPAIR_KITS))
{ {
itemToAdjust.upd.RepairKit = { itemToAdjust.upd.RepairKit = {
Resource: this.randomUtil.getInt(1, itemDetails._props.MaxRepairResource) Resource: this.randomUtil.getInt(1, itemDetails._props.MaxRepairResource),
}; };
return; return;
} }
// Mechanical key + has limited uses // Mechanical key + has limited uses
if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.KEY_MECHANICAL) && itemDetails._props.MaximumNumberOfUsage > 1) if (
this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.KEY_MECHANICAL) &&
itemDetails._props.MaximumNumberOfUsage > 1
)
{ {
itemToAdjust.upd.Key = { itemToAdjust.upd.Key = {
NumberOfUsages: this.randomUtil.getInt(0, itemDetails._props.MaximumNumberOfUsage - 1) NumberOfUsages: this.randomUtil.getInt(0, itemDetails._props.MaximumNumberOfUsage - 1),
}; };
return; return;
@ -718,8 +758,8 @@ export class FenceService
const resourceCurrent = this.randomUtil.getInt(1, itemDetails._props.MaxResource); const resourceCurrent = this.randomUtil.getInt(1, itemDetails._props.MaxResource);
itemToAdjust.upd.Resource = { itemToAdjust.upd.Resource = {
Value : resourceMax - resourceCurrent, Value: resourceMax - resourceCurrent,
UnitsConsumed: resourceCurrent UnitsConsumed: resourceCurrent,
}; };
} }
} }
@ -729,15 +769,15 @@ export class FenceService
* @param limits limits as defined in config * @param limits limits as defined in config
* @returns record, key: item tplId, value: current/max item count allowed * @returns record, key: item tplId, value: current/max item count allowed
*/ */
protected initItemLimitCounter(limits: Record<string, number>): Record<string, {current: number, max: number}> protected initItemLimitCounter(limits: Record<string, number>): Record<string, {current: number; max: number;}>
{ {
const itemTypeCounts: Record<string, {current: number, max: number}> = {}; const itemTypeCounts: Record<string, {current: number; max: number;}> = {};
for (const x in limits) for (const x in limits)
{ {
itemTypeCounts[x] = { itemTypeCounts[x] = {
current: 0, current: 0,
max: limits[x] max: limits[x],
}; };
} }
@ -760,7 +800,7 @@ export class FenceService
*/ */
protected getFenceRefreshTime(): number protected getFenceRefreshTime(): number
{ {
return this.traderConfig.updateTime.find(x => x.traderId === Traders.FENCE).seconds; return this.traderConfig.updateTime.find((x) => x.traderId === Traders.FENCE).seconds;
} }
/** /**
@ -802,12 +842,12 @@ export class FenceService
*/ */
public removeFenceOffer(assortIdToRemove: string): void public removeFenceOffer(assortIdToRemove: string): void
{ {
let relatedAssortIndex = this.fenceAssort.items.findIndex(i => i._id === assortIdToRemove); let relatedAssortIndex = this.fenceAssort.items.findIndex((i) => i._id === assortIdToRemove);
// No offer found in main assort, check discount items // No offer found in main assort, check discount items
if (relatedAssortIndex === -1) if (relatedAssortIndex === -1)
{ {
relatedAssortIndex = this.fenceDiscountAssort.items.findIndex(i => i._id === assortIdToRemove); relatedAssortIndex = this.fenceDiscountAssort.items.findIndex((i) => i._id === assortIdToRemove);
this.fenceDiscountAssort.items.splice(relatedAssortIndex, 1); this.fenceDiscountAssort.items.splice(relatedAssortIndex, 1);
return; return;

View File

@ -25,7 +25,7 @@ export class GiftService
@inject("HashUtil") protected hashUtil: HashUtil, @inject("HashUtil") protected hashUtil: HashUtil,
@inject("TimeUtil") protected timeUtil: TimeUtil, @inject("TimeUtil") protected timeUtil: TimeUtil,
@inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("ProfileHelper") protected profileHelper: ProfileHelper,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.giftConfig = this.configServer.getConfig(ConfigTypes.GIFTS); this.giftConfig = this.configServer.getConfig(ConfigTypes.GIFTS);
@ -77,7 +77,8 @@ export class GiftService
playerId, playerId,
giftData.localeTextId, giftData.localeTextId,
giftData.items, giftData.items,
this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours)); this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours),
);
} }
else else
{ {
@ -85,10 +86,9 @@ export class GiftService
playerId, playerId,
giftData.messageText, giftData.messageText,
giftData.items, giftData.items,
this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours)); this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours),
);
} }
} }
// Handle user messages // Handle user messages
else if (giftData.sender === GiftSenderType.USER) else if (giftData.sender === GiftSenderType.USER)
@ -98,7 +98,8 @@ export class GiftService
giftData.senderDetails, giftData.senderDetails,
giftData.messageText, giftData.messageText,
giftData.items, giftData.items,
this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours)); this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours),
);
} }
else if (giftData.sender === GiftSenderType.TRADER) else if (giftData.sender === GiftSenderType.TRADER)
{ {
@ -110,7 +111,8 @@ export class GiftService
MessageType.MESSAGE_WITH_ITEMS, MessageType.MESSAGE_WITH_ITEMS,
giftData.localeTextId, giftData.localeTextId,
giftData.items, giftData.items,
this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours)); this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours),
);
} }
else else
{ {
@ -120,7 +122,8 @@ export class GiftService
MessageType.MESSAGE_WITH_ITEMS, MessageType.MESSAGE_WITH_ITEMS,
giftData.messageText, giftData.messageText,
giftData.items, giftData.items,
this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours)); this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours),
);
} }
} }
else else
@ -130,10 +133,10 @@ export class GiftService
const details: ISendMessageDetails = { const details: ISendMessageDetails = {
recipientId: playerId, recipientId: playerId,
sender: this.getMessageType(giftData), sender: this.getMessageType(giftData),
senderDetails: { _id: this.getSenderId(giftData), info: null}, senderDetails: {_id: this.getSenderId(giftData), info: null},
messageText: giftData.messageText, messageText: giftData.messageText,
items: giftData.items, items: giftData.items,
itemsMaxStorageLifetimeSeconds: this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours) itemsMaxStorageLifetimeSeconds: this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours),
}; };
if (giftData.trader) if (giftData.trader)
@ -210,6 +213,5 @@ export class GiftService
} }
break; break;
} }
} }
} }

View File

@ -16,7 +16,7 @@ export class HashCacheService
@inject("VFS") protected vfs: VFS, @inject("VFS") protected vfs: VFS,
@inject("HashUtil") protected hashUtil: HashUtil, @inject("HashUtil") protected hashUtil: HashUtil,
@inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("JsonUtil") protected jsonUtil: JsonUtil,
@inject("WinstonLogger") protected logger: ILogger @inject("WinstonLogger") protected logger: ILogger,
) )
{ {
if (!this.vfs.exists(this.modCachePath)) if (!this.vfs.exists(this.modCachePath))
@ -25,8 +25,8 @@ export class HashCacheService
} }
// get mod hash file // get mod hash file
if (!this.modHashes) // empty if (!this.modHashes)
{ { // empty
this.modHashes = this.jsonUtil.deserialize(this.vfs.readFile(`${this.modCachePath}`)); this.modHashes = this.jsonUtil.deserialize(this.vfs.readFile(`${this.modCachePath}`));
} }
} }

View File

@ -46,7 +46,7 @@ export class InsuranceService
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("LocaleService") protected localeService: LocaleService, @inject("LocaleService") protected localeService: LocaleService,
@inject("MailSendService") protected mailSendService: MailSendService, @inject("MailSendService") protected mailSendService: MailSendService,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.insuranceConfig = this.configServer.getConfig(ConfigTypes.INSURANCE); this.insuranceConfig = this.configServer.getConfig(ConfigTypes.INSURANCE);
@ -103,13 +103,17 @@ export class InsuranceService
const dialogueTemplates = this.databaseServer.getTables().traders[traderId].dialogue; const dialogueTemplates = this.databaseServer.getTables().traders[traderId].dialogue;
// Construct "i will go look for your stuff" message // Construct "i will go look for your stuff" message
const messageContent = this.dialogueHelper.createMessageContext(this.randomUtil.getArrayValue(dialogueTemplates.insuranceStart), MessageType.NPC_TRADER, traderBase.insurance.max_storage_time); const messageContent = this.dialogueHelper.createMessageContext(
this.randomUtil.getArrayValue(dialogueTemplates.insuranceStart),
MessageType.NPC_TRADER,
traderBase.insurance.max_storage_time,
);
messageContent.text = ""; // Live insurance returns have an empty string for the text property messageContent.text = ""; // Live insurance returns have an empty string for the text property
messageContent.profileChangeEvents = []; messageContent.profileChangeEvents = [];
messageContent.systemData = { messageContent.systemData = {
date: this.timeUtil.getDateMailFormat(), date: this.timeUtil.getDateMailFormat(),
time: this.timeUtil.getTimeMailFormat(), time: this.timeUtil.getTimeMailFormat(),
location: mapId location: mapId,
}; };
// MUST occur after systemData is hydrated // MUST occur after systemData is hydrated
@ -128,7 +132,7 @@ export class InsuranceService
scheduledTime: insuranceReturnTimestamp, scheduledTime: insuranceReturnTimestamp,
traderId: traderId, traderId: traderId,
messageContent: messageContent, messageContent: messageContent,
items: this.getInsurance(sessionID)[traderId] items: this.getInsurance(sessionID)[traderId],
}); });
} }
@ -143,9 +147,9 @@ export class InsuranceService
public sendLostInsuranceMessage(sessionId: string, locationName = ""): void public sendLostInsuranceMessage(sessionId: string, locationName = ""): void
{ {
const dialogueTemplates = this.databaseServer.getTables().traders[Traders.PRAPOR].dialogue; // todo: get trader id instead of hard coded prapor const dialogueTemplates = this.databaseServer.getTables().traders[Traders.PRAPOR].dialogue; // todo: get trader id instead of hard coded prapor
const randomResponseId = locationName?.toLowerCase() === "laboratory" const randomResponseId = locationName?.toLowerCase() === "laboratory" ?
? this.randomUtil.getArrayValue(dialogueTemplates["insuranceFailedLabs"]) this.randomUtil.getArrayValue(dialogueTemplates["insuranceFailedLabs"]) :
: this.randomUtil.getArrayValue(dialogueTemplates["insuranceFailed"]); this.randomUtil.getArrayValue(dialogueTemplates["insuranceFailed"]);
this.mailSendService.sendLocalisedNpcMessageToPlayer( this.mailSendService.sendLocalisedNpcMessageToPlayer(
sessionId, sessionId,
@ -154,7 +158,8 @@ export class InsuranceService
randomResponseId, randomResponseId,
[], [],
null, null,
{location: locationName}); {location: locationName},
);
} }
/** /**
@ -168,7 +173,7 @@ export class InsuranceService
for (const insuredItem of this.getInsurance(sessionId)[traderId]) for (const insuredItem of this.getInsurance(sessionId)[traderId])
{ {
// Find insured items parent // Find insured items parent
const insuredItemsParent = insuredItems.find(x => x._id === insuredItem.parentId); const insuredItemsParent = insuredItems.find((x) => x._id === insuredItem.parentId);
if (!insuredItemsParent) if (!insuredItemsParent)
{ {
// Remove location + set slotId of insured items parent // Remove location + set slotId of insured items parent
@ -190,14 +195,16 @@ export class InsuranceService
// If override inconfig is non-zero, use that instead of trader values // If override inconfig is non-zero, use that instead of trader values
if (this.insuranceConfig.returnTimeOverrideSeconds > 0) if (this.insuranceConfig.returnTimeOverrideSeconds > 0)
{ {
this.logger.debug(`Insurance override used: returning in ${this.insuranceConfig.returnTimeOverrideSeconds} seconds`); this.logger.debug(
`Insurance override used: returning in ${this.insuranceConfig.returnTimeOverrideSeconds} seconds`,
);
return this.timeUtil.getTimestamp() + this.insuranceConfig.returnTimeOverrideSeconds; return this.timeUtil.getTimestamp() + this.insuranceConfig.returnTimeOverrideSeconds;
} }
const insuranceReturnTimeBonus = pmcData.Bonuses.find(b => b.type === "InsuranceReturnTime"); const insuranceReturnTimeBonus = pmcData.Bonuses.find((b) => b.type === "InsuranceReturnTime");
const insuranceReturnTimeBonusPercent = 1.0 - (insuranceReturnTimeBonus const insuranceReturnTimeBonusPercent = 1.0 - (insuranceReturnTimeBonus ?
? Math.abs(insuranceReturnTimeBonus.value) Math.abs(insuranceReturnTimeBonus.value) :
: 0) / 100; 0) / 100;
const traderMinReturnAsSeconds = trader.insurance.min_return_hour * TimeUtil.oneHourAsSeconds; const traderMinReturnAsSeconds = trader.insurance.min_return_hour * TimeUtil.oneHourAsSeconds;
const traderMaxReturnAsSeconds = trader.insurance.max_return_hour * TimeUtil.oneHourAsSeconds; const traderMaxReturnAsSeconds = trader.insurance.max_return_hour * TimeUtil.oneHourAsSeconds;
@ -215,7 +222,13 @@ export class InsuranceService
* @param sessionID Session id * @param sessionID Session id
* @param playerDied did the player die in raid * @param playerDied did the player die in raid
*/ */
public storeLostGear(pmcData: IPmcData, offraidData: ISaveProgressRequestData, preRaidGear: Item[], sessionID: string, playerDied: boolean): void public storeLostGear(
pmcData: IPmcData,
offraidData: ISaveProgressRequestData,
preRaidGear: Item[],
sessionID: string,
playerDied: boolean,
): void
{ {
const preRaidGearHash = this.createItemHashTable(preRaidGear); const preRaidGearHash = this.createItemHashTable(preRaidGear);
const offRaidGearHash = this.createItemHashTable(offraidData.profile.Inventory.items); const offRaidGearHash = this.createItemHashTable(offraidData.profile.Inventory.items);
@ -242,9 +255,13 @@ export class InsuranceService
{ {
equipmentToSendToPlayer.push({ equipmentToSendToPlayer.push({
pmcData: pmcData, pmcData: pmcData,
itemToReturnToPlayer: this.getInsuredItemDetails(pmcData, preRaidItem, offraidData.insurance?.find(x => x.id === insuredItem.itemId)), itemToReturnToPlayer: this.getInsuredItemDetails(
pmcData,
preRaidItem,
offraidData.insurance?.find((x) => x.id === insuredItem.itemId),
),
traderId: insuredItem.tid, traderId: insuredItem.tid,
sessionID: sessionID sessionID: sessionID,
}); });
} }
} }
@ -264,7 +281,11 @@ export class InsuranceService
* @param insuredItemFromClient Item data when player left raid (durability values) * @param insuredItemFromClient Item data when player left raid (durability values)
* @returns Item object * @returns Item object
*/ */
protected getInsuredItemDetails(pmcData: IPmcData, preRaidItem: Item, insuredItemFromClient: IInsuredItemsData): Item protected getInsuredItemDetails(
pmcData: IPmcData,
preRaidItem: Item,
insuredItemFromClient: IInsuredItemsData,
): Item
{ {
// Get baseline item to return, clone pre raid item // Get baseline item to return, clone pre raid item
const itemToReturn: Item = this.jsonUtil.clone(preRaidItem); const itemToReturn: Item = this.jsonUtil.clone(preRaidItem);
@ -298,7 +319,7 @@ export class InsuranceService
{ {
itemToReturn.upd.Repairable = { itemToReturn.upd.Repairable = {
Durability: insuredItemFromClient.durability, Durability: insuredItemFromClient.durability,
MaxDurability: insuredItemFromClient.maxDurability MaxDurability: insuredItemFromClient.maxDurability,
}; };
} }
else else
@ -306,7 +327,6 @@ export class InsuranceService
itemToReturn.upd.Repairable.Durability = insuredItemFromClient.durability; itemToReturn.upd.Repairable.Durability = insuredItemFromClient.durability;
itemToReturn.upd.Repairable.MaxDurability = insuredItemFromClient.maxDurability; itemToReturn.upd.Repairable.MaxDurability = insuredItemFromClient.maxDurability;
} }
} }
// Client item has FaceShield values, Ensure values persist into server data // Client item has FaceShield values, Ensure values persist into server data
@ -316,14 +336,13 @@ export class InsuranceService
if (!itemToReturn.upd.FaceShield) if (!itemToReturn.upd.FaceShield)
{ {
itemToReturn.upd.FaceShield = { itemToReturn.upd.FaceShield = {
Hits: insuredItemFromClient.hits Hits: insuredItemFromClient.hits,
}; };
} }
else else
{ {
itemToReturn.upd.FaceShield.Hits = insuredItemFromClient.hits; itemToReturn.upd.FaceShield.Hits = insuredItemFromClient.hits;
} }
} }
return itemToReturn; return itemToReturn;
@ -340,7 +359,7 @@ export class InsuranceService
"pocket1", "pocket1",
"pocket2", "pocket2",
"pocket3", "pocket3",
"pocket4" "pocket4",
]; ];
// Some pockets can lose items with player death, some don't // Some pockets can lose items with player death, some don't
@ -379,7 +398,9 @@ export class InsuranceService
* @param itemToReturnToPlayer item to store * @param itemToReturnToPlayer item to store
* @param traderId Id of trader item was insured with * @param traderId Id of trader item was insured with
*/ */
protected addGearToSend(gear: { sessionID: string; pmcData: IPmcData; itemToReturnToPlayer: Item; traderId: string}): void protected addGearToSend(
gear: {sessionID: string; pmcData: IPmcData; itemToReturnToPlayer: Item; traderId: string;},
): void
{ {
const sessionId = gear.sessionID; const sessionId = gear.sessionID;
const pmcData = gear.pmcData; const pmcData = gear.pmcData;
@ -436,7 +457,6 @@ export class InsuranceService
*/ */
public addInsuranceItemToArray(sessionId: string, traderId: string, itemToAdd: Item): void public addInsuranceItemToArray(sessionId: string, traderId: string, itemToAdd: Item): void
{ {
this.insured[sessionId][traderId].push(itemToAdd); this.insured[sessionId][traderId].push(itemToAdd);
} }
@ -453,7 +473,9 @@ export class InsuranceService
if (!insuranceMultiplier) if (!insuranceMultiplier)
{ {
insuranceMultiplier = 0.3; insuranceMultiplier = 0.3;
this.logger.warning(this.localisationService.getText("insurance-missing_insurance_price_multiplier", traderId)); this.logger.warning(
this.localisationService.getText("insurance-missing_insurance_price_multiplier", traderId),
);
} }
// Multiply item handbook price by multiplier in config to get the new insurance price // Multiply item handbook price by multiplier in config to get the new insurance price
@ -462,7 +484,7 @@ export class InsuranceService
if (coef > 0) if (coef > 0)
{ {
pricePremium *= (1 - this.traderHelper.getLoyaltyLevel(traderId, pmcData).insurance_price_coef / 100); pricePremium *= 1 - this.traderHelper.getLoyaltyLevel(traderId, pmcData).insurance_price_coef / 100;
} }
return Math.round(pricePremium); return Math.round(pricePremium);

View File

@ -18,7 +18,7 @@ export class ItemBaseClassService
constructor( constructor(
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("DatabaseServer") protected databaseServer: DatabaseServer @inject("DatabaseServer") protected databaseServer: DatabaseServer,
) )
{} {}
@ -39,7 +39,7 @@ export class ItemBaseClassService
return; return;
} }
const filteredDbItems = Object.values(allDbItems).filter(x => x._type === "Item"); const filteredDbItems = Object.values(allDbItems).filter((x) => x._type === "Item");
for (const item of filteredDbItems) for (const item of filteredDbItems)
{ {
const itemIdToUpdate = item._id; const itemIdToUpdate = item._id;
@ -111,7 +111,7 @@ export class ItemBaseClassService
} }
} }
return this.itemBaseClassesCache[itemTpl].some(x => baseClasses.includes(x)); return this.itemBaseClassesCache[itemTpl].some((x) => baseClasses.includes(x));
} }
/** /**

View File

@ -10,12 +10,12 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
@injectable() @injectable()
export class ItemFilterService export class ItemFilterService
{ {
protected itemConfig: IItemConfig ; protected itemConfig: IItemConfig;
constructor( constructor(
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.itemConfig = this.configServer.getConfig(ConfigTypes.ITEM); this.itemConfig = this.configServer.getConfig(ConfigTypes.ITEM);

View File

@ -17,7 +17,7 @@ export class LocaleService
constructor( constructor(
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.localeConfig = this.configServer.getConfig(ConfigTypes.LOCALE); this.localeConfig = this.configServer.getConfig(ConfigTypes.LOCALE);
@ -35,7 +35,9 @@ export class LocaleService
return desiredLocale; return desiredLocale;
} }
this.logger.warning(`Unable to find desired locale file using locale ${this.getDesiredGameLocale()} from config/locale.json, falling back to 'en'`); this.logger.warning(
`Unable to find desired locale file using locale ${this.getDesiredGameLocale()} from config/locale.json, falling back to 'en'`,
);
return this.databaseServer.getTables().locales.global["en"]; return this.databaseServer.getTables().locales.global["en"];
} }
@ -95,7 +97,9 @@ export class LocaleService
if (!this.localeConfig.serverSupportedLocales.includes(platformLocale.language)) if (!this.localeConfig.serverSupportedLocales.includes(platformLocale.language))
{ {
this.logger.warning(`Unsupported system langauge found ${platformLocale.baseName}, falling back to english`); this.logger.warning(
`Unsupported system langauge found ${platformLocale.baseName}, falling back to english`,
);
return "en"; return "en";
} }

View File

@ -21,17 +21,22 @@ export class LocalisationService
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("RandomUtil") protected randomUtil: RandomUtil, @inject("RandomUtil") protected randomUtil: RandomUtil,
@inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("LocaleService") protected localeService: LocaleService @inject("LocaleService") protected localeService: LocaleService,
) )
{ {
const localeFileDirectory = path.join(process.cwd(), globalThis.G_RELEASE_CONFIGURATION ? "Aki_Data/Server/database/locales/server" : "./assets/database/locales/server"); const localeFileDirectory = path.join(
process.cwd(),
globalThis.G_RELEASE_CONFIGURATION ?
"Aki_Data/Server/database/locales/server" :
"./assets/database/locales/server",
);
this.i18n = new I18n( this.i18n = new I18n(
{ {
locales: this.localeService.getServerSupportedLocales(), locales: this.localeService.getServerSupportedLocales(),
defaultLocale: "en", defaultLocale: "en",
directory: localeFileDirectory, directory: localeFileDirectory,
retryInDefaultLocale: true retryInDefaultLocale: true,
} },
); );
this.i18n.setLocale(this.localeService.getDesiredServerLocale()); this.i18n.setLocale(this.localeService.getDesiredServerLocale());
@ -64,7 +69,9 @@ export class LocalisationService
*/ */
public getRandomTextThatMatchesPartialKey(partialKey: string): string public getRandomTextThatMatchesPartialKey(partialKey: string): string
{ {
const filteredKeys = Object.keys(this.databaseServer.getTables().locales.server["en"]).filter(x => x.startsWith(partialKey)); const filteredKeys = Object.keys(this.databaseServer.getTables().locales.server["en"]).filter((x) =>
x.startsWith(partialKey)
);
const chosenKey = this.randomUtil.getArrayValue(filteredKeys); const chosenKey = this.randomUtil.getArrayValue(filteredKeys);
return this.getText(chosenKey); return this.getText(chosenKey);

View File

@ -33,9 +33,9 @@ export class MailSendService
@inject("NotificationSendHelper") protected notificationSendHelper: NotificationSendHelper, @inject("NotificationSendHelper") protected notificationSendHelper: NotificationSendHelper,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("ItemHelper") protected itemHelper: ItemHelper, @inject("ItemHelper") protected itemHelper: ItemHelper,
@inject("TraderHelper") protected traderHelper: TraderHelper @inject("TraderHelper") protected traderHelper: TraderHelper,
) )
{ } {}
/** /**
* Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale
@ -46,11 +46,25 @@ export class MailSendService
* @param items Optional items to send to player * @param items Optional items to send to player
* @param maxStorageTimeSeconds Optional time to collect items before they expire * @param maxStorageTimeSeconds Optional time to collect items before they expire
*/ */
public sendDirectNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, message: string, items: Item[] = [], maxStorageTimeSeconds = null, systemData = null, ragfair = null): void public sendDirectNpcMessageToPlayer(
sessionId: string,
trader: Traders,
messageType: MessageType,
message: string,
items: Item[] = [],
maxStorageTimeSeconds = null,
systemData = null,
ragfair = null,
): void
{ {
if (!trader) if (!trader)
{ {
this.logger.error(this.localisationService.getText("mailsend-missing_trader", {messageType: messageType, sessionId: sessionId})); this.logger.error(
this.localisationService.getText("mailsend-missing_trader", {
messageType: messageType,
sessionId: sessionId,
}),
);
return; return;
} }
@ -60,7 +74,7 @@ export class MailSendService
sender: messageType, sender: messageType,
dialogType: MessageType.NPC_TRADER, dialogType: MessageType.NPC_TRADER,
trader: trader, trader: trader,
messageText: message messageText: message,
}; };
// Add items to message // Add items to message
@ -92,11 +106,25 @@ export class MailSendService
* @param items Optional items to send to player * @param items Optional items to send to player
* @param maxStorageTimeSeconds Optional time to collect items before they expire * @param maxStorageTimeSeconds Optional time to collect items before they expire
*/ */
public sendLocalisedNpcMessageToPlayer(sessionId: string, trader: Traders, messageType: MessageType, messageLocaleId: string, items: Item[] = [], maxStorageTimeSeconds = null, systemData = null, ragfair = null): void public sendLocalisedNpcMessageToPlayer(
sessionId: string,
trader: Traders,
messageType: MessageType,
messageLocaleId: string,
items: Item[] = [],
maxStorageTimeSeconds = null,
systemData = null,
ragfair = null,
): void
{ {
if (!trader) if (!trader)
{ {
this.logger.error(this.localisationService.getText("mailsend-missing_trader", {messageType: messageType, sessionId: sessionId})); this.logger.error(
this.localisationService.getText("mailsend-missing_trader", {
messageType: messageType,
sessionId: sessionId,
}),
);
return; return;
} }
@ -106,7 +134,7 @@ export class MailSendService
sender: messageType, sender: messageType,
dialogType: MessageType.NPC_TRADER, dialogType: MessageType.NPC_TRADER,
trader: trader, trader: trader,
templateId: messageLocaleId templateId: messageLocaleId,
}; };
// Add items to message // Add items to message
@ -136,12 +164,17 @@ export class MailSendService
* @param items Optional items to send to player * @param items Optional items to send to player
* @param maxStorageTimeSeconds Optional time to collect items before they expire * @param maxStorageTimeSeconds Optional time to collect items before they expire
*/ */
public sendSystemMessageToPlayer(sessionId: string, message: string, items: Item[] = [], maxStorageTimeSeconds = null): void public sendSystemMessageToPlayer(
sessionId: string,
message: string,
items: Item[] = [],
maxStorageTimeSeconds = null,
): void
{ {
const details: ISendMessageDetails = { const details: ISendMessageDetails = {
recipientId: sessionId, recipientId: sessionId,
sender: MessageType.SYSTEM_MESSAGE, sender: MessageType.SYSTEM_MESSAGE,
messageText: message messageText: message,
}; };
// Add items to message // Add items to message
@ -161,12 +194,17 @@ export class MailSendService
* @param items Optional items to send to player * @param items Optional items to send to player
* @param maxStorageTimeSeconds Optional time to collect items before they expire * @param maxStorageTimeSeconds Optional time to collect items before they expire
*/ */
public sendLocalisedSystemMessageToPlayer(sessionId: string, messageLocaleId: string, items: Item[] = [], maxStorageTimeSeconds = null): void public sendLocalisedSystemMessageToPlayer(
sessionId: string,
messageLocaleId: string,
items: Item[] = [],
maxStorageTimeSeconds = null,
): void
{ {
const details: ISendMessageDetails = { const details: ISendMessageDetails = {
recipientId: sessionId, recipientId: sessionId,
sender: MessageType.SYSTEM_MESSAGE, sender: MessageType.SYSTEM_MESSAGE,
templateId: messageLocaleId templateId: messageLocaleId,
}; };
// Add items to message // Add items to message
@ -187,13 +225,19 @@ export class MailSendService
* @param items Optional items to send to player * @param items Optional items to send to player
* @param maxStorageTimeSeconds Optional time to collect items before they expire * @param maxStorageTimeSeconds Optional time to collect items before they expire
*/ */
public sendUserMessageToPlayer(sessionId: string, senderDetails: IUserDialogInfo, message: string, items: Item[] = [], maxStorageTimeSeconds = null): void public sendUserMessageToPlayer(
sessionId: string,
senderDetails: IUserDialogInfo,
message: string,
items: Item[] = [],
maxStorageTimeSeconds = null,
): void
{ {
const details: ISendMessageDetails = { const details: ISendMessageDetails = {
recipientId: sessionId, recipientId: sessionId,
sender: MessageType.USER_MESSAGE, sender: MessageType.USER_MESSAGE,
senderDetails: senderDetails, senderDetails: senderDetails,
messageText: message messageText: message,
}; };
// Add items to message // Add items to message
@ -240,9 +284,15 @@ export class MailSendService
// TODO: clean up old code here // TODO: clean up old code here
// Offer Sold notifications are now separate from the main notification // Offer Sold notifications are now separate from the main notification
if ([MessageType.NPC_TRADER, MessageType.FLEAMARKET_MESSAGE].includes(senderDialog.type) && messageDetails.ragfairDetails) if (
[MessageType.NPC_TRADER, MessageType.FLEAMARKET_MESSAGE].includes(senderDialog.type) &&
messageDetails.ragfairDetails
)
{ {
const offerSoldMessage = this.notifierHelper.createRagfairOfferSoldNotification(message, messageDetails.ragfairDetails); const offerSoldMessage = this.notifierHelper.createRagfairOfferSoldNotification(
message,
messageDetails.ragfairDetails,
);
this.notificationSendHelper.sendMessage(messageDetails.recipientId, offerSoldMessage); this.notificationSendHelper.sendMessage(messageDetails.recipientId, offerSoldMessage);
message.type = MessageType.MESSAGE_WITH_ITEMS; // Should prevent getting the same notification popup twice message.type = MessageType.MESSAGE_WITH_ITEMS; // Should prevent getting the same notification popup twice
} }
@ -276,7 +326,7 @@ export class MailSendService
uid: playerProfile.characters.pmc._id, uid: playerProfile.characters.pmc._id,
type: MessageType.USER_MESSAGE, type: MessageType.USER_MESSAGE,
rewardCollected: false, rewardCollected: false,
text: message text: message,
}); });
} }
@ -298,7 +348,9 @@ export class MailSendService
hasRewards: false, // The default dialog message has no rewards, can be added later via addRewardItemsToMessage() 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() 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" 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 // Clean up empty system data
@ -322,7 +374,11 @@ export class MailSendService
* @param itemsToSendToPlayer Items to add to message * @param itemsToSendToPlayer Items to add to message
* @param maxStorageTimeSeconds total time items are stored in mail before being deleted * @param maxStorageTimeSeconds total time items are stored in mail before being deleted
*/ */
protected addRewardItemsToMessage(message: Message, itemsToSendToPlayer: MessageItems, maxStorageTimeSeconds: number): void protected addRewardItemsToMessage(
message: Message,
itemsToSendToPlayer: MessageItems,
maxStorageTimeSeconds: number,
): void
{ {
if (itemsToSendToPlayer?.data?.length > 0) if (itemsToSendToPlayer?.data?.length > 0)
{ {
@ -350,7 +406,10 @@ export class MailSendService
const parentItem = this.getBaseItemFromRewards(messageDetails.items); const parentItem = this.getBaseItemFromRewards(messageDetails.items);
if (!parentItem) if (!parentItem)
{ {
this.localisationService.getText("mailsend-missing_parent", {traderId: messageDetails.trader, sender: messageDetails.sender}); this.localisationService.getText("mailsend-missing_parent", {
traderId: messageDetails.trader,
sender: messageDetails.sender,
});
return itemsToSendToPlayer; return itemsToSendToPlayer;
} }
@ -363,7 +422,7 @@ export class MailSendService
itemsToSendToPlayer = { itemsToSendToPlayer = {
stash: parentItem.parentId, stash: parentItem.parentId,
data: [] data: [],
}; };
// Ensure Ids are unique and cont collide with items in player inventory later // Ensure Ids are unique and cont collide with items in player inventory later
@ -376,7 +435,12 @@ export class MailSendService
if (!itemTemplate) if (!itemTemplate)
{ {
// Can happen when modded items are insured + mod is removed // Can happen when modded items are insured + mod is removed
this.logger.error(this.localisationService.getText("dialog-missing_item_template", {tpl: reward._tpl, type: dialogType})); this.logger.error(
this.localisationService.getText("dialog-missing_item_template", {
tpl: reward._tpl,
type: dialogType,
}),
);
continue; continue;
} }
@ -427,7 +491,7 @@ export class MailSendService
} }
// Find first item with slotId that indicates its a 'base' item // 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) if (item)
{ {
return item; return item;
@ -435,7 +499,7 @@ export class MailSendService
// Not a singlular item + no items have a hideout/main slotid // Not a singlular item + no items have a hideout/main slotid
// Look for first item without parent id // Look for first item without parent id
item = items.find(x => !x.parentId); item = items.find((x) => !x.parentId);
if (item) if (item)
{ {
return item; return item;
@ -467,7 +531,7 @@ export class MailSendService
messages: [], messages: [],
pinned: false, pinned: false,
new: 0, new: 0,
attachmentsNew: 0 attachmentsNew: 0,
}; };
senderDialog = dialogsInProfile[senderId]; senderDialog = dialogsInProfile[senderId];
@ -510,5 +574,4 @@ export class MailSendService
this.logger.warning(`Unable to handle message of type: ${messageDetails.sender}`); this.logger.warning(`Unable to handle message of type: ${messageDetails.sender}`);
} }
} }

View File

@ -12,7 +12,7 @@ export class MatchBotDetailsCacheService
constructor( constructor(
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("LocalisationService") protected localisationService: LocalisationService @inject("LocalisationService") protected localisationService: LocalisationService,
) )
{} {}
@ -48,5 +48,4 @@ export class MatchBotDetailsCacheService
return botInCache; return botInCache;
} }
} }

View File

@ -9,9 +9,9 @@ export class MatchLocationService
protected locations = {}; protected locations = {};
constructor( constructor(
@inject("TimeUtil") protected timeUtil: TimeUtil @inject("TimeUtil") protected timeUtil: TimeUtil,
) )
{ } {}
public createGroup(sessionID: string, info: ICreateGroupRequestData): any public createGroup(sessionID: string, info: ICreateGroupRequestData): any
{ {
@ -33,10 +33,10 @@ export class MatchLocationService
region: "EUR", region: "EUR",
ip: "127.0.0.1", ip: "127.0.0.1",
savageId: `scav${sessionID}`, savageId: `scav${sessionID}`,
accessKeyId: "" accessKeyId: "",
} },
], ],
customDataCenter: [] customDataCenter: [],
}; };
return this.locations[info.location].groups[groupID]; return this.locations[info.location].groups[groupID];

View File

@ -16,7 +16,7 @@ export class ModCompilerService
constructor( constructor(
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("HashCacheService") protected hashCacheService: HashCacheService, @inject("HashCacheService") protected hashCacheService: HashCacheService,
@inject("VFS") protected vfs: VFS @inject("VFS") protected vfs: VFS,
) )
{ {
const packageJsonPath: string = path.join(__dirname, "../../package.json"); const packageJsonPath: string = path.join(__dirname, "../../package.json");
@ -38,7 +38,7 @@ export class ModCompilerService
for (const file of modTypeScriptFiles) for (const file of modTypeScriptFiles)
{ {
const fileContent = this.vfs.readFile(file); const fileContent = this.vfs.readFile(file);
tsFileContents+= fileContent; tsFileContents += fileContent;
// Does equivalent .js file exist // Does equivalent .js file exist
if (!this.vfs.exists(file.replace(".ts", ".js"))) if (!this.vfs.exists(file.replace(".ts", ".js")))
@ -61,22 +61,21 @@ export class ModCompilerService
this.hashCacheService.storeModContent(modName, tsFileContents); this.hashCacheService.storeModContent(modName, tsFileContents);
} }
return this.compile(modTypeScriptFiles, return this.compile(modTypeScriptFiles, {
{ noEmitOnError: true,
noEmitOnError: true, noImplicitAny: false,
noImplicitAny: false, target: ts.ScriptTarget.ES2022,
target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.CommonJS,
module: ts.ModuleKind.CommonJS, moduleResolution: ts.ModuleResolutionKind.Node10,
moduleResolution: ts.ModuleResolutionKind.Node10, sourceMap: true,
sourceMap: true, resolveJsonModule: true,
resolveJsonModule: true, allowJs: true,
allowJs: true, esModuleInterop: true,
esModuleInterop: true, downlevelIteration: true,
downlevelIteration: true, experimentalDecorators: true,
experimentalDecorators: true, emitDecoratorMetadata: true,
emitDecoratorMetadata: true, rootDir: modPath,
rootDir: modPath });
});
} }
/** /**
@ -87,7 +86,7 @@ export class ModCompilerService
protected async compile(fileNames: string[], options: ts.CompilerOptions): Promise<void> protected async compile(fileNames: string[], options: ts.CompilerOptions): Promise<void>
{ {
// C:/snapshot/project || /snapshot/project // C:/snapshot/project || /snapshot/project
const baseDir: string = __dirname.replace(/\\/g,"/").split("/").slice(0, 3).join("/"); const baseDir: string = __dirname.replace(/\\/g, "/").split("/").slice(0, 3).join("/");
for (const filePath of fileNames) for (const filePath of fileNames)
{ {
@ -107,18 +106,21 @@ export class ModCompilerService
} }
else else
{ {
replacedText = text.replace(/(@spt-aki)/g, path.join(__dirname, "..").replace(/\\/g,"/")); replacedText = text.replace(/(@spt-aki)/g, path.join(__dirname, "..").replace(/\\/g, "/"));
} }
const output = ts.transpileModule(replacedText, { compilerOptions: options }); const output = ts.transpileModule(replacedText, {compilerOptions: options});
if (output.sourceMapText) if (output.sourceMapText)
{ {
output.outputText = output.outputText.replace("//# sourceMappingURL=module.js.map", `//# sourceMappingURL=${parsedDestPath.base}.map`); output.outputText = output.outputText.replace(
"//# sourceMappingURL=module.js.map",
`//# sourceMappingURL=${parsedDestPath.base}.map`,
);
const sourceMap = JSON.parse(output.sourceMapText); const sourceMap = JSON.parse(output.sourceMapText);
sourceMap.file = parsedDestPath.base; sourceMap.file = parsedDestPath.base;
sourceMap.sources = [ parsedPath.base ]; sourceMap.sources = [parsedPath.base];
fs.writeFileSync(`${destPath}.map`, JSON.stringify(sourceMap)); fs.writeFileSync(`${destPath}.map`, JSON.stringify(sourceMap));
} }
@ -138,7 +140,7 @@ export class ModCompilerService
*/ */
protected areFilesReady(fileNames: string[]): boolean protected areFilesReady(fileNames: string[]): boolean
{ {
return fileNames.filter(x => !this.vfs.exists(x.replace(".ts", ".js"))).length === 0; return fileNames.filter((x) => !this.vfs.exists(x.replace(".ts", ".js"))).length === 0;
} }
/** /**
@ -148,6 +150,6 @@ export class ModCompilerService
*/ */
protected delay(ms: number): Promise<unknown> protected delay(ms: number): Promise<unknown>
{ {
return new Promise( resolve => setTimeout(resolve, ms) ); return new Promise((resolve) => setTimeout(resolve, ms));
} }
} }

View File

@ -22,7 +22,7 @@ export class OpenZoneService
@inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("JsonUtil") protected jsonUtil: JsonUtil,
@inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION); this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION);

View File

@ -28,9 +28,9 @@ export class PaymentService
@inject("ItemHelper") protected itemHelper: ItemHelper, @inject("ItemHelper") protected itemHelper: ItemHelper,
@inject("InventoryHelper") protected inventoryHelper: InventoryHelper, @inject("InventoryHelper") protected inventoryHelper: InventoryHelper,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("PaymentHelper") protected paymentHelper: PaymentHelper @inject("PaymentHelper") protected paymentHelper: PaymentHelper,
) )
{ } {}
/** /**
* Take money and insert items into return to server request * Take money and insert items into return to server request
@ -39,12 +39,17 @@ export class PaymentService
* @param {string} sessionID * @param {string} sessionID
* @returns IItemEventRouterResponse * @returns IItemEventRouterResponse
*/ */
public payMoney(pmcData: IPmcData, request: IProcessBuyTradeRequestData, sessionID: string, output: IItemEventRouterResponse): IItemEventRouterResponse public payMoney(
pmcData: IPmcData,
request: IProcessBuyTradeRequestData,
sessionID: string,
output: IItemEventRouterResponse,
): IItemEventRouterResponse
{ {
const trader = this.traderHelper.getTrader(request.tid, sessionID); const trader = this.traderHelper.getTrader(request.tid, sessionID);
// Track the amounts of each type of currency involved in the trade. // Track the amounts of each type of currency involved in the trade.
const currencyAmounts: { [key: string]: number } = {}; const currencyAmounts: {[key: string]: number;} = {};
// Delete barter items and track currencies if the action is "TradingConfirm". // Delete barter items and track currencies if the action is "TradingConfirm".
if (request.Action === "TradingConfirm") if (request.Action === "TradingConfirm")
@ -52,7 +57,7 @@ export class PaymentService
for (const index in request.scheme_items) for (const index in request.scheme_items)
{ {
// Find the corresponding item in the player's inventory. // 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 (item !== undefined)
{ {
if (!this.paymentHelper.isMoneyTpl(item._tpl)) if (!this.paymentHelper.isMoneyTpl(item._tpl))
@ -64,7 +69,8 @@ export class PaymentService
else else
{ {
// If the item is money, add its count to the currencyAmounts object. // If the item is money, add its count to the currencyAmounts object.
currencyAmounts[item._tpl] = (currencyAmounts[item._tpl] || 0) + request.scheme_items[index].count; currencyAmounts[item._tpl] = (currencyAmounts[item._tpl] || 0) +
request.scheme_items[index].count;
} }
} }
} }
@ -90,7 +96,10 @@ export class PaymentService
} }
// Convert the amount to the trader's currency and update the sales sum. // Convert the amount to the trader's currency and update the sales sum.
const costOfPurchaseInCurrency = this.handbookHelper.fromRUB(this.handbookHelper.inRUB(currencyAmount, currencyTpl), this.paymentHelper.getCurrency(trader.currency)); const costOfPurchaseInCurrency = this.handbookHelper.fromRUB(
this.handbookHelper.inRUB(currencyAmount, currencyTpl),
this.paymentHelper.getCurrency(trader.currency),
);
pmcData.TradersInfo[request.tid].salesSum += costOfPurchaseInCurrency; pmcData.TradersInfo[request.tid].salesSum += costOfPurchaseInCurrency;
} }
} }
@ -101,7 +110,10 @@ export class PaymentService
this.logger.debug(this.localisationService.getText("payment-zero_price_no_payment")); this.logger.debug(this.localisationService.getText("payment-zero_price_no_payment"));
// Convert the handbook price to the trader's currency and update the sales sum. // Convert the handbook price to the trader's currency and update the sales sum.
const costOfPurchaseInCurrency = this.handbookHelper.fromRUB(this.getTraderItemHandbookPriceRouble(request.item_id, request.tid), this.paymentHelper.getCurrency(trader.currency)); const costOfPurchaseInCurrency = this.handbookHelper.fromRUB(
this.getTraderItemHandbookPriceRouble(request.item_id, request.tid),
this.paymentHelper.getCurrency(trader.currency),
);
pmcData.TradersInfo[request.tid].salesSum += costOfPurchaseInCurrency; pmcData.TradersInfo[request.tid].salesSum += costOfPurchaseInCurrency;
} }
@ -128,7 +140,9 @@ export class PaymentService
const assortItemPriceRouble = this.handbookHelper.getTemplatePrice(purchasedAssortItem._tpl); const assortItemPriceRouble = this.handbookHelper.getTemplatePrice(purchasedAssortItem._tpl);
if (!assortItemPriceRouble) if (!assortItemPriceRouble)
{ {
this.logger.debug(`No item price found for ${purchasedAssortItem._tpl} on trader: ${traderId} in assort: ${traderAssortId}`); this.logger.debug(
`No item price found for ${purchasedAssortItem._tpl} on trader: ${traderId} in assort: ${traderAssortId}`,
);
return 1; return 1;
} }
@ -145,7 +159,13 @@ export class PaymentService
* @param {string} sessionID * @param {string} sessionID
* @returns IItemEventRouterResponse * @returns IItemEventRouterResponse
*/ */
public getMoney(pmcData: IPmcData, amount: number, body: IProcessSellTradeRequestData, output: IItemEventRouterResponse, sessionID: string): IItemEventRouterResponse public getMoney(
pmcData: IPmcData,
amount: number,
body: IProcessSellTradeRequestData,
output: IItemEventRouterResponse,
sessionID: string,
): IItemEventRouterResponse
{ {
const trader = this.traderHelper.getTrader(body.tid, sessionID); const trader = this.traderHelper.getTrader(body.tid, sessionID);
const currency = this.paymentHelper.getCurrency(trader.currency); const currency = this.paymentHelper.getCurrency(trader.currency);
@ -169,7 +189,6 @@ export class PaymentService
if (item.upd.StackObjectsCount < maxStackSize) if (item.upd.StackObjectsCount < maxStackSize)
{ {
if (item.upd.StackObjectsCount + calcAmount > maxStackSize) if (item.upd.StackObjectsCount + calcAmount > maxStackSize)
{ {
// calculate difference // calculate difference
@ -197,9 +216,9 @@ export class PaymentService
items: [{ items: [{
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
item_id: currency, item_id: currency,
count: calcAmount count: calcAmount,
}], }],
tid: body.tid tid: body.tid,
}; };
output = this.inventoryHelper.addItem(pmcData, request, output, sessionID, null, false, null, true); output = this.inventoryHelper.addItem(pmcData, request, output, sessionID, null, false, null, true);
@ -215,10 +234,10 @@ export class PaymentService
} }
/** /**
* Recursively checks if the given item is * Recursively checks if the given item is
* inside the stash, that is it has the stash as * inside the stash, that is it has the stash as
* ancestor with slotId=hideout * ancestor with slotId=hideout
*/ */
protected isItemInStash(pmcData: IPmcData, item: Item): boolean protected isItemInStash(pmcData: IPmcData, item: Item): boolean
{ {
let container = item; let container = item;
@ -230,7 +249,7 @@ export class PaymentService
return true; return true;
} }
container = pmcData.Inventory.items.find(i => i._id === container.parentId); container = pmcData.Inventory.items.find((i) => i._id === container.parentId);
if (!container) if (!container)
{ {
break; break;
@ -248,16 +267,38 @@ export class PaymentService
* @param output output object to send to client * @param output output object to send to client
* @returns IItemEventRouterResponse * @returns IItemEventRouterResponse
*/ */
public addPaymentToOutput(pmcData: IPmcData, currencyTpl: string, amountToPay: number, sessionID: string, output: IItemEventRouterResponse): IItemEventRouterResponse public addPaymentToOutput(
pmcData: IPmcData,
currencyTpl: string,
amountToPay: number,
sessionID: string,
output: IItemEventRouterResponse,
): IItemEventRouterResponse
{ {
const moneyItemsInInventory = this.getSortedMoneyItemsInInventory(pmcData, currencyTpl, pmcData.Inventory.stash); const moneyItemsInInventory = this.getSortedMoneyItemsInInventory(
const amountAvailable = moneyItemsInInventory.reduce((accumulator, item) => accumulator + item.upd.StackObjectsCount, 0); pmcData,
currencyTpl,
pmcData.Inventory.stash,
);
const amountAvailable = moneyItemsInInventory.reduce(
(accumulator, item) => accumulator + item.upd.StackObjectsCount,
0,
);
// If no money in inventory or amount is not enough we return false // If no money in inventory or amount is not enough we return false
if (moneyItemsInInventory.length <= 0 || amountAvailable < amountToPay) if (moneyItemsInInventory.length <= 0 || amountAvailable < amountToPay)
{ {
this.logger.error(this.localisationService.getText("payment-not_enough_money_to_complete_transation", {amountToPay: amountToPay, amountAvailable: amountAvailable})); this.logger.error(
output = this.httpResponse.appendErrorToOutput(output, this.localisationService.getText("payment-not_enough_money_to_complete_transation_short"), BackendErrorCodes.UNKNOWN_TRADING_ERROR); this.localisationService.getText("payment-not_enough_money_to_complete_transation", {
amountToPay: amountToPay,
amountAvailable: amountAvailable,
}),
);
output = this.httpResponse.appendErrorToOutput(
output,
this.localisationService.getText("payment-not_enough_money_to_complete_transation_short"),
BackendErrorCodes.UNKNOWN_TRADING_ERROR,
);
return output; return output;
} }
@ -360,7 +401,7 @@ export class PaymentService
*/ */
protected isInStash(itemId: string, inventoryItems: Item[], playerStashId: string): boolean 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) if (itemParent)
{ {

View File

@ -9,14 +9,13 @@ import { TimeUtil } from "@spt-aki/utils/TimeUtil";
@injectable() @injectable()
export class PlayerService export class PlayerService
{ {
constructor( constructor(
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("TimeUtil") protected timeUtil: TimeUtil, @inject("TimeUtil") protected timeUtil: TimeUtil,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("DatabaseServer") protected databaseServer: DatabaseServer @inject("DatabaseServer") protected databaseServer: DatabaseServer,
) )
{ } {}
/** /**
* Get level of player * Get level of player
@ -27,7 +26,7 @@ export class PlayerService
{ {
let accExp = 0; let accExp = 0;
for (const [level, { exp }] of this.databaseServer.getTables().globals.config.exp.level.exp_table.entries()) for (const [level, {exp}] of this.databaseServer.getTables().globals.config.exp.level.exp_table.entries())
{ {
accExp += exp; accExp += exp;

View File

@ -27,7 +27,7 @@ export class PmcChatResponseService
@inject("MatchBotDetailsCacheService") protected matchBotDetailsCacheService: MatchBotDetailsCacheService, @inject("MatchBotDetailsCacheService") protected matchBotDetailsCacheService: MatchBotDetailsCacheService,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.pmcResponsesConfig = this.configServer.getConfig(ConfigTypes.PMC_CHAT_RESPONSE); this.pmcResponsesConfig = this.configServer.getConfig(ConfigTypes.PMC_CHAT_RESPONSE);
@ -50,18 +50,21 @@ export class PmcChatResponseService
const victimDetails = this.getVictimDetails(victim); const victimDetails = this.getVictimDetails(victim);
const message = this.chooseMessage(true, pmcData); const message = this.chooseMessage(true, pmcData);
this.notificationSendHelper.sendMessageToPlayer(sessionId, victimDetails, message, MessageType.USER_MESSAGE); this.notificationSendHelper.sendMessageToPlayer(
sessionId,
victimDetails,
message,
MessageType.USER_MESSAGE,
);
} }
} }
/** /**
* Not fully implemented yet, needs method of acquiring killers details after raid * Not fully implemented yet, needs method of acquiring killers details after raid
* @param sessionId Session id * @param sessionId Session id
* @param pmcData Players profile * @param pmcData Players profile
* @param killer The bot who killed the player * @param killer The bot who killed the player
*/ */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public sendKillerResponse(sessionId: string, pmcData: IPmcData, killer: Aggressor): void public sendKillerResponse(sessionId: string, pmcData: IPmcData, killer: Aggressor): void
{ {
if (!killer) if (!killer)
@ -75,7 +78,10 @@ export class PmcChatResponseService
} }
// find bot by name in cache // find bot by name in cache
const killerDetailsInCache = this.matchBotDetailsCacheService.getBotByNameAndSide(killer.Name.trim(), killer.Side); const killerDetailsInCache = this.matchBotDetailsCacheService.getBotByNameAndSide(
killer.Name.trim(),
killer.Side,
);
if (!killerDetailsInCache) if (!killerDetailsInCache)
{ {
return; return;
@ -93,8 +99,8 @@ export class PmcChatResponseService
Nickname: killerDetailsInCache.Info.Nickname, Nickname: killerDetailsInCache.Info.Nickname,
Side: killerDetailsInCache.Info.Side, Side: killerDetailsInCache.Info.Side,
Level: killerDetailsInCache.Info.Level, Level: killerDetailsInCache.Info.Level,
MemberCategory: killerDetailsInCache.Info.MemberCategory MemberCategory: killerDetailsInCache.Info.MemberCategory,
} },
}; };
const message = this.chooseMessage(false, pmcData); const message = this.chooseMessage(false, pmcData);
@ -127,11 +133,17 @@ export class PmcChatResponseService
} }
// Choose random response from above list and request it from localisation service // Choose random response from above list and request it from localisation service
let responseText = this.localisationService.getText(this.randomUtil.getArrayValue(possibleResponseLocaleKeys), {playerName: pmcData.Info.Nickname, playerLevel: pmcData.Info.Level, playerSide: pmcData.Info.Side}); let responseText = this.localisationService.getText(this.randomUtil.getArrayValue(possibleResponseLocaleKeys), {
playerName: pmcData.Info.Nickname,
playerLevel: pmcData.Info.Level,
playerSide: pmcData.Info.Side,
});
if (this.appendSuffixToMessageEnd(isVictim)) if (this.appendSuffixToMessageEnd(isVictim))
{ {
const suffixText = this.localisationService.getText(this.randomUtil.getArrayValue(this.getResponseSuffixLocaleKeys())); const suffixText = this.localisationService.getText(
this.randomUtil.getArrayValue(this.getResponseSuffixLocaleKeys()),
);
responseText += ` ${suffixText}`; responseText += ` ${suffixText}`;
} }
@ -155,9 +167,9 @@ export class PmcChatResponseService
*/ */
protected stripCapitalistion(isVictim: boolean): boolean protected stripCapitalistion(isVictim: boolean): boolean
{ {
const chance = isVictim const chance = isVictim ?
? this.pmcResponsesConfig.victim.stripCapitalisationChancePercent this.pmcResponsesConfig.victim.stripCapitalisationChancePercent :
: this.pmcResponsesConfig.killer.stripCapitalisationChancePercent; this.pmcResponsesConfig.killer.stripCapitalisationChancePercent;
return this.randomUtil.getChance100(chance); return this.randomUtil.getChance100(chance);
} }
@ -169,9 +181,9 @@ export class PmcChatResponseService
*/ */
protected allCaps(isVictim: boolean): boolean protected allCaps(isVictim: boolean): boolean
{ {
const chance = isVictim const chance = isVictim ?
? this.pmcResponsesConfig.victim.allCapsChancePercent this.pmcResponsesConfig.victim.allCapsChancePercent :
: this.pmcResponsesConfig.killer.allCapsChancePercent; this.pmcResponsesConfig.killer.allCapsChancePercent;
return this.randomUtil.getChance100(chance); return this.randomUtil.getChance100(chance);
} }
@ -183,9 +195,9 @@ export class PmcChatResponseService
*/ */
appendSuffixToMessageEnd(isVictim: boolean): boolean appendSuffixToMessageEnd(isVictim: boolean): boolean
{ {
const chance = isVictim const chance = isVictim ?
? this.pmcResponsesConfig.victim.appendBroToMessageEndChancePercent this.pmcResponsesConfig.victim.appendBroToMessageEndChancePercent :
: this.pmcResponsesConfig.killer.appendBroToMessageEndChancePercent; this.pmcResponsesConfig.killer.appendBroToMessageEndChancePercent;
return this.randomUtil.getChance100(chance); return this.randomUtil.getChance100(chance);
} }
@ -197,9 +209,9 @@ export class PmcChatResponseService
*/ */
protected chooseResponseType(isVictim = true): string protected chooseResponseType(isVictim = true): string
{ {
const responseWeights = isVictim const responseWeights = isVictim ?
? this.pmcResponsesConfig.victim.responseTypeWeights this.pmcResponsesConfig.victim.responseTypeWeights :
: this.pmcResponsesConfig.killer.responseTypeWeights; this.pmcResponsesConfig.killer.responseTypeWeights;
return this.weightedRandomHelper.getWeightedValue<string>(responseWeights); return this.weightedRandomHelper.getWeightedValue<string>(responseWeights);
} }
@ -215,7 +227,7 @@ export class PmcChatResponseService
const keyBase = isVictim ? "pmcresponse-victim_" : "pmcresponse-killer_"; const keyBase = isVictim ? "pmcresponse-victim_" : "pmcresponse-killer_";
const keys = this.localisationService.getKeys(); const keys = this.localisationService.getKeys();
return keys.filter(x => x.startsWith(`${keyBase}${keyType}`)); return keys.filter((x) => x.startsWith(`${keyBase}${keyType}`));
} }
/** /**
@ -226,7 +238,7 @@ export class PmcChatResponseService
{ {
const keys = this.localisationService.getKeys(); const keys = this.localisationService.getKeys();
return keys.filter(x => x.startsWith("pmcresponse-suffix")); return keys.filter((x) => x.startsWith("pmcresponse-suffix"));
} }
/** /**
@ -248,7 +260,25 @@ export class PmcChatResponseService
*/ */
protected getVictimDetails(pmcVictim: Victim): IUserDialogInfo protected getVictimDetails(pmcVictim: Victim): IUserDialogInfo
{ {
const categories = [MemberCategory.UNIQUE_ID, MemberCategory.DEFAULT, MemberCategory.DEFAULT, MemberCategory.DEFAULT, MemberCategory.DEFAULT, MemberCategory.DEFAULT, MemberCategory.DEFAULT, MemberCategory.SHERPA, MemberCategory.DEVELOPER]; const categories = [
return {_id: pmcVictim.Name, info:{Nickname: pmcVictim.Name, Level: pmcVictim.Level, Side: pmcVictim.Side, MemberCategory: this.randomUtil.getArrayValue(categories)}}; MemberCategory.UNIQUE_ID,
MemberCategory.DEFAULT,
MemberCategory.DEFAULT,
MemberCategory.DEFAULT,
MemberCategory.DEFAULT,
MemberCategory.DEFAULT,
MemberCategory.DEFAULT,
MemberCategory.SHERPA,
MemberCategory.DEVELOPER,
];
return {
_id: pmcVictim.Name,
info: {
Nickname: pmcVictim.Name,
Level: pmcVictim.Level,
Side: pmcVictim.Side,
MemberCategory: this.randomUtil.getArrayValue(categories),
},
};
} }
} }

View File

@ -44,7 +44,7 @@ export class ProfileFixerService
@inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("JsonUtil") protected jsonUtil: JsonUtil,
@inject("HashUtil") protected hashUtil: HashUtil, @inject("HashUtil") protected hashUtil: HashUtil,
@inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.coreConfig = this.configServer.getConfig(ConfigTypes.CORE); this.coreConfig = this.configServer.getConfig(ConfigTypes.CORE);
@ -81,30 +81,74 @@ export class ProfileFixerService
this.reorderHideoutAreasWithResouceInputs(pmcProfile); this.reorderHideoutAreasWithResouceInputs(pmcProfile);
if (pmcProfile.Hideout.Areas[HideoutAreas.GENERATOR].slots.length < if (
(6 + this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots.Generator.Slots)) pmcProfile.Hideout.Areas[HideoutAreas.GENERATOR].slots.length <
(6 +
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"); this.logger.debug("Updating generator area slots to a size of 6 + hideout management skill");
this.addEmptyObjectsToHideoutAreaSlots(HideoutAreas.GENERATOR, (6 + this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots.Generator.Slots), pmcProfile); this.addEmptyObjectsToHideoutAreaSlots(
HideoutAreas.GENERATOR,
6 +
this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots
.Generator
.Slots,
pmcProfile,
);
} }
if (pmcProfile.Hideout.Areas[HideoutAreas.WATER_COLLECTOR].slots.length < (1 + this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots.WaterCollector.Slots)) if (
pmcProfile.Hideout.Areas[HideoutAreas.WATER_COLLECTOR].slots.length <
(1 +
this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots
.WaterCollector.Slots)
)
{ {
this.logger.debug("Updating water collector area slots to a size of 1 + hideout management skill"); this.logger.debug("Updating water collector area slots to a size of 1 + hideout management skill");
this.addEmptyObjectsToHideoutAreaSlots(HideoutAreas.WATER_COLLECTOR, (1 + this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots.WaterCollector.Slots), pmcProfile); this.addEmptyObjectsToHideoutAreaSlots(
HideoutAreas.WATER_COLLECTOR,
1 +
this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots
.WaterCollector.Slots,
pmcProfile,
);
} }
if (pmcProfile.Hideout.Areas[HideoutAreas.AIR_FILTERING].slots.length < (3 + this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots.AirFilteringUnit.Slots)) if (
pmcProfile.Hideout.Areas[HideoutAreas.AIR_FILTERING].slots.length <
(3 +
this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots
.AirFilteringUnit.Slots)
)
{ {
this.logger.debug("Updating air filter area slots to a size of 3 + hideout management skill"); this.logger.debug("Updating air filter area slots to a size of 3 + hideout management skill");
this.addEmptyObjectsToHideoutAreaSlots(HideoutAreas.AIR_FILTERING, (3 + this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots.AirFilteringUnit.Slots), pmcProfile); this.addEmptyObjectsToHideoutAreaSlots(
HideoutAreas.AIR_FILTERING,
3 +
this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots
.AirFilteringUnit.Slots,
pmcProfile,
);
} }
// BTC Farm doesnt have extra slots for hideout management, but we still check for modded stuff!! // BTC Farm doesnt have extra slots for hideout management, but we still check for modded stuff!!
if (pmcProfile.Hideout.Areas[HideoutAreas.BITCOIN_FARM].slots.length < (50 + this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots.BitcoinFarm.Slots)) if (
pmcProfile.Hideout.Areas[HideoutAreas.BITCOIN_FARM].slots.length <
(50 +
this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots
.BitcoinFarm.Slots)
)
{ {
this.logger.debug("Updating bitcoin farm area slots to a size of 50 + hideout management skill"); this.logger.debug("Updating bitcoin farm area slots to a size of 50 + hideout management skill");
this.addEmptyObjectsToHideoutAreaSlots(HideoutAreas.BITCOIN_FARM, (50 + this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots.BitcoinFarm.Slots), pmcProfile); this.addEmptyObjectsToHideoutAreaSlots(
HideoutAreas.BITCOIN_FARM,
50 +
this.databaseServer.getTables().globals.config.SkillsSettings.HideoutManagement.EliteSlots
.BitcoinFarm.Slots,
pmcProfile,
);
} }
} }
@ -120,7 +164,7 @@ export class ProfileFixerService
protected addMissingGunStandContainerImprovements(pmcProfile: IPmcData): void 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) if (!weaponStandArea || weaponStandArea.level === 0)
{ {
// No stand in profile or its level 0, skip // No stand in profile or its level 0, skip
@ -128,8 +172,8 @@ export class ProfileFixerService
} }
const db = this.databaseServer.getTables(); const db = this.databaseServer.getTables();
const hideoutStandAreaDb = db.hideout.areas.find(x => x.type === HideoutAreas.WEAPON_STAND); const hideoutStandAreaDb = db.hideout.areas.find((x) => x.type === HideoutAreas.WEAPON_STAND);
const hideoutStandSecondaryAreaDb = db.hideout.areas.find(x => x.parentArea === hideoutStandAreaDb._id); const hideoutStandSecondaryAreaDb = db.hideout.areas.find((x) => x.parentArea === hideoutStandAreaDb._id);
const stageCurrentAt = hideoutStandAreaDb.stages[weaponStandArea.level]; const stageCurrentAt = hideoutStandAreaDb.stages[weaponStandArea.level];
const hideoutStandStashId = pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND]; const hideoutStandStashId = pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND];
const hideoutSecondaryStashId = pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND_SECONDARY]; const hideoutSecondaryStashId = pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND_SECONDARY];
@ -139,51 +183,66 @@ export class ProfileFixerService
{ {
// Value is missing, add it // Value is missing, add it
pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND] = hideoutStandAreaDb._id; pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND] = hideoutStandAreaDb._id;
pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND_SECONDARY] = hideoutStandSecondaryAreaDb._id; pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND_SECONDARY] =
hideoutStandSecondaryAreaDb._id;
// Add stash item to profile // 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) if (gunStandStashItem)
{ {
gunStandStashItem._tpl = stageCurrentAt.container; gunStandStashItem._tpl = stageCurrentAt.container;
this.logger.debug(`Updated existing gun stand inventory stash: ${gunStandStashItem._id} tpl to ${stageCurrentAt.container}`); this.logger.debug(
`Updated existing gun stand inventory stash: ${gunStandStashItem._id} tpl to ${stageCurrentAt.container}`,
);
} }
else else
{ {
pmcProfile.Inventory.items.push({ _id: hideoutStandAreaDb._id, _tpl: stageCurrentAt.container }); pmcProfile.Inventory.items.push({_id: hideoutStandAreaDb._id, _tpl: stageCurrentAt.container});
this.logger.debug(`Added missing gun stand inventory stash: ${hideoutStandAreaDb._id} tpl to ${stageCurrentAt.container}`); this.logger.debug(
`Added missing gun stand inventory stash: ${hideoutStandAreaDb._id} tpl to ${stageCurrentAt.container}`,
);
} }
// Add secondary stash item to profile // 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) if (gunStandStashItem)
{ {
gunStandStashSecondaryItem._tpl = stageCurrentAt.container; gunStandStashSecondaryItem._tpl = stageCurrentAt.container;
this.logger.debug(`Updated gun stand existing inventory secondary stash: ${gunStandStashSecondaryItem._id} tpl to ${stageCurrentAt.container}`); this.logger.debug(
`Updated gun stand existing inventory secondary stash: ${gunStandStashSecondaryItem._id} tpl to ${stageCurrentAt.container}`,
);
} }
else else
{ {
pmcProfile.Inventory.items.push({ _id: hideoutStandSecondaryAreaDb._id, _tpl: stageCurrentAt.container }); pmcProfile.Inventory.items.push({_id: hideoutStandSecondaryAreaDb._id, _tpl: stageCurrentAt.container});
this.logger.debug(`Added missing gun stand inventory secondary stash: ${hideoutStandSecondaryAreaDb._id} tpl to ${stageCurrentAt.container}`); this.logger.debug(
`Added missing gun stand inventory secondary stash: ${hideoutStandSecondaryAreaDb._id} tpl to ${stageCurrentAt.container}`,
);
} }
return; return;
} }
const stashItem = pmcProfile.Inventory.items?.find(x => x._id === hideoutStandAreaDb._id); const stashItem = pmcProfile.Inventory.items?.find((x) => x._id === hideoutStandAreaDb._id);
// `hideoutAreaStashes` has value related stash inventory items tpl doesnt match what's expected // `hideoutAreaStashes` has value related stash inventory items tpl doesnt match what's expected
if (hideoutStandStashId && stashItem?._tpl !== stageCurrentAt.container) if (hideoutStandStashId && stashItem?._tpl !== stageCurrentAt.container)
{ {
this.logger.debug(`primary Stash tpl was: ${stashItem._tpl}, but should be ${stageCurrentAt.container}, updating`); this.logger.debug(
`primary Stash tpl was: ${stashItem._tpl}, but should be ${stageCurrentAt.container}, updating`,
);
// The id inside the profile does not match what the hideout db value is, out of sync, adjust // The id inside the profile does not match what the hideout db value is, out of sync, adjust
stashItem._tpl = stageCurrentAt.container; stashItem._tpl = stageCurrentAt.container;
} }
const stashSecondaryItem = pmcProfile.Inventory.items?.find(x => x._id === hideoutStandSecondaryAreaDb._id); const stashSecondaryItem = pmcProfile.Inventory.items?.find((x) => x._id === hideoutStandSecondaryAreaDb._id);
// `hideoutAreaStashes` has value related stash inventory items tpl doesnt match what's expected // `hideoutAreaStashes` has value related stash inventory items tpl doesnt match what's expected
if (hideoutSecondaryStashId && stashSecondaryItem?._tpl !== stageCurrentAt.container) if (hideoutSecondaryStashId && stashSecondaryItem?._tpl !== stageCurrentAt.container)
{ {
this.logger.debug(`Secondary stash tpl was: ${stashSecondaryItem._tpl}, but should be ${stageCurrentAt.container}, updating`); this.logger.debug(
`Secondary stash tpl was: ${stashSecondaryItem._tpl}, but should be ${stageCurrentAt.container}, updating`,
);
// The id inside the profile does not match what the hideout db value is, out of sync, adjust // The id inside the profile does not match what the hideout db value is, out of sync, adjust
stashSecondaryItem._tpl = stageCurrentAt.container; stashSecondaryItem._tpl = stageCurrentAt.container;
} }
@ -192,10 +251,10 @@ export class ProfileFixerService
protected ensureGunStandLevelsMatch(pmcProfile: IPmcData): void protected ensureGunStandLevelsMatch(pmcProfile: IPmcData): void
{ {
// only proceed if stand is level 1 or above // 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) 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) if (gunStandChild && gunStandParent.level !== gunStandChild.level)
{ {
this.logger.success("Upgraded gun stand levels to match"); this.logger.success("Upgraded gun stand levels to match");
@ -215,7 +274,7 @@ export class ProfileFixerService
protected addMissingHideoutWallAreas(pmcProfile: IPmcData): void 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( pmcProfile.Hideout.Areas.push(
{ {
@ -226,12 +285,12 @@ export class ProfileFixerService
completeTime: 0, completeTime: 0,
constructing: false, constructing: false,
slots: [], slots: [],
lastRecipe: "" lastRecipe: "",
} },
); );
} }
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( pmcProfile.Hideout.Areas.push(
{ {
@ -242,8 +301,8 @@ export class ProfileFixerService
completeTime: 0, completeTime: 0,
constructing: false, constructing: false,
slots: [], slots: [],
lastRecipe: "" lastRecipe: "",
} },
); );
} }
} }
@ -269,7 +328,7 @@ export class ProfileFixerService
continue; continue;
} }
const itemHandbookPrice = handbookPrices.find(x => x.Id === itemTpl); const itemHandbookPrice = handbookPrices.find((x) => x.Id === itemTpl);
if (!itemHandbookPrice) if (!itemHandbookPrice)
{ {
continue; continue;
@ -300,7 +359,7 @@ export class ProfileFixerService
this.logger.debug("Adding aki object to profile"); this.logger.debug("Adding aki object to profile");
fullProfile.aki = { fullProfile.aki = {
version: this.watermark.getVersionTag(), version: this.watermark.getVersionTag(),
receivedGifts: [] receivedGifts: [],
}; };
} }
} }
@ -314,7 +373,7 @@ export class ProfileFixerService
{ {
if (pmcProfile.ConditionCounters) if (pmcProfile.ConditionCounters)
{ {
pmcProfile.ConditionCounters.Counters = pmcProfile.ConditionCounters.Counters.filter(c => c.qid !== null); pmcProfile.ConditionCounters.Counters = pmcProfile.ConditionCounters.Counters.filter((c) => c.qid !== null);
} }
} }
@ -335,7 +394,7 @@ export class ProfileFixerService
salesSum: 0, salesSum: 0,
standing: 0.2, standing: 0.2,
loyaltyLevel: 1, loyaltyLevel: 1,
nextResupply: this.timeUtil.getTimestamp() + 3600 // now + 1 hour nextResupply: this.timeUtil.getTimestamp() + 3600, // now + 1 hour
}; };
} }
} }
@ -346,7 +405,7 @@ export class ProfileFixerService
{ {
this.logger.debug("Adding UnlockedInfo object to profile"); this.logger.debug("Adding UnlockedInfo object to profile");
pmcProfile.UnlockedInfo = { pmcProfile.UnlockedInfo = {
unlockedProductionRecipe: [] unlockedProductionRecipe: [],
}; };
} }
} }
@ -361,8 +420,8 @@ export class ProfileFixerService
{ {
if (pmcProfile.RepeatableQuests && activeQuests.length > 0) if (pmcProfile.RepeatableQuests && activeQuests.length > 0)
{ {
const existsInActiveRepeatableQuests = activeQuests.some(x => x._id === backendCounter.qid); const existsInActiveRepeatableQuests = activeQuests.some((x) => x._id === backendCounter.qid);
const existsInQuests = pmcProfile.Quests.some(q => q.qid === backendCounter.qid); const existsInQuests = pmcProfile.Quests.some((q) => q.qid === backendCounter.qid);
// if BackendCounter's quest is neither in activeQuests nor Quests it's stale // if BackendCounter's quest is neither in activeQuests nor Quests it's stale
if (!existsInActiveRepeatableQuests && !existsInQuests) if (!existsInActiveRepeatableQuests && !existsInQuests)
@ -375,7 +434,7 @@ export class ProfileFixerService
for (const counterKeyToRemove of counterKeysToRemove) for (const counterKeyToRemove of counterKeysToRemove)
{ {
this.logger.debug(`Removed ${counterKeyToRemove} backend count object`); this.logger.debug(`Removed ${counterKeyToRemove} backend count object`);
delete pmcProfile.BackendCounters[counterKeyToRemove]; delete pmcProfile.BackendCounters[counterKeyToRemove];
} }
} }
} }
@ -448,9 +507,13 @@ export class ProfileFixerService
if (quest.status && !Number(quest.status)) if (quest.status && !Number(quest.status))
{ {
if (fixes.has(quest.status)) if (fixes.has(quest.status))
{
fixes.set(quest.status, fixes.get(quest.status) + 1); fixes.set(quest.status, fixes.get(quest.status) + 1);
}
else else
{
fixes.set(quest.status, 1); fixes.set(quest.status, 1);
}
const newQuestStatus = QuestStatus[quest.status]; const newQuestStatus = QuestStatus[quest.status];
quest.status = <QuestStatus><unknown>newQuestStatus; quest.status = <QuestStatus><unknown>newQuestStatus;
@ -461,7 +524,7 @@ export class ProfileFixerService
{ {
const newKey = QuestStatus[statusTimer]; const newKey = QuestStatus[statusTimer];
quest.statusTimers[newKey] = quest.statusTimers[statusTimer]; quest.statusTimers[newKey] = quest.statusTimers[statusTimer];
delete quest.statusTimers[statusTimer]; delete quest.statusTimers[statusTimer];
} }
} }
} }
@ -473,7 +536,13 @@ export class ProfileFixerService
} }
if (fixes.size > 0) if (fixes.size > 0)
this.logger.debug(`Updated quests values: ${Array.from(fixes.entries()).map(([k, v]) => `(${k}: ${v} times)`).join(", ")}`); {
this.logger.debug(
`Updated quests values: ${
Array.from(fixes.entries()).map(([k, v]) => `(${k}: ${v} times)`).join(", ")
}`,
);
}
} }
protected addMissingRepeatableQuestsProperty(pmcProfile: IPmcData): void protected addMissingRepeatableQuestsProperty(pmcProfile: IPmcData): void
@ -485,7 +554,9 @@ export class ProfileFixerService
{ {
if ( if (
!(currentRepeatable.changeRequirement && !(currentRepeatable.changeRequirement &&
currentRepeatable.activeQuests.every(x => (typeof x.changeCost !== "undefined" && typeof x.changeStandingCost !== "undefined"))) currentRepeatable.activeQuests.every(
(x) => (typeof x.changeCost !== "undefined" && typeof x.changeStandingCost !== "undefined"),
))
) )
{ {
repeatablesCompatible = false; repeatablesCompatible = false;
@ -507,7 +578,9 @@ export class ProfileFixerService
protected addMissingWallImprovements(pmcProfile: IPmcData): void protected addMissingWallImprovements(pmcProfile: IPmcData): void
{ {
const profileWallArea = pmcProfile.Hideout.Areas[HideoutAreas.EMERGENCY_WALL]; const profileWallArea = pmcProfile.Hideout.Areas[HideoutAreas.EMERGENCY_WALL];
const wallDb = this.databaseServer.getTables().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) if (profileWallArea.level > 0)
{ {
@ -531,7 +604,7 @@ export class ProfileFixerService
pmcProfile.Hideout.Improvement[improvement.id] = { pmcProfile.Hideout.Improvement[improvement.id] = {
completed: true, completed: true,
improveCompleteTimestamp: this.timeUtil.getTimestamp() + i // add some variability improveCompleteTimestamp: this.timeUtil.getTimestamp() + i, // add some variability
}; };
this.logger.debug(`Added wall improvement ${improvement.id} to profile`); this.logger.debug(`Added wall improvement ${improvement.id} to profile`);
@ -555,13 +628,13 @@ export class ProfileFixerService
} }
// Only slots with location index // 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: // Only slots that:
// Have an item property and it has at least one item in it // Have an item property and it has at least one item in it
// Or // Or
// Have no item property // 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));
} }
} }
@ -571,7 +644,12 @@ export class ProfileFixerService
*/ */
protected reorderHideoutAreasWithResouceInputs(pmcProfile: IPmcData): void protected reorderHideoutAreasWithResouceInputs(pmcProfile: IPmcData): void
{ {
const areasToCheck = [HideoutAreas.AIR_FILTERING, HideoutAreas.GENERATOR, HideoutAreas.BITCOIN_FARM, HideoutAreas.WATER_COLLECTOR]; const areasToCheck = [
HideoutAreas.AIR_FILTERING,
HideoutAreas.GENERATOR,
HideoutAreas.BITCOIN_FARM,
HideoutAreas.WATER_COLLECTOR,
];
for (const areaId of areasToCheck) for (const areaId of areasToCheck)
{ {
@ -583,13 +661,13 @@ export class ProfileFixerService
continue; continue;
} }
if (!area.slots || area.slots.length === 0) if (!area.slots || area.slots.length === 0)
{ {
this.logger.debug(`unable to sort ${areaId} slots, no slots found`); this.logger.debug(`unable to sort ${areaId} slots, no slots found`);
continue; continue;
} }
area.slots = area.slots.sort( (a, b) => area.slots = area.slots.sort((a, b) =>
{ {
return a.locationIndex > b.locationIndex ? 1 : -1; return a.locationIndex > b.locationIndex ? 1 : -1;
}); });
@ -601,10 +679,13 @@ export class ProfileFixerService
* @param areaType area to check * @param areaType area to check
* @param pmcProfile profile to update * @param pmcProfile profile to update
*/ */
protected addEmptyObjectsToHideoutAreaSlots(areaType: HideoutAreas, emptyItemCount: number, pmcProfile: IPmcData): void protected addEmptyObjectsToHideoutAreaSlots(
areaType: HideoutAreas,
emptyItemCount: number,
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); area.slots = this.addObjectsToArray(emptyItemCount, area.slots);
} }
@ -612,14 +693,13 @@ export class ProfileFixerService
{ {
for (let i = 0; i < count; i++) 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}); slots.push({locationIndex: i});
} }
} }
return slots; return slots;
} }
/** /**
@ -628,7 +708,7 @@ export class ProfileFixerService
*/ */
protected updateProfilePocketsToNewId(pmcProfile: IPmcData): void protected updateProfilePocketsToNewId(pmcProfile: IPmcData): void
{ {
const pocketItem = pmcProfile.Inventory?.items?.find(x => x.slotId === "Pockets"); const pocketItem = pmcProfile.Inventory?.items?.find((x) => x.slotId === "Pockets");
if (pocketItem) if (pocketItem)
{ {
if (pocketItem._tpl === "557ffd194bdc2d28148b457f") if (pocketItem._tpl === "557ffd194bdc2d28148b457f")
@ -668,7 +748,7 @@ export class ProfileFixerService
} }
// Iterate over area levels, check for bonuses, add if needed // 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) if (!dbArea)
{ {
continue; continue;
@ -691,7 +771,11 @@ export class ProfileFixerService
if (!profileBonus) if (!profileBonus)
{ {
// no bonus, add to profile // no bonus, add to profile
this.logger.debug(`Profile has level ${level} area ${HideoutAreas[area.type]} but no bonus found, adding ${bonus.type}`); this.logger.debug(
`Profile has level ${level} area ${
HideoutAreas[area.type]
} but no bonus found, adding ${bonus.type}`,
);
this.hideoutHelper.applyPlayerUpgradesBonuses(pmcProfile, bonus); this.hideoutHelper.applyPlayerUpgradesBonuses(pmcProfile, bonus);
} }
} }
@ -700,7 +784,6 @@ export class ProfileFixerService
} }
/** /**
*
* @param profileBonuses bonuses from profile * @param profileBonuses bonuses from profile
* @param bonus bonus to find * @param bonus bonus to find
* @returns matching bonus * @returns matching bonus
@ -710,27 +793,33 @@ export class ProfileFixerService
// match by id first, used by "TextBonus" bonuses // match by id first, used by "TextBonus" bonuses
if (bonus.id) if (bonus.id)
{ {
return profileBonuses.find(x => x.id === bonus.id); return profileBonuses.find((x) => x.id === bonus.id);
} }
if (bonus.type.toLowerCase() === "stashsize") if (bonus.type.toLowerCase() === "stashsize")
{ {
return profileBonuses.find( return profileBonuses.find(
x => x.type === bonus.type (x) =>
&& x.templateId === bonus.templateId); x.type === bonus.type &&
x.templateId === bonus.templateId,
);
} }
if (bonus.type.toLowerCase() === "additionalslots") if (bonus.type.toLowerCase() === "additionalslots")
{ {
return profileBonuses.find( return profileBonuses.find(
x => x.type === bonus.type (x) =>
&& x.value === bonus.value x.type === bonus.type &&
&& x.visible === bonus.visible); x.value === bonus.value &&
x.visible === bonus.visible,
);
} }
return profileBonuses.find( return profileBonuses.find(
x => x.type === bonus.type (x) =>
&& x.value === bonus.value); x.type === bonus.type &&
x.value === bonus.value,
);
} }
/** /**
@ -745,7 +834,7 @@ export class ProfileFixerService
// Get items placed in root of stash // Get items placed in root of stash
// TODO: extend to other areas / sub items // TODO: extend to other areas / sub items
const inventoryItemsToCheck = pmcProfile.Inventory.items.filter(x => ["hideout", "main"].includes(x.slotId)); const inventoryItemsToCheck = pmcProfile.Inventory.items.filter((x) => ["hideout", "main"].includes(x.slotId));
if (!inventoryItemsToCheck) if (!inventoryItemsToCheck)
{ {
return; return;
@ -760,7 +849,9 @@ export class ProfileFixerService
if (this.coreConfig.fixes.removeModItemsFromProfile) if (this.coreConfig.fixes.removeModItemsFromProfile)
{ {
this.logger.success(`Deleting item from inventory and insurance with id: ${item._id} tpl: ${item._tpl}`); this.logger.success(
`Deleting item from inventory and insurance with id: ${item._id} tpl: ${item._tpl}`,
);
// Also deletes from insured array // Also deletes from insured array
this.inventoryHelper.removeItem(pmcProfile, item._id, sessionId); this.inventoryHelper.removeItem(pmcProfile, item._id, sessionId);
@ -781,7 +872,9 @@ export class ProfileFixerService
if (this.coreConfig.fixes.removeModItemsFromProfile) if (this.coreConfig.fixes.removeModItemsFromProfile)
{ {
delete fullProfile.userbuilds.weaponBuilds[buildId]; delete fullProfile.userbuilds.weaponBuilds[buildId];
this.logger.warning(`Item: ${item._tpl} has resulted in the deletion of weapon build: ${buildId}`); this.logger.warning(
`Item: ${item._tpl} has resulted in the deletion of weapon build: ${buildId}`,
);
} }
break; break;
@ -824,8 +917,10 @@ export class ProfileFixerService
if (this.coreConfig.fixes.removeModItemsFromProfile) 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}`); this.logger.warning(
`Item: ${item._tpl} has resulted in the deletion of message: ${message._id} from dialog ${dialogId}`,
);
} }
break; break;
@ -857,8 +952,13 @@ export class ProfileFixerService
this.logger.error(this.localisationService.getText("fixer-mod_item_found", activeQuest.traderId)); this.logger.error(this.localisationService.getText("fixer-mod_item_found", activeQuest.traderId));
if (this.coreConfig.fixes.removeModItemsFromProfile) if (this.coreConfig.fixes.removeModItemsFromProfile)
{ {
this.logger.warning(`Non-default quest: ${activeQuest._id} from trader: ${activeQuest.traderId} removed from RepeatableQuests list in profile`); this.logger.warning(
repeatable.activeQuests.splice(repeatable.activeQuests.findIndex(x => x._id === activeQuest._id), 1); `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),
1,
);
} }
continue; continue;
@ -872,11 +972,18 @@ export class ProfileFixerService
{ {
if (!itemsDb[rewardItem._tpl]) if (!itemsDb[rewardItem._tpl])
{ {
this.logger.error(this.localisationService.getText("fixer-mod_item_found", rewardItem._tpl)); this.logger.error(
this.localisationService.getText("fixer-mod_item_found", rewardItem._tpl),
);
if (this.coreConfig.fixes.removeModItemsFromProfile) if (this.coreConfig.fixes.removeModItemsFromProfile)
{ {
this.logger.warning(`Non-default quest: ${activeQuest._id} from trader: ${activeQuest.traderId} removed from RepeatableQuests list in profile`); this.logger.warning(
repeatable.activeQuests.splice(repeatable.activeQuests.findIndex(x => x._id === activeQuest._id), 1); `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),
1,
);
} }
} }
} }
@ -939,7 +1046,7 @@ export class ProfileFixerService
// Get all areas from templates/profiles.json // Get all areas from templates/profiles.json
for (const area of profileTemplate.character.Hideout.Areas) 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); pmcProfile.Hideout.Areas.push(area);
this.logger.debug(`Added missing hideout area ${area.type} to profile`); this.logger.debug(`Added missing hideout area ${area.type} to profile`);
@ -957,7 +1064,7 @@ export class ProfileFixerService
{ {
if (prodKey.startsWith("ScavCase")) if (prodKey.startsWith("ScavCase"))
{ {
delete pmcProfile.Hideout.Production[prodKey]; delete pmcProfile.Hideout.Production[prodKey];
} }
} }
} }
@ -980,7 +1087,9 @@ export class ProfileFixerService
fullProfile.info.aid = fullProfile.characters.pmc.aid; fullProfile.info.aid = fullProfile.characters.pmc.aid;
this.logger.debug(`Migrated AccountId from: ${fullProfile.characters.pmc.sessionId} to: ${fullProfile.characters.pmc.aid}`); this.logger.debug(
`Migrated AccountId from: ${fullProfile.characters.pmc.sessionId} to: ${fullProfile.characters.pmc.aid}`,
);
} }
} }
@ -1025,7 +1134,9 @@ export class ProfileFixerService
for (const stageIndex in area.stages) for (const stageIndex in area.stages)
{ {
const stageInfo = area.stages[stageIndex]; 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) if (matchingBonus)
{ {
// Add id to bonus, flag bonus as found and exit stage loop // Add id to bonus, flag bonus as found and exit stage loop

View File

@ -9,7 +9,7 @@ export class ProfileSnapshotService
protected storedProfileSnapshots: Record<string, IAkiProfile> = {}; protected storedProfileSnapshots: Record<string, IAkiProfile> = {};
constructor( constructor(
@inject("JsonUtil") protected jsonUtil: JsonUtil @inject("JsonUtil") protected jsonUtil: JsonUtil,
) )
{} {}

View File

@ -9,9 +9,9 @@ export class RagfairCategoriesService
protected categories: Record<string, number> = {}; protected categories: Record<string, number> = {};
constructor( constructor(
@inject("WinstonLogger") protected logger: ILogger @inject("WinstonLogger") protected logger: ILogger,
) )
{ } {}
/** /**
* Get all flea categories and their count of offers * Get all flea categories and their count of offers
@ -53,14 +53,14 @@ export class RagfairCategoriesService
* @param categories Categories to update * @param categories Categories to update
* @param increment (Optional) Should item be incremented or decremented * @param increment (Optional) Should item be incremented or decremented
*/ */
protected addOrIncrementCategory(offer: IRagfairOffer, categories: Record<string, number>, increment = true ): void protected addOrIncrementCategory(offer: IRagfairOffer, categories: Record<string, number>, increment = true): void
{ {
const itemId = offer.items[0]._tpl; const itemId = offer.items[0]._tpl;
if (increment) if (increment)
{ {
categories[itemId] = categories[itemId] categories[itemId] = categories[itemId] ?
? categories[itemId] + 1 categories[itemId] + 1 :
: 1; 1;
} }
else else
{ {

View File

@ -12,9 +12,9 @@ export class RagfairLinkedItemService
constructor( constructor(
@inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("ItemHelper") protected itemHelper: ItemHelper @inject("ItemHelper") protected itemHelper: ItemHelper,
) )
{ } {}
public getLinkedItems(linkedSearchId: string): Set<string> public getLinkedItems(linkedSearchId: string): Set<string>
{ {
@ -34,7 +34,7 @@ export class RagfairLinkedItemService
public getLinkedDbItems(itemTpl: string): ITemplateItem[] public getLinkedDbItems(itemTpl: string): ITemplateItem[]
{ {
const linkedItemsToWeaponTpls = this.getLinkedItems(itemTpl); const linkedItemsToWeaponTpls = this.getLinkedItems(itemTpl);
return [...linkedItemsToWeaponTpls].map(x => return [...linkedItemsToWeaponTpls].map((x) =>
{ {
const itemDetails = this.itemHelper.getItem(x); const itemDetails = this.itemHelper.getItem(x);
return itemDetails[1]; return itemDetails[1];
@ -90,9 +90,12 @@ export class RagfairLinkedItemService
* @param cylinder Revolvers cylinder * @param cylinder Revolvers cylinder
* @param applyLinkedItems * @param applyLinkedItems
*/ */
protected addRevolverCylinderAmmoToLinkedItems(cylinder: ITemplateItem, applyLinkedItems: (items: string[]) => void): void protected addRevolverCylinderAmmoToLinkedItems(
cylinder: ITemplateItem,
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) if (cylinderMod)
{ {
// Get the first cylinder filter tpl // Get the first cylinder filter tpl

View File

@ -38,7 +38,7 @@ export class RagfairOfferService
@inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder, @inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder,
@inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR);
@ -118,7 +118,9 @@ export class RagfairOfferService
const offer = this.ragfairOfferHandler.getOfferById(offerId); const offer = this.ragfairOfferHandler.getOfferById(offerId);
if (!offer) if (!offer)
{ {
this.logger.warning(this.localisationService.getText("ragfair-unable_to_remove_offer_doesnt_exist", offerId)); this.logger.warning(
this.localisationService.getText("ragfair-unable_to_remove_offer_doesnt_exist", offerId),
);
return; return;
} }
@ -235,7 +237,7 @@ export class RagfairOfferService
const pmcID = String(offer.user.id); const pmcID = String(offer.user.id);
const profile = this.profileHelper.getProfileByPmcId(pmcID); const profile = this.profileHelper.getProfileByPmcId(pmcID);
const sessionID = profile.sessionId; const sessionID = profile.sessionId;
const offerIndex = profile.RagfairInfo.offers.findIndex(o => o._id === offer._id); const offerIndex = profile.RagfairInfo.offers.findIndex((o) => o._id === offer._id);
profile.RagfairInfo.rating -= this.ragfairConfig.sell.reputation.loss; profile.RagfairInfo.rating -= this.ragfairConfig.sell.reputation.loss;
profile.RagfairInfo.isRatingGrowing = false; profile.RagfairInfo.isRatingGrowing = false;
@ -243,7 +245,10 @@ export class RagfairOfferService
if (offerIndex === -1) if (offerIndex === -1)
{ {
this.logger.warning(this.localisationService.getText("ragfair-unable_to_find_offer_to_remove", offer._id)); this.logger.warning(this.localisationService.getText("ragfair-unable_to_find_offer_to_remove", offer._id));
return this.httpResponse.appendErrorToOutput(this.eventOutputHolder.getOutput(sessionID), this.localisationService.getText("ragfair-offer_not_found_in_profile_short")); return this.httpResponse.appendErrorToOutput(
this.eventOutputHolder.getOutput(sessionID),
this.localisationService.getText("ragfair-offer_not_found_in_profile_short"),
);
} }
if (offer.items[0].upd.StackObjectsCount > offer.items[0].upd.OriginalStackObjectsCount) if (offer.items[0].upd.StackObjectsCount > offer.items[0].upd.OriginalStackObjectsCount)

View File

@ -31,7 +31,7 @@ export class RagfairPriceService implements OnLoad
protected prices: IRagfairServerPrices = { protected prices: IRagfairServerPrices = {
static: {}, static: {},
dynamic: {} dynamic: {},
}; };
constructor( constructor(
@ -43,7 +43,7 @@ export class RagfairPriceService implements OnLoad
@inject("TraderHelper") protected traderHelper: TraderHelper, @inject("TraderHelper") protected traderHelper: TraderHelper,
@inject("RandomUtil") protected randomUtil: RandomUtil, @inject("RandomUtil") protected randomUtil: RandomUtil,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR);
@ -77,7 +77,11 @@ export class RagfairPriceService implements OnLoad
*/ */
public generateStaticPrices(): void 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)); this.prices.static[item._id] = Math.round(this.handbookHelper.getTemplatePrice(item._id));
} }
@ -103,7 +107,9 @@ export class RagfairPriceService implements OnLoad
let itemPrice = this.getDynamicPriceForItem(tplId) || this.getStaticPriceForItem(tplId); let itemPrice = this.getDynamicPriceForItem(tplId) || this.getStaticPriceForItem(tplId);
if (!itemPrice) if (!itemPrice)
{ {
this.logger.warning(this.localisationService.getText("ragfair-unable_to_find_item_price_for_item_in_flea_handbook", tplId)); this.logger.warning(
this.localisationService.getText("ragfair-unable_to_find_item_price_for_item_in_flea_handbook", tplId),
);
} }
// If no price in dynamic/static, set to 1 // If no price in dynamic/static, set to 1
@ -150,7 +156,7 @@ export class RagfairPriceService implements OnLoad
public getAllFleaPrices(): Record<string, number> public getAllFleaPrices(): Record<string, number>
{ {
// assign static values first, then overwrite them with dynamic, any values not stored in dynamic data will be covered by static data // assign static values first, then overwrite them with dynamic, any values not stored in dynamic data will be covered by static data
return { ...this.prices.static, ...this.prices.dynamic }; return {...this.prices.static, ...this.prices.dynamic};
} }
public getAllStaticPrices(): Record<string, number> public getAllStaticPrices(): Record<string, number>
@ -180,7 +186,7 @@ export class RagfairPriceService implements OnLoad
for (const item of barterScheme) for (const item of barterScheme)
{ {
price += (this.prices.static[item._tpl] * item.count); price += this.prices.static[item._tpl] * item.count;
} }
return Math.round(price); return Math.round(price);
@ -291,12 +297,17 @@ export class RagfairPriceService implements OnLoad
const priceDifferencePercent = this.getPriceDifference(itemHandbookPrice, itemPrice); const priceDifferencePercent = this.getPriceDifference(itemHandbookPrice, itemPrice);
// Only adjust price if difference is > a percent AND item price passes threshhold set in config // Only adjust price if difference is > a percent AND item price passes threshhold set in config
if (priceDifferencePercent > this.ragfairConfig.dynamic.offerAdjustment.maxPriceDifferenceBelowHandbookPercent if (
&& itemPrice >= this.ragfairConfig.dynamic.offerAdjustment.priceThreshholdRub) priceDifferencePercent >
this.ragfairConfig.dynamic.offerAdjustment.maxPriceDifferenceBelowHandbookPercent &&
itemPrice >= this.ragfairConfig.dynamic.offerAdjustment.priceThreshholdRub
)
{ {
//const itemDetails = this.itemHelper.getItem(itemTpl); // const itemDetails = this.itemHelper.getItem(itemTpl);
//this.logger.debug(`item below handbook price ${itemDetails[1]._name} handbook: ${itemHandbookPrice} flea: ${itemPrice} ${priceDifferencePercent}%`); // this.logger.debug(`item below handbook price ${itemDetails[1]._name} handbook: ${itemHandbookPrice} flea: ${itemPrice} ${priceDifferencePercent}%`);
itemPrice = Math.round(itemHandbookPrice * this.ragfairConfig.dynamic.offerAdjustment.handbookPriceMultipier); itemPrice = Math.round(
itemHandbookPrice * this.ragfairConfig.dynamic.offerAdjustment.handbookPriceMultipier,
);
} }
return itemPrice; return itemPrice;
@ -344,7 +355,9 @@ export class RagfairPriceService implements OnLoad
} }
// Get mods on current gun not in default preset // Get mods on current gun not in default preset
const newOrReplacedModsInPresetVsDefault = items.filter(x => !presetResult.preset._items.some(y => y._tpl === x._tpl)); const newOrReplacedModsInPresetVsDefault = items.filter((x) =>
!presetResult.preset._items.some((y) => y._tpl === x._tpl)
);
// Add up extra mods price // Add up extra mods price
let extraModsPrice = 0; let extraModsPrice = 0;
@ -358,7 +371,9 @@ export class RagfairPriceService implements OnLoad
if (newOrReplacedModsInPresetVsDefault.length >= 1) if (newOrReplacedModsInPresetVsDefault.length >= 1)
{ {
// Add up cost of mods replaced // 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 // Add up replaced mods price
let replacedModsPrice = 0; let replacedModsPrice = 0;
@ -398,29 +413,37 @@ export class RagfairPriceService implements OnLoad
* @param presets weapon presets to choose from * @param presets weapon presets to choose from
* @returns Default preset object * @returns Default preset object
*/ */
protected getWeaponPreset(presets: IPreset[], weapon: Item): {isDefault: boolean, preset: IPreset} protected getWeaponPreset(presets: IPreset[], weapon: Item): {isDefault: boolean; preset: IPreset;}
{ {
const defaultPreset = presets.find(x => x._encyclopedia); const defaultPreset = presets.find((x) => x._encyclopedia);
if (defaultPreset) if (defaultPreset)
{ {
return { return {
isDefault: true, isDefault: true,
preset: defaultPreset preset: defaultPreset,
}; };
} }
if (presets.length === 1) if (presets.length === 1)
{ {
this.logger.debug(`Item Id: ${weapon._tpl} has no default encyclopedia entry but only one preset (${presets[0]._name}), choosing preset (${presets[0]._name})`); this.logger.debug(
`Item Id: ${weapon._tpl} has no default encyclopedia entry but only one preset (${
presets[0]._name
}), choosing preset (${presets[0]._name})`,
);
} }
else else
{ {
this.logger.debug(`Item Id: ${weapon._tpl} has no default encyclopedia entry, choosing first preset (${presets[0]._name}) of ${presets.length}`); this.logger.debug(
`Item Id: ${weapon._tpl} has no default encyclopedia entry, choosing first preset (${
presets[0]._name
}) of ${presets.length}`,
);
} }
return { return {
isDefault: false, isDefault: false,
preset: presets[0] preset: presets[0],
}; };
} }
} }

View File

@ -12,9 +12,9 @@ export class RagfairRequiredItemsService
constructor( constructor(
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("PaymentHelper") protected paymentHelper: PaymentHelper, @inject("PaymentHelper") protected paymentHelper: PaymentHelper,
@inject("RagfairOfferService") protected ragfairOfferService: RagfairOfferService @inject("RagfairOfferService") protected ragfairOfferService: RagfairOfferService,
) )
{ } {}
public getRequiredItemsById(searchId: string): any public getRequiredItemsById(searchId: string): any
{ {
@ -50,5 +50,4 @@ export class RagfairRequiredItemsService
this.requiredItemsCache = requiredItems; this.requiredItemsCache = requiredItems;
} }
} }

View File

@ -18,9 +18,9 @@ export class RagfairTaxService
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService, @inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService,
@inject("ItemHelper") protected itemHelper: ItemHelper @inject("ItemHelper") protected itemHelper: ItemHelper,
) )
{ } {}
public storeClientOfferTaxValue(sessionId: string, offer: IStorePlayerOfferTaxAmountRequestData): void public storeClientOfferTaxValue(sessionId: string, offer: IStorePlayerOfferTaxAmountRequestData): void
{ {
@ -39,7 +39,13 @@ export class RagfairTaxService
// This method, along with calculateItemWorth, is trying to mirror the client-side code found in the method "CalculateTaxPrice". // This method, along with calculateItemWorth, is trying to mirror the client-side code found in the method "CalculateTaxPrice".
// It's structured to resemble the client-side code as closely as possible - avoid making any big structure changes if it's not necessary. // It's structured to resemble the client-side code as closely as possible - avoid making any big structure changes if it's not necessary.
public calculateTax(item: Item, pmcData: IPmcData, requirementsValue: number, offerItemCount: number, sellInOnePiece: boolean): number public calculateTax(
item: Item,
pmcData: IPmcData,
requirementsValue: number,
offerItemCount: number,
sellInOnePiece: boolean,
): number
{ {
if (!requirementsValue) if (!requirementsValue)
{ {
@ -56,7 +62,8 @@ export class RagfairTaxService
const requirementsPrice = requirementsValue * (sellInOnePiece ? 1 : offerItemCount); const requirementsPrice = requirementsValue * (sellInOnePiece ? 1 : offerItemCount);
const itemTaxMult = this.databaseServer.getTables().globals.config.RagFair.communityItemTax / 100.0; 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 itemPriceMult = Math.log10(itemWorth / requirementsPrice);
let requirementPriceMult = Math.log10(requirementsPrice / itemWorth); let requirementPriceMult = Math.log10(requirementsPrice / itemWorth);
@ -73,12 +80,15 @@ export class RagfairTaxService
itemPriceMult = 4 ** itemPriceMult; itemPriceMult = 4 ** itemPriceMult;
requirementPriceMult = 4 ** requirementPriceMult; requirementPriceMult = 4 ** requirementPriceMult;
const hideoutFleaTaxDiscountBonus = pmcData.Bonuses.find(b => b.type === "RagfairCommission"); const hideoutFleaTaxDiscountBonus = pmcData.Bonuses.find((b) => b.type === "RagfairCommission");
const taxDiscountPercent = hideoutFleaTaxDiscountBonus ? Math.abs(hideoutFleaTaxDiscountBonus.value) : 0; 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 discountedTax = tax * (1.0 - taxDiscountPercent / 100.0);
const itemComissionMult = itemTemplate._props.RagFairCommissionModifier ? itemTemplate._props.RagFairCommissionModifier : 1; const itemComissionMult = itemTemplate._props.RagFairCommissionModifier ?
itemTemplate._props.RagFairCommissionModifier :
1;
if (item.upd.Buff) if (item.upd.Buff)
{ {
@ -93,13 +103,19 @@ export class RagfairTaxService
// This method is trying to replicate the item worth calculation method found in the client code. // This method is trying to replicate the item worth calculation method found in the client code.
// Any inefficiencies or style issues are intentional and should not be fixed, to preserve the client-side code mirroring. // Any inefficiencies or style issues are intentional and should not be fixed, to preserve the client-side code mirroring.
protected calculateItemWorth(item: Item, itemTemplate: ITemplateItem, itemCount: number, pmcData: IPmcData, isRootItem = true): number protected calculateItemWorth(
item: Item,
itemTemplate: ITemplateItem,
itemCount: number,
pmcData: IPmcData,
isRootItem = true,
): number
{ {
let worth = this.ragfairPriceService.getFleaPriceForItem(item._tpl); let worth = this.ragfairPriceService.getFleaPriceForItem(item._tpl);
// In client, all item slots are traversed and any items contained within have their values added // 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 if (isRootItem)
{ { // 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); const itemChildren = this.itemHelper.findAndReturnChildrenAsItems(pmcData.Inventory.items, item._id);
if (itemChildren.length > 1) if (itemChildren.length > 1)
{ {
@ -110,7 +126,13 @@ export class RagfairTaxService
continue; continue;
} }
worth += this.calculateItemWorth(child, this.itemHelper.getItem(child._tpl)[1], child.upd.StackObjectsCount, pmcData, false); worth += this.calculateItemWorth(
child,
this.itemHelper.getItem(child._tpl)[1],
child.upd.StackObjectsCount,
pmcData,
false,
);
} }
} }
} }
@ -122,7 +144,8 @@ export class RagfairTaxService
if ("Key" in item.upd && itemTemplate._props.MaximumNumberOfUsage > 0) if ("Key" in item.upd && itemTemplate._props.MaximumNumberOfUsage > 0)
{ {
worth = worth / itemTemplate._props.MaximumNumberOfUsage * (itemTemplate._props.MaximumNumberOfUsage - item.upd.Key.NumberOfUsages); worth = worth / itemTemplate._props.MaximumNumberOfUsage *
(itemTemplate._props.MaximumNumberOfUsage - item.upd.Key.NumberOfUsages);
} }
if ("Resource" in item.upd && itemTemplate._props.MaxResource > 0) if ("Resource" in item.upd && itemTemplate._props.MaxResource > 0)
@ -148,7 +171,11 @@ export class RagfairTaxService
if ("Repairable" in item.upd && <number>itemTemplate._props.armorClass > 0) if ("Repairable" in item.upd && <number>itemTemplate._props.armorClass > 0)
{ {
const num2 = 0.01 * (0.0 ** item.upd.Repairable.MaxDurability); const num2 = 0.01 * (0.0 ** item.upd.Repairable.MaxDurability);
worth = worth * ((item.upd.Repairable.MaxDurability / itemTemplate._props.Durability) - num2) - Math.floor(itemTemplate._props.RepairCost * (item.upd.Repairable.MaxDurability - item.upd.Repairable.Durability)); worth = worth * ((item.upd.Repairable.MaxDurability / itemTemplate._props.Durability) - num2) -
Math.floor(
itemTemplate._props.RepairCost *
(item.upd.Repairable.MaxDurability - item.upd.Repairable.Durability),
);
} }
return worth * itemCount; return worth * itemCount;

View File

@ -39,7 +39,7 @@ export class RepairService
@inject("PaymentService") protected paymentService: PaymentService, @inject("PaymentService") protected paymentService: PaymentService,
@inject("RepairHelper") protected repairHelper: RepairHelper, @inject("RepairHelper") protected repairHelper: RepairHelper,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.repairConfig = this.configServer.getConfig(ConfigTypes.REPAIR); this.repairConfig = this.configServer.getConfig(ConfigTypes.REPAIR);
@ -53,9 +53,14 @@ export class RepairService
* @param traderId Trader being used to repair item * @param traderId Trader being used to repair item
* @returns RepairDetails object * @returns RepairDetails object
*/ */
public repairItemByTrader(sessionID: string, pmcData: IPmcData, repairItemDetails: RepairItem, traderId: string): RepairDetails public repairItemByTrader(
sessionID: string,
pmcData: IPmcData,
repairItemDetails: RepairItem,
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) if (itemToRepair === undefined)
{ {
throw new Error(`Item ${repairItemDetails._id} not found in profile inventory, unable to repair`); throw new Error(`Item ${repairItemDetails._id} not found in profile inventory, unable to repair`);
@ -64,12 +69,12 @@ export class RepairService
const priceCoef = this.traderHelper.getLoyaltyLevel(traderId, pmcData).repair_price_coef; const priceCoef = this.traderHelper.getLoyaltyLevel(traderId, pmcData).repair_price_coef;
const traderRepairDetails = this.traderHelper.getTrader(traderId, sessionID).repair; const traderRepairDetails = this.traderHelper.getTrader(traderId, sessionID).repair;
const repairQualityMultiplier = traderRepairDetails.quality; const repairQualityMultiplier = traderRepairDetails.quality;
const repairRate = (priceCoef <= 0) const repairRate = (priceCoef <= 0) ?
? 1 1 :
: (priceCoef / 100 + 1); (priceCoef / 100 + 1);
const itemToRepairDetails = this.databaseServer.getTables().templates.items[itemToRepair._tpl]; const itemToRepairDetails = this.databaseServer.getTables().templates.items[itemToRepair._tpl];
const repairItemIsArmor = (!!itemToRepairDetails._props.ArmorMaterial); const repairItemIsArmor = !!itemToRepairDetails._props.ArmorMaterial;
this.repairHelper.updateItemDurability( this.repairHelper.updateItemDurability(
itemToRepair, itemToRepair,
@ -78,12 +83,14 @@ export class RepairService
repairItemDetails.count, repairItemDetails.count,
false, false,
repairQualityMultiplier, repairQualityMultiplier,
repairQualityMultiplier !== 0 && this.repairConfig.applyRandomizeDurabilityLoss repairQualityMultiplier !== 0 && this.repairConfig.applyRandomizeDurabilityLoss,
); );
// get repair price // get repair price
const itemRepairCost = this.databaseServer.getTables().templates.items[itemToRepair._tpl]._props.RepairCost; const itemRepairCost = this.databaseServer.getTables().templates.items[itemToRepair._tpl]._props.RepairCost;
const repairCost = Math.round((itemRepairCost * repairItemDetails.count * repairRate) * this.repairConfig.priceMultiplier); const repairCost = Math.round(
(itemRepairCost * repairItemDetails.count * repairRate) * this.repairConfig.priceMultiplier,
);
this.logger.debug(`item base repair cost: ${itemRepairCost}`, true); this.logger.debug(`item base repair cost: ${itemRepairCost}`, true);
this.logger.debug(`price multipler: ${this.repairConfig.priceMultiplier}`, true); this.logger.debug(`price multipler: ${this.repairConfig.priceMultiplier}`, true);
@ -94,12 +101,11 @@ export class RepairService
repairedItem: itemToRepair, repairedItem: itemToRepair,
repairedItemIsArmor: repairItemIsArmor, repairedItemIsArmor: repairItemIsArmor,
repairAmount: repairItemDetails.count, repairAmount: repairItemDetails.count,
repairedByKit: false repairedByKit: false,
}; };
} }
/** /**
*
* @param sessionID Session id * @param sessionID Session id
* @param pmcData profile to take money from * @param pmcData profile to take money from
* @param repairedItemId Repaired item id * @param repairedItemId Repaired item id
@ -113,15 +119,16 @@ export class RepairService
repairedItemId: string, repairedItemId: string,
repairCost: number, repairCost: number,
traderId: string, traderId: string,
output: IItemEventRouterResponse): void output: IItemEventRouterResponse,
): void
{ {
const options: IProcessBuyTradeRequestData = { const options: IProcessBuyTradeRequestData = {
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
scheme_items: [ scheme_items: [
{ {
id: repairedItemId, id: repairedItemId,
count: Math.round(repairCost) count: Math.round(repairCost),
} },
], ],
tid: traderId, tid: traderId,
Action: "", Action: "",
@ -130,7 +137,7 @@ export class RepairService
item_id: "", item_id: "",
count: 0, count: 0,
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
scheme_id: 0 scheme_id: 0,
}; };
this.paymentService.payMoney(pmcData, options, sessionID, output); this.paymentService.payMoney(pmcData, options, sessionID, output);
@ -145,9 +152,13 @@ export class RepairService
public addRepairSkillPoints( public addRepairSkillPoints(
sessionId: string, sessionId: string,
repairDetails: RepairDetails, repairDetails: RepairDetails,
pmcData: IPmcData): void pmcData: IPmcData,
): void
{ {
if (repairDetails.repairedByKit && this.itemHelper.isOfBaseclass(repairDetails.repairedItem._tpl, BaseClasses.WEAPON)) if (
repairDetails.repairedByKit &&
this.itemHelper.isOfBaseclass(repairDetails.repairedItem._tpl, BaseClasses.WEAPON)
)
{ {
const skillPoints = this.getWeaponRepairSkillPoints(repairDetails); const skillPoints = this.getWeaponRepairSkillPoints(repairDetails);
@ -155,22 +166,31 @@ export class RepairService
} }
// Handle kit repairs of armor // Handle kit repairs of armor
if (repairDetails.repairedByKit && this.itemHelper.isOfBaseclasses(repairDetails.repairedItem._tpl, [BaseClasses.ARMOR, BaseClasses.VEST])) if (
repairDetails.repairedByKit &&
this.itemHelper.isOfBaseclasses(repairDetails.repairedItem._tpl, [BaseClasses.ARMOR, BaseClasses.VEST])
)
{ {
const itemDetails = this.itemHelper.getItem(repairDetails.repairedItem._tpl); const itemDetails = this.itemHelper.getItem(repairDetails.repairedItem._tpl);
if (!itemDetails[0]) if (!itemDetails[0])
{ {
// No item found // No item found
this.logger.error(this.localisationService.getText("repair-unable_to_find_item_in_db", repairDetails.repairedItem._tpl)); this.logger.error(
this.localisationService.getText(
"repair-unable_to_find_item_in_db",
repairDetails.repairedItem._tpl,
),
);
return; return;
} }
const isHeavyArmor = itemDetails[1]._props.ArmorType === "Heavy"; const isHeavyArmor = itemDetails[1]._props.ArmorType === "Heavy";
const vestSkillToLevel = (isHeavyArmor) const vestSkillToLevel = isHeavyArmor ?
? SkillTypes.HEAVY_VESTS SkillTypes.HEAVY_VESTS :
: SkillTypes.LIGHT_VESTS; SkillTypes.LIGHT_VESTS;
const pointsToAddToVestSkill = repairDetails.repairPoints * this.repairConfig.armorKitSkillPointGainPerRepairPointMultiplier; const pointsToAddToVestSkill = repairDetails.repairPoints *
this.repairConfig.armorKitSkillPointGainPerRepairPointMultiplier;
this.profileHelper.addSkillPointsToPlayer(pmcData, vestSkillToLevel, pointsToAddToVestSkill); this.profileHelper.addSkillPointsToPlayer(pmcData, vestSkillToLevel, pointsToAddToVestSkill);
} }
@ -179,17 +199,24 @@ export class RepairService
let intellectGainedFromRepair: number; let intellectGainedFromRepair: number;
if (repairDetails.repairedByKit) if (repairDetails.repairedByKit)
{ {
const intRepairMultiplier = (this.itemHelper.isOfBaseclass(repairDetails.repairedItem._tpl, BaseClasses.WEAPON)) const intRepairMultiplier =
? this.repairConfig.repairKitIntellectGainMultiplier.weapon (this.itemHelper.isOfBaseclass(repairDetails.repairedItem._tpl, BaseClasses.WEAPON)) ?
: this.repairConfig.repairKitIntellectGainMultiplier.armor; this.repairConfig.repairKitIntellectGainMultiplier.weapon :
this.repairConfig.repairKitIntellectGainMultiplier.armor;
// limit gain to a max value defined in config.maxIntellectGainPerRepair // limit gain to a max value defined in config.maxIntellectGainPerRepair
intellectGainedFromRepair = Math.min(repairDetails.repairPoints * intRepairMultiplier, this.repairConfig.maxIntellectGainPerRepair.kit); intellectGainedFromRepair = Math.min(
repairDetails.repairPoints * intRepairMultiplier,
this.repairConfig.maxIntellectGainPerRepair.kit,
);
} }
else else
{ {
// Trader repair - Not as accurate as kit, needs data from live // Trader repair - Not as accurate as kit, needs data from live
intellectGainedFromRepair = Math.min(repairDetails.repairAmount / 10, this.repairConfig.maxIntellectGainPerRepair.trader); intellectGainedFromRepair = Math.min(
repairDetails.repairAmount / 10,
this.repairConfig.maxIntellectGainPerRepair.trader,
);
} }
this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.INTELLECT, intellectGainedFromRepair); this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.INTELLECT, intellectGainedFromRepair);
@ -201,7 +228,8 @@ export class RepairService
* @returns the number of skill points to reward the user * @returns the number of skill points to reward the user
*/ */
protected getWeaponRepairSkillPoints( protected getWeaponRepairSkillPoints(
repairDetails: RepairDetails): number repairDetails: RepairDetails,
): number
{ {
// This formula and associated configs is calculated based on 30 repairs done on live // This formula and associated configs is calculated based on 30 repairs done on live
// The points always came out 2-aligned, which is why there's a divide/multiply by 2 with ceil calls // The points always came out 2-aligned, which is why there's a divide/multiply by 2 with ceil calls
@ -233,7 +261,6 @@ export class RepairService
} }
/** /**
*
* @param sessionId Session id * @param sessionId Session id
* @param pmcData Profile to update repaired item in * @param pmcData Profile to update repaired item in
* @param repairKits Array of Repair kits to use * @param repairKits Array of Repair kits to use
@ -246,10 +273,11 @@ export class RepairService
pmcData: IPmcData, pmcData: IPmcData,
repairKits: RepairKitsInfo[], repairKits: RepairKitsInfo[],
itemToRepairId: string, itemToRepairId: string,
output: IItemEventRouterResponse): RepairDetails output: IItemEventRouterResponse,
): RepairDetails
{ {
// Find item to repair in inventory // Find item to repair in inventory
const itemToRepair = pmcData.Inventory.items.find((x: { _id: string; }) => x._id === itemToRepairId); const itemToRepair = pmcData.Inventory.items.find((x: {_id: string;}) => x._id === itemToRepairId);
if (itemToRepair === undefined) if (itemToRepair === undefined)
{ {
throw new Error(`Item ${itemToRepairId} not found, unable to repair`); throw new Error(`Item ${itemToRepairId} not found, unable to repair`);
@ -257,9 +285,12 @@ export class RepairService
const itemsDb = this.databaseServer.getTables().templates.items; const itemsDb = this.databaseServer.getTables().templates.items;
const itemToRepairDetails = itemsDb[itemToRepair._tpl]; const itemToRepairDetails = itemsDb[itemToRepair._tpl];
const repairItemIsArmor = (!!itemToRepairDetails._props.ArmorMaterial); const repairItemIsArmor = !!itemToRepairDetails._props.ArmorMaterial;
const repairAmount = repairKits[0].count / this.getKitDivisor(itemToRepairDetails, repairItemIsArmor, pmcData); const repairAmount = repairKits[0].count / this.getKitDivisor(itemToRepairDetails, repairItemIsArmor, pmcData);
const shouldApplyDurabilityLoss = this.shouldRepairKitApplyDurabilityLoss(pmcData, this.repairConfig.applyRandomizeDurabilityLoss); const shouldApplyDurabilityLoss = this.shouldRepairKitApplyDurabilityLoss(
pmcData,
this.repairConfig.applyRandomizeDurabilityLoss,
);
this.repairHelper.updateItemDurability( this.repairHelper.updateItemDurability(
itemToRepair, itemToRepair,
@ -268,12 +299,13 @@ export class RepairService
repairAmount, repairAmount,
true, true,
1, 1,
shouldApplyDurabilityLoss); shouldApplyDurabilityLoss,
);
// Find and use repair kit defined in body // Find and use repair kit defined in body
for (const repairKit of repairKits) 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 repairKitDetails = itemsDb[repairKitInInventory._tpl];
const repairKitReductionAmount = repairKit.count; const repairKitReductionAmount = repairKit.count;
@ -290,7 +322,7 @@ export class RepairService
repairedItem: itemToRepair, repairedItem: itemToRepair,
repairedItemIsArmor: repairItemIsArmor, repairedItemIsArmor: repairItemIsArmor,
repairAmount: repairAmount, repairAmount: repairAmount,
repairedByKit: true repairedByKit: true,
}; };
} }
@ -307,27 +339,28 @@ export class RepairService
const globalRepairSettings = globals.config.RepairSettings; const globalRepairSettings = globals.config.RepairSettings;
const intellectRepairPointsPerLevel = globals.config.SkillsSettings.Intellect.RepairPointsCostReduction; 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); const intellectPointReduction = intellectRepairPointsPerLevel * Math.trunc(profileIntellectLevel / 100);
if (isArmor) if (isArmor)
{ {
const durabilityPointCostArmor = globalRepairSettings.durabilityPointCostArmor; const durabilityPointCostArmor = globalRepairSettings.durabilityPointCostArmor;
const repairArmorBonus = this.getBonusMultiplierValue("RepairArmorBonus", pmcData); const repairArmorBonus = this.getBonusMultiplierValue("RepairArmorBonus", pmcData);
const armorBonus = (1.0 - (repairArmorBonus - 1.0) - intellectPointReduction); const armorBonus = 1.0 - (repairArmorBonus - 1.0) - intellectPointReduction;
const materialType = itemToRepairDetails._props.ArmorMaterial ?? ""; const materialType = itemToRepairDetails._props.ArmorMaterial ?? "";
const armorMaterial = globals.config.ArmorMaterials[materialType] as IArmorType; const armorMaterial = globals.config.ArmorMaterials[materialType] as IArmorType;
const destructability = (1 + armorMaterial.Destructibility); const destructability = 1 + armorMaterial.Destructibility;
const armorClass = parseInt(`${itemToRepairDetails._props.armorClass}`); const armorClass = parseInt(`${itemToRepairDetails._props.armorClass}`);
const armorClassDivisor = globals.config.RepairSettings.armorClassDivisor; const armorClassDivisor = globals.config.RepairSettings.armorClassDivisor;
const armorClassMultiplier = (1.0 + armorClass / armorClassDivisor); const armorClassMultiplier = 1.0 + armorClass / armorClassDivisor;
return durabilityPointCostArmor * armorBonus * destructability * armorClassMultiplier; return durabilityPointCostArmor * armorBonus * destructability * armorClassMultiplier;
} }
else else
{ {
const repairWeaponBonus = this.getBonusMultiplierValue("RepairWeaponBonus", pmcData) - 1; const repairWeaponBonus = this.getBonusMultiplierValue("RepairWeaponBonus", pmcData) - 1;
const repairPointMultiplier = (1.0 - repairWeaponBonus - intellectPointReduction); const repairPointMultiplier = 1.0 - repairWeaponBonus - intellectPointReduction;
const durabilityPointCostGuns = globals.config.RepairSettings.durabilityPointCostGuns; const durabilityPointCostGuns = globals.config.RepairSettings.durabilityPointCostGuns;
return durabilityPointCostGuns * repairPointMultiplier; return durabilityPointCostGuns * repairPointMultiplier;
@ -342,11 +375,11 @@ export class RepairService
*/ */
protected getBonusMultiplierValue(skillBonusName: string, pmcData: IPmcData): number protected getBonusMultiplierValue(skillBonusName: string, pmcData: IPmcData): number
{ {
const bonusesMatched = pmcData?.Bonuses?.filter(b => b.type === skillBonusName); const bonusesMatched = pmcData?.Bonuses?.filter((b) => b.type === skillBonusName);
let value = 1; let value = 1;
if (bonusesMatched != null) 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; value = 1 + sumedPercentage / 100;
} }
@ -389,14 +422,14 @@ export class RepairService
this.logger.debug(`Repair kit: ${repairKitInInventory._id} in inventory lacks upd object, adding`); this.logger.debug(`Repair kit: ${repairKitInInventory._id} in inventory lacks upd object, adding`);
repairKitInInventory.upd = { repairKitInInventory.upd = {
RepairKit: { RepairKit: {
Resource: maxRepairAmount Resource: maxRepairAmount,
} },
}; };
} }
if (!repairKitInInventory.upd.RepairKit?.Resource) if (!repairKitInInventory.upd.RepairKit?.Resource)
{ {
repairKitInInventory.upd.RepairKit = { repairKitInInventory.upd.RepairKit = {
Resource: maxRepairAmount Resource: maxRepairAmount,
}; };
} }
} }
@ -450,7 +483,10 @@ export class RepairService
rarity: bonusRarity, rarity: bonusRarity,
buffType: bonusType, buffType: bonusType,
value: bonusValue, value: bonusValue,
thresholdDurability: this.randomUtil.getPercentOfValue(bonusThresholdPercent, item.upd.Repairable.Durability) thresholdDurability: this.randomUtil.getPercentOfValue(
bonusThresholdPercent,
item.upd.Repairable.Durability,
),
}; };
} }
@ -467,7 +503,9 @@ export class RepairService
const hasTemplate = this.itemHelper.getItem(repairDetails.repairedItem._tpl); const hasTemplate = this.itemHelper.getItem(repairDetails.repairedItem._tpl);
if (!hasTemplate[0]) if (!hasTemplate[0])
{
return false; return false;
}
const template = hasTemplate[1]; const template = hasTemplate[1];
const itemSkillType = this.getItemSkillType(template); const itemSkillType = this.getItemSkillType(template);
@ -476,14 +514,22 @@ export class RepairService
return false; return false;
} }
const commonBuffMinChanceValue = globals.config.SkillsSettings[itemSkillType as string].BuffSettings.CommonBuffMinChanceValue; const commonBuffMinChanceValue =
const commonBuffChanceLevelBonus = globals.config.SkillsSettings[itemSkillType as string].BuffSettings.CommonBuffChanceLevelBonus; globals.config.SkillsSettings[itemSkillType as string].BuffSettings.CommonBuffMinChanceValue;
const receivedDurabilityMaxPercent = globals.config.SkillsSettings[itemSkillType as string].BuffSettings.ReceivedDurabilityMaxPercent; const commonBuffChanceLevelBonus =
globals.config.SkillsSettings[itemSkillType as string].BuffSettings.CommonBuffChanceLevelBonus;
const receivedDurabilityMaxPercent =
globals.config.SkillsSettings[itemSkillType as string].BuffSettings.ReceivedDurabilityMaxPercent;
const skillLevel = Math.trunc((this.profileHelper.getSkillFromProfile(pmcData, itemSkillType)?.Progress ?? 0) / 100); const skillLevel = Math.trunc(
(this.profileHelper.getSkillFromProfile(pmcData, itemSkillType)?.Progress ?? 0) / 100,
);
const durabilityToRestorePercent = repairDetails.repairPoints / template._props.MaxDurability; const durabilityToRestorePercent = repairDetails.repairPoints / template._props.MaxDurability;
const durabilityMultiplier = this.getDurabilityMultiplier(receivedDurabilityMaxPercent, durabilityToRestorePercent); const durabilityMultiplier = this.getDurabilityMultiplier(
receivedDurabilityMaxPercent,
durabilityToRestorePercent,
);
const doBuff = commonBuffMinChanceValue + commonBuffChanceLevelBonus * skillLevel * durabilityMultiplier; const doBuff = commonBuffMinChanceValue + commonBuffChanceLevelBonus * skillLevel * durabilityMultiplier;
@ -533,7 +579,7 @@ export class RepairService
*/ */
protected getDurabilityMultiplier(receiveDurabilityMaxPercent: number, receiveDurabilityPercent: number): number protected getDurabilityMultiplier(receiveDurabilityMaxPercent: number, receiveDurabilityPercent: number): number
{ {
receiveDurabilityMaxPercent = ((receiveDurabilityMaxPercent > 0) ? receiveDurabilityMaxPercent : 0.01); receiveDurabilityMaxPercent = (receiveDurabilityMaxPercent > 0) ? receiveDurabilityMaxPercent : 0.01;
const num = receiveDurabilityPercent / receiveDurabilityMaxPercent; const num = receiveDurabilityPercent / receiveDurabilityMaxPercent;
if (num > 1) if (num > 1)
{ {

View File

@ -36,7 +36,7 @@ export class SeasonalEventService
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("BotHelper") protected botHelper: BotHelper, @inject("BotHelper") protected botHelper: BotHelper,
@inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("ProfileHelper") protected profileHelper: ProfileHelper,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.seasonalEventConfig = this.configServer.getConfig(ConfigTypes.SEASONAL_EVENT); this.seasonalEventConfig = this.configServer.getConfig(ConfigTypes.SEASONAL_EVENT);
@ -54,7 +54,7 @@ export class SeasonalEventService
"5df8a77486f77412672a1e3f", // Violet bauble "5df8a77486f77412672a1e3f", // Violet bauble
"5df8a72c86f77412640e2e83", // Silver bauble "5df8a72c86f77412640e2e83", // Silver bauble
"5a43943586f77416ad2f06e2", // Ded moroz hat "5a43943586f77416ad2f06e2", // Ded moroz hat
"5a43957686f7742a2c2f11b0" // Santa hat "5a43957686f7742a2c2f11b0", // Santa hat
]; ];
} }
@ -71,7 +71,7 @@ export class SeasonalEventService
"6176a40f0b8c0312ac75a3d3", // Ghoul mask "6176a40f0b8c0312ac75a3d3", // Ghoul mask
"62a5c2c98ec41a51b34739c0", // Hockey player mask "Captain" "62a5c2c98ec41a51b34739c0", // Hockey player mask "Captain"
"62a5c333ec21e50cad3b5dc6", // Hockey player mask "Brawler" "62a5c333ec21e50cad3b5dc6", // Hockey player mask "Brawler"
"62a5c41e8ec41a51b34739c3" // Hockey player mask "Quiet" "62a5c41e8ec41a51b34739c3", // Hockey player mask "Quiet"
]; ];
} }
@ -236,11 +236,13 @@ export class SeasonalEventService
const eventEndDate = new Date(currentDate.getFullYear(), event.endMonth - 1, event.endDay); const eventEndDate = new Date(currentDate.getFullYear(), event.endMonth - 1, event.endDay);
// Current date is between start/end dates // Current date is between start/end dates
if (currentDate >= eventStartDate if (
&& currentDate <= eventEndDate) currentDate >= eventStartDate &&
currentDate <= eventEndDate
)
{ {
this.christmasEventActive = (SeasonalEventType[event.type] === SeasonalEventType.CHRISTMAS); this.christmasEventActive = SeasonalEventType[event.type] === SeasonalEventType.CHRISTMAS;
this.halloweenEventActive = (SeasonalEventType[event.type] === SeasonalEventType.HALLOWEEN); this.halloweenEventActive = SeasonalEventType[event.type] === SeasonalEventType.HALLOWEEN;
} }
} }
} }
@ -261,12 +263,18 @@ export class SeasonalEventService
{ {
if (!botInventory.equipment[equipmentSlotKey]) if (!botInventory.equipment[equipmentSlotKey])
{ {
this.logger.warning(this.localisationService.getText("seasonal-missing_equipment_slot_on_bot", {equipmentSlot: equipmentSlotKey, botRole: botRole})); this.logger.warning(
this.localisationService.getText("seasonal-missing_equipment_slot_on_bot", {
equipmentSlot: equipmentSlotKey,
botRole: botRole,
}),
);
} }
const equipment: Record<string, number> = botInventory.equipment[equipmentSlotKey]; const equipment: Record<string, number> = botInventory.equipment[equipmentSlotKey];
// eslint-disable-next-line @typescript-eslint/no-unused-vars botInventory.equipment[equipmentSlotKey] = Object.fromEntries(
botInventory.equipment[equipmentSlotKey] = Object.fromEntries(Object.entries(equipment).filter(([index]) => !christmasItems.includes(index))); Object.entries(equipment).filter(([index]) => !christmasItems.includes(index)),
);
} }
// Remove christmas related loot from loot containers // Remove christmas related loot from loot containers
@ -274,10 +282,17 @@ export class SeasonalEventService
{ {
if (!botInventory.items[lootContainerKey]) if (!botInventory.items[lootContainerKey])
{ {
this.logger.warning(this.localisationService.getText("seasonal-missing_loot_container_slot_on_bot", {lootContainer: lootContainerKey, botRole: botRole})); this.logger.warning(
this.localisationService.getText("seasonal-missing_loot_container_slot_on_bot", {
lootContainer: lootContainerKey,
botRole: botRole,
}),
);
} }
botInventory.items[lootContainerKey] = botInventory.items[lootContainerKey].filter((x: string) => !christmasItems.includes(x)); botInventory.items[lootContainerKey] = botInventory.items[lootContainerKey].filter((x: string) =>
!christmasItems.includes(x)
);
} }
} }
@ -292,7 +307,7 @@ export class SeasonalEventService
switch (eventType.toLowerCase()) switch (eventType.toLowerCase())
{ {
case SeasonalEventType.HALLOWEEN.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("Halloween");
globalConfig.EventType.push("HalloweenIllumination"); globalConfig.EventType.push("HalloweenIllumination");
globalConfig.Health.ProfileHealthSettings.DefaultStimulatorBuff = "Buffs_Halloween"; globalConfig.Health.ProfileHealthSettings.DefaultStimulatorBuff = "Buffs_Halloween";
@ -304,7 +319,7 @@ export class SeasonalEventService
this.adjustTraderIcons(eventType); this.adjustTraderIcons(eventType);
break; break;
case SeasonalEventType.CHRISTMAS.toLowerCase(): case SeasonalEventType.CHRISTMAS.toLowerCase():
globalConfig.EventType = globalConfig.EventType.filter(x => x !== "None"); globalConfig.EventType = globalConfig.EventType.filter((x) => x !== "None");
globalConfig.EventType.push("Christmas"); globalConfig.EventType.push("Christmas");
this.addEventGearToBots(eventType); this.addEventGearToBots(eventType);
this.addGifterBotToMaps(); this.addGifterBotToMaps();
@ -352,10 +367,10 @@ export class SeasonalEventService
} }
for (const boss of bossesToAdd) for (const boss of bossesToAdd)
{ {
const mapBosses: BossLocationSpawn[] = this.databaseServer.getTables().locations[mapKey].base.BossLocationSpawn; const mapBosses: BossLocationSpawn[] =
if (!mapBosses.find(x => x.BossName === boss.BossName)) this.databaseServer.getTables().locations[mapKey].base.BossLocationSpawn;
if (!mapBosses.find((x) => x.BossName === boss.BossName))
{ {
this.databaseServer.getTables().locations[mapKey].base.BossLocationSpawn.push(...bossesToAdd); this.databaseServer.getTables().locations[mapKey].base.BossLocationSpawn.push(...bossesToAdd);
} }
} }
@ -371,21 +386,31 @@ export class SeasonalEventService
switch (eventType.toLowerCase()) switch (eventType.toLowerCase())
{ {
case SeasonalEventType.HALLOWEEN.toLowerCase(): case SeasonalEventType.HALLOWEEN.toLowerCase():
this.httpConfig.serverImagePathOverride["./assets/images/traders/5a7c2ebb86f7746e324a06ab.png"] = "./assets/images/traders/halloween/5a7c2ebb86f7746e324a06ab.png"; this.httpConfig.serverImagePathOverride["./assets/images/traders/5a7c2ebb86f7746e324a06ab.png"] =
this.httpConfig.serverImagePathOverride["./assets/images/traders/5ac3b86a86f77461491d1ad8.png"] = "./assets/images/traders/halloween/5ac3b86a86f77461491d1ad8.png"; "./assets/images/traders/halloween/5a7c2ebb86f7746e324a06ab.png";
this.httpConfig.serverImagePathOverride["./assets/images/traders/5c06531a86f7746319710e1b.png"] = "./assets/images/traders/halloween/5c06531a86f7746319710e1b.png"; this.httpConfig.serverImagePathOverride["./assets/images/traders/5ac3b86a86f77461491d1ad8.png"] =
this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91ca086f77469a81232e4.png"] = "./assets/images/traders/halloween/59b91ca086f77469a81232e4.png"; "./assets/images/traders/halloween/5ac3b86a86f77461491d1ad8.png";
this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91cab86f77469aa5343ca.png"] = "./assets/images/traders/halloween/59b91cab86f77469aa5343ca.png"; this.httpConfig.serverImagePathOverride["./assets/images/traders/5c06531a86f7746319710e1b.png"] =
this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91cb486f77469a81232e5.png"] = "./assets/images/traders/halloween/59b91cb486f77469a81232e5.png"; "./assets/images/traders/halloween/5c06531a86f7746319710e1b.png";
this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91cbd86f77469aa5343cb.png"] = "./assets/images/traders/halloween/59b91cbd86f77469aa5343cb.png"; this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91ca086f77469a81232e4.png"] =
this.httpConfig.serverImagePathOverride["./assets/images/traders/579dc571d53a0658a154fbec.png"] = "./assets/images/traders/halloween/579dc571d53a0658a154fbec.png"; "./assets/images/traders/halloween/59b91ca086f77469a81232e4.png";
this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91cab86f77469aa5343ca.png"] =
"./assets/images/traders/halloween/59b91cab86f77469aa5343ca.png";
this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91cb486f77469a81232e5.png"] =
"./assets/images/traders/halloween/59b91cb486f77469a81232e5.png";
this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91cbd86f77469aa5343cb.png"] =
"./assets/images/traders/halloween/59b91cbd86f77469aa5343cb.png";
this.httpConfig.serverImagePathOverride["./assets/images/traders/579dc571d53a0658a154fbec.png"] =
"./assets/images/traders/halloween/579dc571d53a0658a154fbec.png";
break; break;
case SeasonalEventType.CHRISTMAS.toLowerCase(): case SeasonalEventType.CHRISTMAS.toLowerCase():
// TODO: find christmas trader icons // TODO: find christmas trader icons
break; break;
} }
this.databaseImporter.loadImages(`${this.databaseImporter.getSptDataPath()}images/`, ["traders"], ["/files/trader/avatar/"]); this.databaseImporter.loadImages(`${this.databaseImporter.getSptDataPath()}images/`, ["traders"], [
"/files/trader/avatar/",
]);
} }
/** /**
@ -429,7 +454,10 @@ export class SeasonalEventService
for (const equipmentSlot in gearAmendments) for (const equipmentSlot in gearAmendments)
{ {
// Adjust slots spawn chance to be at least 75% // Adjust slots spawn chance to be at least 75%
botToUpdate.chances.equipment[equipmentSlot] = Math.max(botToUpdate.chances.equipment[equipmentSlot], 75); botToUpdate.chances.equipment[equipmentSlot] = Math.max(
botToUpdate.chances.equipment[equipmentSlot],
75,
);
// Grab gear to add and loop over it // Grab gear to add and loop over it
const itemsToAdd = gearAmendments[equipmentSlot]; const itemsToAdd = gearAmendments[equipmentSlot];
@ -496,7 +524,7 @@ export class SeasonalEventService
TriggerId: "", TriggerId: "",
TriggerName: "", TriggerName: "",
Delay: 0, Delay: 0,
RandomTimeSpawn: false RandomTimeSpawn: false,
}); });
} }
} }
@ -512,7 +540,6 @@ export class SeasonalEventService
{ {
this.giftService.sendGiftToPlayer(playerId, giftkey); this.giftService.sendGiftToPlayer(playerId, giftkey);
} }
} }
/** /**

View File

@ -22,7 +22,7 @@ export class TraderPurchasePersisterService
@inject("TimeUtil") protected timeUtil: TimeUtil, @inject("TimeUtil") protected timeUtil: TimeUtil,
@inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("ProfileHelper") protected profileHelper: ProfileHelper,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("ConfigServer") protected configServer: ConfigServer @inject("ConfigServer") protected configServer: ConfigServer,
) )
{ {
this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER); this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER);
@ -95,20 +95,27 @@ export class TraderPurchasePersisterService
for (const purchaseKey in profile.traderPurchases[traderId]) 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) if (!traderUpdateDetails)
{ {
this.logger.error(this.localisationService.getText("trader-unable_to_delete_stale_purchases", {profileId: profile.info.id, traderId: traderId})); this.logger.error(
this.localisationService.getText("trader-unable_to_delete_stale_purchases", {
profileId: profile.info.id,
traderId: traderId,
}),
);
continue; continue;
} }
const purchaseDetails = profile.traderPurchases[traderId][purchaseKey]; const purchaseDetails = profile.traderPurchases[traderId][purchaseKey];
const resetTimeForItem = purchaseDetails.purchaseTimestamp + traderUpdateDetails.seconds; const resetTimeForItem = purchaseDetails.purchaseTimestamp + traderUpdateDetails.seconds;
if ((resetTimeForItem) < this.timeUtil.getTimestamp()) if (resetTimeForItem < this.timeUtil.getTimestamp())
{ {
// Item was purchased far enough in past a trader refresh would have occured, remove purchase record from profile // Item was purchased far enough in past a trader refresh would have occured, remove purchase record from profile
this.logger.debug(`Removed trader: ${traderId} purchase: ${purchaseKey} from profile: ${profile.info.id}`); this.logger.debug(
`Removed trader: ${traderId} purchase: ${purchaseKey} from profile: ${profile.info.id}`,
);
delete profile.traderPurchases[traderId][purchaseKey]; delete profile.traderPurchases[traderId][purchaseKey];
} }
} }

View File

@ -1,7 +1,12 @@
import { inject, injectable } from "tsyringe"; import { inject, injectable } from "tsyringe";
import { ITemplateItem, Props } from "@spt-aki/models/eft/common/tables/ITemplateItem"; import { ITemplateItem, Props } from "@spt-aki/models/eft/common/tables/ITemplateItem";
import { CreateItemResult, LocaleDetails, NewItemDetails, NewItemFromCloneDetails } from "@spt-aki/models/spt/mod/NewItemDetails"; import {
CreateItemResult,
LocaleDetails,
NewItemDetails,
NewItemFromCloneDetails,
} from "@spt-aki/models/spt/mod/NewItemDetails";
import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables"; import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
@ -17,7 +22,7 @@ export class CustomItemService
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("HashUtil") protected hashUtil: HashUtil, @inject("HashUtil") protected hashUtil: HashUtil,
@inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("JsonUtil") protected jsonUtil: JsonUtil,
@inject("DatabaseServer") protected databaseServer: DatabaseServer @inject("DatabaseServer") protected databaseServer: DatabaseServer,
) )
{ {
this.tables = this.databaseServer.getTables(); this.tables = this.databaseServer.getTables();
@ -115,9 +120,9 @@ export class CustomItemService
*/ */
protected getOrGenerateIdForItem(newId: string): string protected getOrGenerateIdForItem(newId: string): string
{ {
return (newId === "") return (newId === "") ?
? this.hashUtil.generate() this.hashUtil.generate() :
: newId; newId;
} }
/** /**
@ -156,8 +161,8 @@ export class CustomItemService
{ {
Id: newItemId, Id: newItemId,
ParentId: parentId, ParentId: parentId,
Price: priceRoubles Price: priceRoubles,
} },
); );
} }

View File

@ -4,7 +4,7 @@ export class DynamicRouterMod extends DynamicRouter
{ {
public constructor( public constructor(
routes: RouteAction[], routes: RouteAction[],
private topLevelRoute: string private topLevelRoute: string,
) )
{ {
super(routes); super(routes);

View File

@ -11,7 +11,7 @@ export class DynamicRouterModService
public registerDynamicRouter( public registerDynamicRouter(
name: string, name: string,
routes: RouteAction[], routes: RouteAction[],
topLevelRoute: string topLevelRoute: string,
): void ): void
{ {
this.container.register(name, {useValue: new DynamicRouterMod(routes, topLevelRoute)}); this.container.register(name, {useValue: new DynamicRouterMod(routes, topLevelRoute)});

View File

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

View File

@ -13,10 +13,12 @@ export class HttpListenerModService
public registerHttpListener( public registerHttpListener(
name: string, name: string,
canHandleOverride: (sessionId: string, req: IncomingMessage) => boolean, canHandleOverride: (sessionId: string, req: IncomingMessage) => boolean,
handleOverride: (sessionId: string, req: IncomingMessage, resp: ServerResponse) => void handleOverride: (sessionId: string, req: IncomingMessage, resp: ServerResponse) => void,
): void ): void
{ {
this.container.register<IHttpListener>(name, {useValue: new HttpListenerMod(canHandleOverride, handleOverride)}); this.container.register<IHttpListener>(name, {
useValue: new HttpListenerMod(canHandleOverride, handleOverride),
});
this.container.registerType("HttpListener", name); this.container.registerType("HttpListener", name);
} }
} }

View File

@ -4,10 +4,10 @@ export class OnLoadMod implements OnLoad
{ {
public constructor( public constructor(
private onLoadOverride: () => void, private onLoadOverride: () => void,
private getRouteOverride: () => string private getRouteOverride: () => string,
) )
{ {
//super(); // super();
} }
public async onLoad(): Promise<void> public async onLoad(): Promise<void>

View File

@ -11,7 +11,7 @@ export class OnLoadModService
public registerOnLoad( public registerOnLoad(
name: string, name: string,
onLoad: () => void, onLoad: () => void,
getRoute: () => string getRoute: () => string,
): void ): void
{ {
this.container.register(name, {useValue: new OnLoadMod(onLoad, getRoute)}); this.container.register(name, {useValue: new OnLoadMod(onLoad, getRoute)});

View File

@ -3,8 +3,8 @@ import { OnUpdate } from "@spt-aki/di/OnUpdate";
export class OnUpdateMod implements OnUpdate export class OnUpdateMod implements OnUpdate
{ {
public constructor( public constructor(
private onUpdateOverride: ( timeSinceLastRun: number ) => boolean, private onUpdateOverride: (timeSinceLastRun: number) => boolean,
private getRouteOverride: () => string private getRouteOverride: () => string,
) )
{ {
} }

View File

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

View File

@ -4,7 +4,7 @@ export class StaticRouterMod extends StaticRouter
{ {
public constructor( public constructor(
routes: RouteAction[], routes: RouteAction[],
private topLevelRoute: string private topLevelRoute: string,
) )
{ {
super(routes); super(routes);

View File

@ -11,7 +11,7 @@ export class StaticRouterModService
public registerStaticRouter( public registerStaticRouter(
name: string, name: string,
routes: RouteAction[], routes: RouteAction[],
topLevelRoute: string topLevelRoute: string,
): void ): void
{ {
this.container.register(name, {useValue: new StaticRouterMod(routes, topLevelRoute)}); this.container.register(name, {useValue: new StaticRouterMod(routes, topLevelRoute)});