Formatting for services.
This commit is contained in:
parent
ca9ab9bcc8
commit
8576929404
@ -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}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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
|
||||||
|
@ -17,7 +17,7 @@ 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,
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -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),
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
@ -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,13 +542,16 @@ 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++)
|
||||||
{
|
{
|
||||||
@ -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;
|
||||||
@ -719,7 +759,7 @@ export class FenceService
|
|||||||
|
|
||||||
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;
|
||||||
|
@ -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
|
||||||
@ -133,7 +136,7 @@ export class GiftService
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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}`));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,7 +15,7 @@ export class ItemFilterService
|
|||||||
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);
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -33,7 +33,7 @@ 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,
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -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}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ export class MatchLocationService
|
|||||||
protected locations = {};
|
protected locations = {};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@inject("TimeUtil") protected timeUtil: TimeUtil
|
@inject("TimeUtil") protected timeUtil: TimeUtil,
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -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];
|
||||||
|
@ -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");
|
||||||
@ -61,8 +61,7 @@ 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,
|
||||||
@ -75,7 +74,7 @@ export class ModCompilerService
|
|||||||
downlevelIteration: true,
|
downlevelIteration: true,
|
||||||
experimentalDecorators: true,
|
experimentalDecorators: true,
|
||||||
emitDecoratorMetadata: true,
|
emitDecoratorMetadata: true,
|
||||||
rootDir: modPath
|
rootDir: modPath,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +113,10 @@ export class ModCompilerService
|
|||||||
|
|
||||||
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;
|
||||||
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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);
|
||||||
|
@ -28,7 +28,7 @@ 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,
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -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);
|
||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -9,12 +9,11 @@ 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,
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -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),
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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)
|
||||||
@ -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;
|
||||||
@ -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)
|
||||||
{
|
{
|
||||||
@ -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`);
|
||||||
@ -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
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ 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,
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -58,9 +58,9 @@ export class RagfairCategoriesService
|
|||||||
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
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ 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,
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
@ -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],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,7 +12,7 @@ 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,
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -50,5 +50,4 @@ export class RagfairRequiredItemsService
|
|||||||
|
|
||||||
this.requiredItemsCache = requiredItems;
|
this.requiredItemsCache = requiredItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -18,7 +18,7 @@ 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,
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -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;
|
||||||
|
@ -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,7 +273,8 @@ 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);
|
||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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)});
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ export class OnLoadMod implements OnLoad
|
|||||||
{
|
{
|
||||||
public constructor(
|
public constructor(
|
||||||
private onLoadOverride: () => void,
|
private onLoadOverride: () => void,
|
||||||
private getRouteOverride: () => string
|
private getRouteOverride: () => string,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// super();
|
// super();
|
||||||
|
@ -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)});
|
||||||
|
@ -4,7 +4,7 @@ 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,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -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)});
|
||||||
|
@ -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);
|
||||||
|
@ -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)});
|
||||||
|
Loading…
Reference in New Issue
Block a user