import { ICustomizationItem } from "@spt/models/eft/common/tables/ICustomizationItem"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; import { ISuit } from "@spt/models/eft/common/tables/ITrader"; import { IEquipmentFilterDetails, EquipmentFilters, IBotConfig, IRandomisationDetails, IWeightingAdjustmentDetails, } from "@spt/models/spt/config/IBotConfig"; import advancedConfig from "../../config/advancedConfig.json"; import config, { levelRange } from "../../config/config.json"; import { MinMax } from "../../types/models/common/MinMax"; import { IAppearance, IInventory, IMods, } from "../../types/models/eft/common/tables/IBotType"; import InternalBlacklist from "./InternalBlacklist"; import mappedPresets from "../Constants/mappedPresets.json"; export const saveToFile = (data, filePath) => { var fs = require("fs"); let dir = __dirname; let dirArray = dir.split("\\"); const directory = `${dirArray[dirArray.length - 5]}/${ dirArray[dirArray.length - 4] }/${dirArray[dirArray.length - 3]}/${dirArray[dirArray.length - 2]}/`; fs.writeFile( directory + filePath, JSON.stringify(data, null, 4), function (err) { if (err) throw err; } ); }; export const headwearParent = "5a341c4086f77401f2541505"; export const AmmoParent = "5485a8684bdc2da71d8b4567"; export const magParent = "5448bc234bdc2d3c308b4569"; export const barterParent = "5448eb774bdc2d0a728b4567"; export const keyMechanical = "5c99f98d86f7745c314214b3"; export const stimParent = "5448f3a64bdc2d60728b456a"; export const painKillerParent = "5448f3a14bdc2d27728b4569"; export const medicalParent = "5448f3ac4bdc2dce718b4569"; export const medKitParent = "5448f39d4bdc2d0a728b4568"; export const FoodDrinkParent = "543be6674bdc2df1348b4569"; export const medsParent = "543be5664bdc2dd4348b4569"; export const modParent = "5448fe124bdc2da5018b4567"; export const masterMod = "55802f4a4bdc2ddb688b4569"; export const moneyParent = "543be5dd4bdc2deb348b4569"; export const sightParent = "5448fe7a4bdc2d6f028b456b"; export const stockParent = "55818a594bdc2db9688b456a"; export const pistolGripParent = "55818a684bdc2ddd698b456d"; export const muzzleParent = "5448fe394bdc2d0d028b456c"; export const receiverParent = "55818a304bdc2db5418b457d"; export const gasblockParent = "56ea9461d2720b67698b456f"; export const barrelParent = "555ef6e44bdc2de9068b457e"; export const handguardParent = "55818a104bdc2db9688b4569"; export const chargeParent = "55818a104bdc2db9688b4569"; export const mountParent = "55818b224bdc2dde698b456f"; export const weaponParent = "5422acb9af1c889c16000029"; export const armorParent = "57bef4c42459772e8d35a53b"; export const rigParent = "5448e5284bdc2dcb718b4567"; export const armorPlateParent = "644120aa86ffbe10ee032b6f"; export enum SightType { AssaultScope = "55818add4bdc2d5b648b456f", Collimator = "55818ad54bdc2ddc698b4569", CompactCollimator = "55818acf4bdc2dde698b456b", OpticScope = "55818ae44bdc2dde698b456c", SpecialScope = "55818aeb4bdc2ddc698b456a", ThermalVision = "5d21f59b6dbe99052b54ef83", NightVision = "5a2c3a9486f774688b05e574", } export const weaponTypeNameToId = { SniperRifle: "5447b6254bdc2dc3278b4568", MarksmanRifle: "5447b6194bdc2d67278b4567", AssaultCarbine: "5447b5fc4bdc2d87278b4567", AssaultRifle: "5447b5f14bdc2d61278b4567", MachineGun: "5447bed64bdc2d97278b4568", Smg: "5447b5e04bdc2d62278b4567", SpecialWeapon: "5447bee84bdc2dc3278b4569", Shotgun: "5447b6094bdc2dc3278b4567", Pistol: "5447b5cf4bdc2d65278b4567", Revolver: "617f1ef5e8b54b0998387733", GrenadeLauncher: "5447bedf4bdc2d87278b4568", }; export const addToModsObject = ( mods: { "1": {}; "2": {}; "3": {}; "4": {} }, _tpl: string, items: Record, loyaltyLevel: number, slotId: string = "" ) => { switch (true) { case checkParentRecursive(_tpl, items, [magParent]): if (!mods[loyaltyLevel]?.["mod_magazine"]) mods[loyaltyLevel]["mod_magazine"] = []; mods[loyaltyLevel]["mod_magazine"].push(_tpl); break; case slotId !== "hideout": if (!mods[loyaltyLevel]?.[slotId]) mods[loyaltyLevel][slotId] = []; mods[loyaltyLevel][slotId].push(_tpl); break; // case checkParentRecursive(_tpl, items, Object.values(SightType)): // if (!mods[loyaltyLevel]?.["mod_scope"]) mods[loyaltyLevel]["mod_scope"] = [] // mods[loyaltyLevel]["mod_scope"].push(_tpl) // break; // case checkParentRecursive(_tpl, items, [pistolGripParent]): // if (!mods[loyaltyLevel]?.["mod_pistol_grip"]) mods[loyaltyLevel]["mod_pistol_grip"] = [] // mods[loyaltyLevel]["mod_pistol_grip"].push(_tpl) // break; // case checkParentRecursive(_tpl, items, [stockParent]): // if (!mods[loyaltyLevel]?.["mod_stock"]) mods[loyaltyLevel]["mod_stock"] = [] // mods[loyaltyLevel]["mod_stock"].push(_tpl) // break; // case checkParentRecursive(_tpl, items, [muzzleParent]): // if (!mods[loyaltyLevel]?.["mod_muzzle"]) mods[loyaltyLevel]["mod_muzzle"] = [] // mods[loyaltyLevel]["mod_muzzle"].push(_tpl) // break; // case checkParentRecursive(_tpl, items, [receiverParent]): // if (!mods[loyaltyLevel]?.["mod_reciever"]) mods[loyaltyLevel]["mod_reciever"] = [] // mods[loyaltyLevel]["mod_reciever"].push(_tpl) // break; // case checkParentRecursive(_tpl, items, [gasblockParent]): // if (!mods[loyaltyLevel]?.["mod_gas_block"]) mods[loyaltyLevel]["mod_gas_block"] = [] // mods[loyaltyLevel]["mod_gas_block"].push(_tpl) // break; // case checkParentRecursive(_tpl, items, [barrelParent]): // if (!mods[loyaltyLevel]?.["mod_barrel"]) mods[loyaltyLevel]["mod_barrel"] = [] // mods[loyaltyLevel]["mod_barrel"].push(_tpl) // break; // case checkParentRecursive(_tpl, items, [handguardParent]): // if (!mods[loyaltyLevel]?.["mod_handguard"]) mods[loyaltyLevel]["mod_handguard"] = [] // mods[loyaltyLevel]["mod_handguard"].push(_tpl) // break; // case checkParentRecursive(_tpl, items, [chargeParent]): // if (!mods[loyaltyLevel]?.["mod_charge"]) mods[loyaltyLevel]["mod_charge"] = [] // mods[loyaltyLevel]["mod_charge"].push(_tpl) // break; // case checkParentRecursive(_tpl, items, [mountParent]): // if (!mods[loyaltyLevel]?.["mod_mount"]) mods[loyaltyLevel]["mod_mount"] = [] // mods[loyaltyLevel]["mod_mount"].push(_tpl) // break; default: break; } }; export const addKeysToPockets = ( traderItems: Set, items: Record, inventory: IInventory ) => { traderItems.forEach((id) => { if ( id && items[id]?._parent && checkParentRecursive(id, items, [keyMechanical]) ) { inventory.items.Pockets[id] = 1; inventory.items.Backpack[id] = 1; inventory.items.TacticalVest[id] = 1; } }); // inventory.items.Pockets = deDupeArr(inventory.items.Pockets); // inventory.items.Backpack = deDupeArr(inventory.items.Backpack); // inventory.items.TacticalVest = deDupeArr(inventory.items.TacticalVest); }; export const setupMods = (mods: Record>) => { Object.keys(mods).forEach((numstr) => { const num = Number(numstr); Object.keys(mods[num]).forEach((mod) => { mods[num][mod] = deDupeArr(mods[num][mod]); if (mods[num + 1]) { if (!mods[num + 1]?.[mod]) mods[num + 1][mod] = mods[num][mod]; else { mods[num + 1][mod].push(...mods[num][mod]); } } }); }); }; export const reduceEquipmentChancesTo1 = (inventory: IInventory) => { Object.keys(inventory.equipment).forEach((equipType) => { Object.keys(inventory.equipment[equipType]).forEach((id) => { if (inventory.equipment[equipType][id] !== 0) { inventory.equipment[equipType][id] = 1; } }); }); }; export const reduceAmmoChancesTo1 = (inventory: IInventory) => { Object.keys(inventory.Ammo).forEach((caliber) => { Object.keys(inventory.Ammo[caliber]).forEach((id) => { if (inventory.Ammo[caliber][id] !== 0) { inventory.Ammo[caliber][id] = 1; } }); }); }; export const deDupeArr = (arr: any[]) => [...new Set(arr)]; export const checkParentRecursive = ( parentId: string, items: Record, queryIds: string[] ): boolean => { if (queryIds.includes(parentId)) return true; if (!items?.[parentId]?._parent) return false; return checkParentRecursive(items[parentId]._parent, items, queryIds); }; export const cloneDeep = (objectToClone: any) => JSON.parse(JSON.stringify(objectToClone)); export const isObject = (item) => { return item && typeof item === "object" && !Array.isArray(item); }; export const mergeDeep = (target, ...sources) => { if (!sources.length) return target; const source = sources.shift(); if (isObject(target) && isObject(source)) { for (const key in source) { if (isObject(source[key])) { if (!target[key]) Object.assign(target, { [key]: {} }); mergeDeep(target[key], source[key]); } else { Object.assign(target, { [key]: source[key] }); } } } return mergeDeep(target, ...sources); }; export const getArmorRating = ( { _props: { Slots, Weight }, _name, _id }: ITemplateItem, items: Record ): number => { let armorClassWithCoverage = 1; if (Slots?.length > 0) { Slots.forEach((mod) => { const multiplier = (mod._props.filters[0]?.armorColliders?.length || mod._props.filters[0]?.armorPlateColliders?.length) * 3; if (mod._props.filters[0]?.Plate !== undefined) { const plateId = mod._props.filters[0].Plate === "" ? mod._props.filters[0].Filter[0] : mod._props.filters[0].Plate; if (plateId) { const armorClass = Number(items[plateId]?._props?.armorClass || 0); if (armorClass > 0) { armorClassWithCoverage += armorClass * multiplier; if (armorClass >= 3) armorClassWithCoverage += multiplier; } } } }); } // console.log(armorClassWithCoverage, _name, _id); return armorClassWithCoverage; }; export const getAmmoWeighting = ({ _props: { PenetrationPower, Damage, InitialSpeed, ProjectileCount }, _id, _name, }: ITemplateItem): number => { let penBonus = (PenetrationPower - 20) * 10; if (penBonus < 0) penBonus = 0; const damBonus = ProjectileCount > 1 ? Damage * ProjectileCount * 0.1 : Damage; let speedBonus = InitialSpeed > 600 ? 10 : 0; const rating = Math.round(penBonus + speedBonus + damBonus); // if (rating > 20) console.log(rating || 3, _name) return rating || 3; }; export const getHeadwearRating = ( item: ITemplateItem, items: Record ) => { let rating = getArmorRating(item, items); const hasNvg = !!item._props.Slots.find((slot) => slot._name === "mod_nvg"); if (hasNvg) rating += 2; if (item._props?.BlocksEarpiece) rating *= 0.2; // console.log( // Math.round(rating * 1.5 - item._props.Weight), // "-", // item._name, // rating, // item._props.Weight, // item._props?.BlocksEarpiece, // hasNvg, // item._id // ); return Math.round(rating * 1.5 - item._props.Weight) || 1; }; export const getEquipmentType = ( id: string, items: Record ) => { const equipmentKeys = Object.keys(equipmentIdMapper); for (let index = 0; index < equipmentKeys.length; index++) { const key = equipmentKeys[index] as | keyof typeof equipmentIdMapper | undefined; if (checkParentRecursive(id, items, equipmentIdMapper[key])) { return key; } } }; export const getHighestScoringAmmoValue = ( ammoWeight: Record ): number => { let highestValue = 1; let highestKey = ""; for (const key in ammoWeight) { const value = ammoWeight[key]; if (value > highestValue) { highestValue = value; highestKey = key; } } // console.log(highestKey, highestValue) return highestValue; }; export const getWeaponWeighting = ( { _props: { Ergonomics, BoltAction, weapClass, weapFireType, RecoilForceUp, ReloadMode, } = {}, _name, _id, }: ITemplateItem, highestScoringAmmo: number ): number => { let ammo = highestScoringAmmo; let gun = Ergonomics; if (_id === "5bfd297f0db834001a669119") ammo * 0.7; //Make mosin infantry less desirable if (weapFireType.length === 1 && weapFireType.includes("single")) ammo = ammo * 0.8; if (ReloadMode.includes("OnlyBarrel")) ammo = ammo / 4; if (RecoilForceUp > 200) ammo = ammo * 0.8; if (BoltAction) ammo = ammo / 2; if (weapFireType.includes("fullauto")) ammo = ammo * 1.2; if (weapClass !== "pistol" && RecoilForceUp < 100) ammo * 1.2; if ( new Set(["64ca3d3954fc657e230529cc", "64637076203536ad5600c990"]).has(_id) ) { gun *= 0.5; } const finalValue = Math.round(gun + ammo); // if (finalValue > 5) console.log(finalValue > 0 ? finalValue : 1, Math.round(ammo), Math.round(gun), _name, weapClass) return finalValue > 1 ? finalValue : 1; }; export const getBackPackInternalGridValue = ({ _props: { Grids, Weight } = {}, _name, _id, }: ITemplateItem): number => { let total = 0; Grids.forEach(({ _props }) => { total += _props?.cellsH * _props?.cellsV; // if the backpack can't hold "Items" give it a severe lower ranking if ( _props.filters?.[0]?.Filter?.length && !_props.filters?.[0]?.Filter?.includes("54009119af1c881c07000029") ) { total = total / 6; } }); // if (total > 20) total += 20; total = Math.round(total - Weight) * 5; if (total < 0) total = 1; // console.log(total, _name, Weight); if (["6034d103ca006d2dca39b3f0", "6038d614d10cbf667352dd44"].includes(_id)) { total = Math.round(total * 0.7); } return total > 1 ? total : 1; }; export const getTacticalVestValue = ( item: ITemplateItem, items: Record ): number => { const { Grids } = item._props; let spaceTotal = 0; Grids.forEach(({ _props }) => { spaceTotal += _props?.cellsH * _props?.cellsV; }); if (spaceTotal > 12) spaceTotal += 20; spaceTotal = Math.round(spaceTotal - item._props.Weight); const armorRating = getArmorRating(item, items) * 0.8; // console.log( // Math.round( // armorRating > spaceTotal ? armorRating + spaceTotal : spaceTotal * 2 // ), // armorRating > spaceTotal ? "armor" : "vest", // item._name, // item._id // ); return Math.round( armorRating > spaceTotal ? armorRating + spaceTotal : spaceTotal * 2 ); }; export const equipmentIdMapper = { Headwear: [headwearParent], Earpiece: ["5645bcb74bdc2ded0b8b4578"], FaceCover: ["5a341c4686f77469e155819e"], Eyewear: ["5448e5724bdc2ddf718b4568"], ArmBand: ["5b3f15d486f77432d0509248"], ArmorVest: ["5448e54d4bdc2dcc718b4568"], TacticalVest: ["5448e5284bdc2dcb718b4567"], Pockets: ["557596e64bdc2dc2118b4571"], Backpack: ["5448e53e4bdc2d60728b4567"], FirstPrimaryWeapon: [ "5447b5fc4bdc2d87278b4567", "5447b5f14bdc2d61278b4567", "5447bedf4bdc2d87278b4568", "5447bed64bdc2d97278b4568", "5447b6194bdc2d67278b4567", "5447b6094bdc2dc3278b4567", "5447b5e04bdc2d62278b4567", "5447b6254bdc2dc3278b4568", "5447bee84bdc2dc3278b4569", ], // SecondPrimaryWeapon: [], Holster: ["617f1ef5e8b54b0998387733", "5447b5cf4bdc2d65278b4567"], Scabbard: ["5447e1d04bdc2dff2f8b4567"], // mod_magazine: [ // "5448bc234bdc2d3c308b4569", // "610720f290b75a49ff2e5e25" // ], // // Stock: ["55818a594bdc2db9688b456a"], // mod_scope: [...Object.values(SightType)], }; export type oneToFive = "1" | "2" | "3" | "4" | "5"; export const getCurrentLevelRange = ( currentLevel: number ): oneToFive | undefined => { for (const key in levelRange) { const { min, max } = levelRange[key] as MinMax; if (currentLevel >= min && currentLevel <= max) return key as oneToFive; } }; export const numList = [1, 2, 3, 4, 5]; export const arrSum = (arr: number[]): number => arr.reduce((a, b) => a + b, 0); export const setupBaseWhiteList = (): IEquipmentFilterDetails[] => { return numList.map((num) => ({ levelRange: levelRange[num], equipment: {}, cartridge: {}, })); }; export type TradersMasterList = { 1: Set; 2: Set; 3: Set; 4: Set; 5: Set; }; export const setWhitelists = ( items: Record, botConfig: IBotConfig, tradersMasterList: TradersMasterList, mods: Record> ) => { numList.forEach((num, index) => { const loyalty = num; const whitelist = botConfig.equipment.pmc.whitelist; const itemList = [...tradersMasterList[loyalty]]; whitelist[index].equipment = { ...whitelist[index].equipment, ...mods[num], }; itemList.forEach((id) => { const item = items[id]; const parent = item._parent; const equipmentType = getEquipmentType(parent, items); switch (true) { // Check if revolver shotgun case id === "60db29ce99594040e04c4a27": whitelist[index].equipment["FirstPrimaryWeapon"] = [ ...(whitelist[index].equipment["FirstPrimaryWeapon"] ? whitelist[index].equipment["FirstPrimaryWeapon"] : []), id, ]; break; // Check if sawed-off shotgun case id === "64748cb8de82c85eaf0a273a": whitelist[index].equipment["Holster"] = [ ...(whitelist[index].equipment["Holster"] ? whitelist[index].equipment["Holster"] : []), id, ]; break; case !!equipmentType: whitelist[index].equipment[equipmentType] = [ ...(whitelist[index].equipment[equipmentType] ? whitelist[index].equipment[equipmentType] : []), id, ]; break; default: break; } }); if (!!whitelist[index + 1]) { whitelist[index + 1].equipment = cloneDeep(whitelist[index].equipment); } }); // console.log(JSON.stringify(botConfig.equipment.pmc.whitelist)) }; export const buildEmptyWeightAdjustments = (): IWeightingAdjustmentDetails[] => { return numList.map((num) => ({ levelRange: levelRange[num], ammo: { add: {}, edit: {}, }, equipment: { add: {}, edit: {}, }, clothing: { add: {}, edit: {}, }, })); }; const multiplyAndRound = (num1: number, num2: number): number => Math.round(num1 * num2); const setWeightItem = ( weight: IWeightingAdjustmentDetails, equipmentType: string, id: string, rating: number, tierMultiplier: number ) => { // if (add) { // weight.equipment.add[equipmentType] = { // ...weight.equipment.add[equipmentType] || {}, // [id]: rating // } // } else { weight.equipment.edit[equipmentType] = { ...(weight.equipment.edit[equipmentType] || {}), [id]: multiplyAndRound(rating, tierMultiplier) || 1, }; // } }; export const setWeightingAdjustments = ( items: Record, botConfig: IBotConfig, tradersMasterList: TradersMasterList, mods: Record> ) => { const weight = botConfig.equipment.pmc.weightingAdjustmentsByBotLevel; const itemsForNextLevel = {}; numList.forEach((num, index) => { const loyalty = num; const itemList = [...tradersMasterList[loyalty]]; const finalList = [ ...new Set([ ...(advancedConfig.forbiddenBullets[num] || []), ...(itemsForNextLevel[num] || []), ...itemList, ]), ]; // First edit ammo finalList.forEach((id) => { if (num < 4 && combinedForbiddenBullets.has(id)) return; //console.log(num, items[id]._name, id) const item = items[id]; const parent = item._parent; // Ammo Parent if (checkParentRecursive(parent, items, [AmmoParent])) { const calibre = item._props.Caliber || item._props.ammoCaliber; if (num + 1 < 6) { if (!itemsForNextLevel[num + 1]) itemsForNextLevel[num + 1] = new Set([]); itemsForNextLevel[num + 1].add(id); } if (!weight[index]?.ammo.edit?.[calibre]) { weight[index].ammo.edit = { ...weight[index].ammo.edit, [calibre]: {}, }; } const ammoWeight = getAmmoWeighting(item); weight[index].ammo.edit[calibre] = { ...(weight[index].ammo.edit[calibre] || {}), [id]: ammoWeight, }; } }); }); //Make bad ammos worse, better ones better numList.forEach((num, index) => { Object.keys(weight[index].ammo.edit).forEach((caliber) => { const caliberList = Object.keys(weight[index].ammo.edit[caliber]).sort( (a, b) => weight[index].ammo.edit[caliber][b] - weight[index].ammo.edit[caliber][a] ); caliberList.forEach((id, rank) => { if (caliberList.length > 1 && rank > 0) { if (rank > 3) weight[index].ammo.edit[caliber][id] = 5; const modifier = (caliberList.length - rank) / caliberList.length; weight[index].ammo.edit[caliber][id] = Math.round(weight[index].ammo.edit[caliber][id] * modifier) || 5; if (weight[index].ammo.edit[caliber][id] === 1) weight[index].ammo.edit[caliber][id] = 5; } }); }); // console.log(JSON.stringify(weight[index].ammo.edit)) }); //Make best ammos have a chance of use at lower level weight.reverse().forEach((currentItem, index) => { const nextItem = weight?.[index + 1]; if (nextItem) { Object.keys(nextItem.ammo.edit).forEach((caliber) => { if (currentItem.ammo.edit[caliber]) { const max = Math.max(...Object.values(nextItem.ammo.edit[caliber])); const maxValueForHighTier = Math.round( config.higherTierAmmoChance * max ); const nextAmmoIdList = new Set( Object.keys(nextItem.ammo.edit[caliber] || {}) ); const currentTierItemList = Object.keys( currentItem.ammo.edit[caliber] ) .filter( (id) => !nextAmmoIdList.has(id) && currentItem.ammo.edit[caliber][id] > maxValueForHighTier ) .sort( (a, b) => currentItem.ammo.edit[caliber][b] - currentItem.ammo.edit[caliber][a] ); currentTierItemList.forEach((id, rank) => { weight[index + 1].ammo.edit[caliber][id] = Math.round( maxValueForHighTier / (currentTierItemList.length - rank) ); }); } }); } }); weight.reverse(); // Apply randomness weight.forEach(({ ammo }, index) => { Object.keys(ammo.edit).forEach((calbr) => { const list = weight[index].ammo.edit[calbr]; const keys = Object.keys(list); const sortedValues = Object.values(list).sort((a, b) => a - b); const middleIndex = 0 + Math.round((sortedValues.length - 1) / 2); const medianValue = sortedValues[middleIndex]; const highestValue = sortedValues[sortedValues.length - 1]; const lowestValue = sortedValues[0]; const betterValue = Math.round( (medianValue + highestValue + lowestValue) / 3 ); if (betterValue >= 1) { keys.forEach((key) => { const valToAdjust = list[key]; if (valToAdjust > 5) { const adjustedAmountMax = betterValue - valToAdjust; const amountAfterAdjustment = Math.round( valToAdjust + adjustedAmountMax * config.randomness.Ammo ); if (weight[index].ammo.edit[calbr][key]) { weight[index].ammo.edit[calbr][key] = Math.abs( amountAfterAdjustment ); } } }); } }); }); // saveToFile(weight, "refDBS/weight1.json"); //------------------------------------------------------------------------------ // for (const category in weight.ammo.edit) { // const randomnessMultiplier = config?.randomness?.[category]; // if (!randomnessMultiplier) return; // const list = weight[index].equipment.edit[category]; // const keys = Object.keys(list); // const sortedValues = Object.values(list).sort((a, b) => a - b); // const middleIndex = 0 + Math.round((sortedValues.length - 1) / 2); // const medianValue = sortedValues[middleIndex]; // const highestValue = sortedValues[sortedValues.length - 1]; // const lowestValue = sortedValues[0]; // const betterValue = Math.round( // (medianValue + highestValue + lowestValue) / 3 // ); // if (betterValue > 1) { // keys.forEach((key) => { // const valToAdjust = list[key]; // if (valToAdjust > 5) { // const adjustedAmountMax = betterValue - valToAdjust; // const amountAfterAdjustment = Math.round( // valToAdjust + adjustedAmountMax * randomnessMultiplier // ); // if (weight[index].equipment.edit[category][key]) { // weight[index].equipment.edit[category][key] = Math.abs( // amountAfterAdjustment // ); // } // } // }); // } // } // saveToFile(weight, "refDBS/weight1.json"); //------------------------------------------------------------------------------ numList.forEach((actualNum, index) => { numList.forEach((num) => { if (num > actualNum) return; const itemList = [...tradersMasterList[num]]; itemList.forEach((id) => { const item = items[id]; const parent = item._parent; const equipmentType = getEquipmentType(parent, items); const itemIsArmor = Number(item._props.armorClass) > 0; const isLowList = actualNum - num >= (itemIsArmor ? 1 : 3); const tierMultiplier = isLowList ? 0 : num / actualNum; if (equipmentType) { if (!weight[index]?.equipment?.edit?.[equipmentType]) { weight[index].equipment.edit = { ...weight[index].equipment.edit, [equipmentType]: {}, }; } } switch (equipmentType) { case "FirstPrimaryWeapon": case "Holster": if (num + 1 < 6) { if (!itemsForNextLevel[num + 1]) itemsForNextLevel[num + 1] = new Set([]); itemsForNextLevel[num + 1].add(id); } const calibre = item._props.Caliber || item._props.ammoCaliber; const highestScoringAmmo = getHighestScoringAmmoValue( weight[index].ammo.edit[calibre] ); const weaponRating = getWeaponWeighting(item, highestScoringAmmo); switch (id) { // Check if revolver shotgun case "60db29ce99594040e04c4a27": setWeightItem( weight[index], "FirstPrimaryWeapon", id, weaponRating, tierMultiplier ); break; // Check if sawed-off shotgun case "64748cb8de82c85eaf0a273a": setWeightItem( weight[index], "Holster", id, weaponRating, tierMultiplier ); break; default: setWeightItem( weight[index], equipmentType, id, weaponRating, tierMultiplier ); break; } break; case "Headwear": const rating = getHeadwearRating(item, items); setWeightItem( weight[index], equipmentType, id, Math.round(rating), tierMultiplier ); break; case "Earpiece": const ambientVolumeBonus = item?._props?.AmbientVolume * -1; const compressorBonus = item?._props?.CompressorVolume * -0.5; setWeightItem( weight[index], equipmentType, id, Math.round(compressorBonus + ambientVolumeBonus), tierMultiplier ); break; case "FaceCover": setWeightItem( weight[index], equipmentType, id, Math.round( (item._props.BlocksHeadwear ? 0.1 : 1) * (item._props.ExamineExperience || 0) + (item._props.LootExperience || 0) ), tierMultiplier ); break; case "ArmorVest": const armorRating = getArmorRating(item, items); setWeightItem( weight[index], equipmentType, id, armorRating, tierMultiplier ); break; case "ArmBand": setWeightItem(weight[index], equipmentType, id, 20, tierMultiplier); break; case "Scabbard": setWeightItem( weight[index], equipmentType, id, Math.round( (item._props.StabPenetration || 0) + (item._props.SlashPenetration || 0) + (item._props.ExamineExperience || 0) + (item._props.LootExperience || 0) ), tierMultiplier ); break; case "Eyewear": setWeightItem( weight[index], equipmentType, id, Math.round( item._props.LootExperience + item._props.BlindnessProtection * 5 ) || 3, tierMultiplier ); break; case "Backpack": const backpackInternalGridValue = getBackPackInternalGridValue(item); setWeightItem( weight[index], equipmentType, id, backpackInternalGridValue, tierMultiplier ); break; case "TacticalVest": const tacticalVestWeighting = getTacticalVestValue(item, items); setWeightItem( weight[index], equipmentType, id, tacticalVestWeighting, tierMultiplier ); break; default: // switch (true) { // case checkParentRecursive(id, items, [medsParent]): // setWeightItem( // weight[index], // "SecuredContainer", // id, // num * 10, // tierMultiplier // ); // break; // default: // break; // } break; } }); }); for (const category in weight[index].equipment.edit) { const randomnessMultiplier = config?.randomness?.[category]; if (!randomnessMultiplier) return; const list = weight[index].equipment.edit[category]; const keys = Object.keys(list); const sortedValues = Object.values(list).sort((a, b) => a - b); const middleIndex = 0 + Math.round((sortedValues.length - 1) / 2); const medianValue = sortedValues[middleIndex]; const highestValue = sortedValues[sortedValues.length - 1]; const lowestValue = sortedValues[0]; const betterValue = Math.round( (medianValue + highestValue + lowestValue) / 3 ); if (betterValue > 1) { keys.forEach((key) => { const valToAdjust = list[key]; if (valToAdjust > 5) { const adjustedAmountMax = betterValue - valToAdjust; const amountAfterAdjustment = Math.round( valToAdjust + adjustedAmountMax * randomnessMultiplier ); if (weight[index].equipment.edit[category][key]) { weight[index].equipment.edit[category][key] = Math.abs( amountAfterAdjustment ); } } }); } } }); // const list: { [key: string]: string[] } = {} // tradersMasterList[5].forEach(id => { // const parent = items[id]?._parent // if (!parent) return // const equipmentType = getEquipmentType(parent, items) // if (equipmentType) { // if (!list?.[equipmentType]) list[equipmentType] = [] // list[equipmentType].push(id) // } else if (checkParentRecursive(parent, items, [AmmoParent])) { // if (!list?.["ammo"]) list["ammo"] = [] // list.ammo.push(id) // } // }) // saveToFile({ list }, "refDBS/tier5.json") }; export const addAllMedsToInventory = ( traderList: Set, inventory: IInventory, items: Record ) => { traderList.forEach((id) => { if (checkParentRecursive(id, items, [medsParent])) { if ( inventory.equipment.SecuredContainer?.[id] || inventory.equipment.SecuredContainer[id] !== 1 ) { // console.log(items[id]._name); inventory.equipment.SecuredContainer[id] = 1; } } }); }; export const combineWhitelist = (equipmentFilters: EquipmentFilters) => { const combinedWhitelist = { levelRange: { min: 1, max: 99, }, equipment: {}, cartridge: {}, }; equipmentFilters.whitelist.forEach((list, index) => { for (const key in list) { if (key !== "levelRange") { for (const subKey in list[key]) { const value = equipmentFilters.whitelist[index]?.[key]?.[subKey]; if (value) { combinedWhitelist[key][subKey] = deDupeArr([ ...(!!combinedWhitelist[key][subKey] ? combinedWhitelist[key][subKey] : []), ...value, ]); } } } } }); equipmentFilters.whitelist = [combinedWhitelist]; // saveToFile(equipmentFilters.whitelist, "refDBS/equipmentFilters.json"); }; const addRecursive = ( modId: string, items: Record, weaponId: string, mods: IMods, count = 0 ) => { if (count > 115) return false; const newModObject = {}; let pass = false; if (items[modId]?._props?.Slots?.length > 0) { items[modId]._props.Slots.forEach((mod) => { if (mod._props?.filters?.[0]?.Filter?.length) { newModObject[mod._name] = mod._props.filters[0].Filter.filter((id) => { if (blacklistedItems.has(id)) return false; count += 1; addRecursive(id, items, weaponId, mods, count); return true; }); pass = true; } }); } if (pass && Object.keys(newModObject).length) { mods[modId] = newModObject; } }; export const buildOutModsObject = ( traderList: Set, items: Record, inventory: IInventory, botConfig: IBotConfig ) => { traderList.forEach((id) => { const item = items[id]; const newModObject = {} as Record; if ( !blacklistedItems.has(id) && checkParentRecursive(item._parent, items, [ magParent, weaponParent, headwearParent, armorParent, rigParent, ]) ) { switch (true) { case checkParentRecursive(item._parent, items, [magParent]): // if (item?._props?.Height * item?._props?.Width < 3) { const bulletList = item?._props?.Cartridges?.[0]?._props?.filters?.[0]?.Filter.filter( (_tpl) => !!_tpl && !blacklistedItems.has(_tpl) ); if (bulletList) { newModObject["cartridges"] = bulletList; inventory.mods[id] = newModObject; } // } else { // config.debug && // console.warn( // id, // item._name, // item?._props?.Cartridges?.[0]?._max_count // ); // } break; case checkParentRecursive(item._parent, items, [weaponParent]): //Weapon if (item?._props?.Slots?.length > 0) { item._props.Slots.forEach((mod) => { // newModObject[mod._name] = mod._props?.filters[0].Filter.filter((_tpl) => !!_tpl && !blacklistedItems.has(_tpl) && checkForScopeTypeRecursive(_tpl, items, id, inventory.mods)) // } else if (mod._props?.filters?.[0]?.Filter?.length) { newModObject[mod._name] = mod._props.filters[0].Filter.filter( (_tpl) => { if (!!_tpl && !blacklistedItems.has(_tpl)) { addRecursive(_tpl, items, id, inventory.mods); return true; } return false; } ); } }); } if ( item._props?.Chambers?.[0]?._name === "patron_in_weapon" && item._props?.Chambers?.[0]?._props?.filters?.[0]?.Filter?.length ) { newModObject["patron_in_weapon"] = item._props.Chambers[0]._props?.filters[0].Filter.filter( (_tpl) => !!_tpl && !blacklistedItems.has(_tpl) ); } if (Object.keys(newModObject)) { inventory.mods[id] = newModObject; } break; case checkParentRecursive(item._parent, items, [ armorParent, rigParent, headwearParent, ]): //armor/vest if (item?._props?.Slots?.length > 0) { const newModObject = {}; item._props.Slots.forEach((mod) => { newModObject[mod._name] = mod._props.filters[0].Filter.filter( (_tpl) => { addRecursive(_tpl, items, id, inventory.mods); return !!_tpl && !blacklistedItems.has(_tpl); } ); // } }); inventory.mods[id] = newModObject; } break; default: // console.log(items[item._parent]._name, id) break; } } }); traderList.forEach((id) => { const item = items[id]; const newModObject = mappedPresets[id] ? mappedPresets[id] : ({} as Record); if ( !inventory.mods[id] && !blacklistedItems.has(id) && checkParentRecursive(item._parent, items, [modParent]) ) { if (item?._props?.Slots?.length > 0) { item._props.Slots.forEach((mod) => { if (mod._props?.filters?.[0]?.Filter?.length) { switch (true) { case mod._name?.includes("scope") && checkParentRecursive(item._parent, items, [ handguardParent, gasblockParent, ]) /*gasblockParent,*/: if (!newModObject[mod._name]) newModObject[mod._name] = []; break; // case mod._name?.includes("scope"): // newModObject[mod._name] = mod._props?.filters[0].Filter.filter((_tpl) => siteWhiteList["5447bedf4bdc2d87278b4568"].includes(_tpl)) // console.log(item._name, newModObject[mod._name]) default: newModObject[mod._name] = deDupeArr([ ...(newModObject[mod._name] ? newModObject[mod._name] : []), ...mod._props?.filters[0].Filter.filter( (_tpl) => !blacklistedItems.has(_tpl) ), ]); break; } } }); if (Object.keys(newModObject)) { inventory.mods[id] = newModObject; } } } }); // console.log(JSON.stringify(inventory.mods)) }; export const buildInitialRandomization = ( items: Record, botConfig: IBotConfig, traderList: TradersMasterList, lootingBotsDetected: boolean ) => { const randomizationItems: IRandomisationDetails[] = []; numList.forEach((num, index) => { const range = levelRange[num]; const newItem: IRandomisationDetails = { levelRange: range, randomisedArmorSlots: ["TacticalVest", "ArmorVest"], randomisedWeaponModSlots: [], equipment: { Headwear: [75, 85, 99, 99, 99][index], Earpiece: [55, 75, 95, 100, 100][index], FaceCover: [25, 35, 65, 75, 90][index], ArmorVest: index < 2 ? 100 : 70, // [99, 99, 99, 99, 99][index], ArmBand: [25, 45, 59, 69, 80][index], // TacticalVest: [96, 96, 99, 99, 99][index], Pockets: [25, 45, 59, 69, 80][index], SecondPrimaryWeapon: [0, 0, 0, 0, 5][index], SecuredContainer: 100, Scabbard: [1, 5, 5, 10, 40][index], FirstPrimaryWeapon: [85, 98, 99, 99, 99][index], Holster: [1, 5, 10, 10, 25][index], Eyewear: [15, 25, 40, 60, 75][index], Backpack: [70, 85, 90, 99, 99][index], }, generation: { stims: { weights: [ { "0": 5, "1": 1, }, { "0": 3, "1": 1, }, { "0": 2, "1": 1, }, { "0": 6, "1": 5, "2": 1, }, { "0": 5, "1": 5, "2": 1, }, ][index], whitelist: { ...(randomizationItems[index - 1]?.generation.stims.whitelist || {}), }, }, drugs: { weights: [ { "0": 1, "1": 3, }, { "0": 1, "1": 4, }, { "0": 1, "1": 5, }, { "0": 0, "1": 5, "2": 1, }, { "0": 0, "1": 3, "2": 1, }, ][index], whitelist: { ...(randomizationItems[index - 1]?.generation.drugs.whitelist || {}), }, }, healing: { weights: [ { "0": 1, "1": 6, }, { "0": 1, "1": 8, }, { "0": 1, "1": 12, }, { "0": 1, "1": 25, "2": 5, }, { "0": 0, "1": 3, "2": 1, }, ][index], whitelist: { ...(randomizationItems[index - 1]?.generation.healing.whitelist || {}), }, }, grenades: { weights: [ { "0": 1, "1": 1, }, { "0": 2, "1": 2, "2": 1, }, { "0": 1, "1": 2, "2": 1, }, { "0": 1, "1": 2, "2": 2, }, { "0": 0, "1": 2, "2": 2, "3": 1, }, ][index], whitelist: { ...(randomizationItems[index - 1]?.generation.grenades.whitelist || {}), }, }, backpackLoot: { weights: lootingBotsDetected ? { "0": 1, } : [ { "0": 1, "1": 2, "2": 2, "3": 1, "4": 1, }, { "0": 1, "1": 1, "2": 2, "3": 2, "4": 2, "5": 1, }, { "0": 0, "1": 1, "2": 1, "3": 1, "4": 2, "5": 2, "6": 1, "7": 1, }, { "0": 0, "1": 0, "2": 1, "3": 1, "4": 3, "5": 2, "6": 2, "7": 1, }, { "0": 0, "1": 0, "2": 0, "3": 0, "4": 1, "5": 1, "6": 3, "7": 2, "8": 2, }, ][index], whitelist: {}, }, pocketLoot: { weights: lootingBotsDetected ? { "0": 1, } : [ { "0": 4, "1": 1, "2": 1, }, { "0": 3, "1": 2, "2": 1, }, { "0": 2, "1": 2, "2": 1, "3": 1, }, { "0": 1, "1": 2, "2": 1, "3": 1, }, { "0": 1, "1": 1, "2": 2, "3": 1, }, ][index], whitelist: {}, }, vestLoot: { weights: lootingBotsDetected ? { "0": 1, } : [ { "0": 3, "1": 1, "2": 1, }, { "0": 2, "1": 2, "2": 1, "4": 1, }, { "0": 1, "1": 1, "2": 2, "3": 2, "5": 2, }, { "0": 1, "1": 1, "2": 1, "3": 2, "4": 2, "5": 2, }, { "0": 0, "1": 2, "3": 2, "4": 1, "5": 1, }, ][index], whitelist: {}, }, magazines: { weights: [ { "0": 0, "1": 1, "2": 1, }, { "0": 0, "1": 1, "2": 1, }, { "0": 0, "1": 0, "2": 1, "3": 1, }, { "0": 0, "1": 0, "2": 1, "3": 1, }, { "0": 0, "1": 0, "2": 1, "3": 1, }, ][index], whitelist: botConfig.equipment.pmc?.whitelist[index]?.equipment ?.mod_magazine ? (() => { const result = {}; botConfig.equipment.pmc.whitelist[ index ]?.equipment?.mod_magazine.forEach((item) => { result[item] = 1; }); return result; })() : {}, }, }, weaponMods: { mod_barrel: [5, 20, 35, 55, 65][index], mod_bipod: [1, 10, 5, 11, 50][index], mod_flashlight: [5, 35, 65, 80, 90][index], mod_foregrip: [10, 40, 70, 90, 95][index], mod_handguard: [5, 40, 70, 90, 95][index], mod_launcher: [0, 0, 5, 15, 50][index], mod_magazine: [50, 60, 80, 90, 95][index], mod_magazine_000: [0, 0, 25, 75, 90][index], mod_mount: [75, 95, 100, 100, 100][index], mod_mount_000: [20, 45, 75, 90, 95][index], mod_mount_001: [20, 45, 75, 90, 95][index], mod_mount_002: [20, 45, 75, 90, 95][index], mod_mount_003: [20, 45, 75, 90, 95][index], mod_mount_004: [20, 45, 75, 90, 95][index], mod_mount_005: [20, 45, 75, 90, 95][index], mod_mount_006: [20, 45, 75, 90, 95][index], mod_muzzle: [5, 15, 35, 70, 100][index], mod_muzzle_000: [5, 15, 55, 100, 100][index], mod_muzzle_001: [5, 15, 80, 100, 100][index], mod_equipment: [15, 25, 45, 75, 90][index], mod_equipment_000: [0, 0, 10, 35, 45][index], mod_equipment_001: [0, 0, 10, 35, 45][index], mod_equipment_002: [0, 0, 10, 35, 45][index], mod_pistol_grip_akms: [1, 25, 45, 55, 80][index], mod_pistol_grip: [1, 25, 45, 65, 80][index], mod_scope: [30, 70, 100, 100, 100][index], mod_scope_000: [30, 80, 100, 100, 100][index], mod_scope_001: [30, 80, 100, 100, 100][index], mod_scope_002: [30, 80, 100, 100, 100][index], mod_scope_003: [30, 80, 100, 100, 100][index], mod_tactical: [15, 30, 65, 70, 95][index], mod_tactical_2: 0, mod_tactical001: [5, 25, 45, 70, 85][index], mod_tactical002: [5, 25, 45, 70, 85][index], mod_tactical_000: [1, 5, 10, 45, 65][index], mod_tactical_001: [1, 5, 10, 45, 65][index], mod_tactical_002: [15, 30, 55, 70, 95][index], mod_tactical_003: [15, 30, 55, 70, 95][index], mod_charge: [10, 20, 55, 70, 95][index], mod_stock: [5, 15, 55, 70, 95][index], mod_stock_000: 99, // "mod_stock_001": [1, 10, 15, 20][index], mod_stock_akms: 100, mod_sight_front: [90, 40, 5, 0, 0][index], mod_sight_rear: [90, 40, 5, 0, 0][index], // "mod_reciever": 100, // "mod_gas_block": [1, 10, 15, 20][index], mod_pistolgrip: [1, 15, 45, 55, 90][index], // "mod_trigger": 1, // "mod_hammer": 1, // "mod_catch": 1 }, equipmentMods: { mod_nvg: 0, back_plate: [80, 90, 100, 100, 100][index], front_plate: [80, 90, 100, 100, 100][index], left_side_plate: [50, 80, 90, 90, 100][index], right_side_plate: [50, 80, 90, 90, 100][index], mod_flashlight: [5, 25, 35, 45, 70][index], mod_equipment: [15, 25, 25, 35, 70][index], mod_equipment_000: [0, 0, 0, 5, 20][index], mod_equipment_001: [0, 0, 5, 15, 25][index], mod_equipment_002: [0, 0, 5, 15, 25][index], }, }; traderList[num].forEach((id) => { const item = items[id]; const parent = item._parent; switch (true) { case checkParentRecursive( parent, items, num >= 3 ? [painKillerParent, stimParent] : [painKillerParent] ): //stims // console.log(id, item._name, 5 - index); newItem.generation.stims.whitelist[id] = num * num * 5; break; case checkParentRecursive(parent, items, [medicalParent]): //drugs newItem.generation.drugs.whitelist[id] = num * num * 5; break; case checkParentRecursive(parent, items, [medKitParent]): //meds newItem.generation.healing.whitelist[id] = num * num * 5; // medkitsAdd[num].forEach((addId: string) => { // newItem.generation.healing.whitelist[addId] = num * num * 5; // }); // medkitsRemove[num].forEach((removeId: string) => { // delete newItem.generation.healing.whitelist[removeId]; // }); break; case checkParentRecursive(parent, items, ["543be6564bdc2df4348b4568"]): //ThrowWeap if (items[id]._props.ThrowType !== "smoke_grenade") { newItem.generation.grenades.whitelist[id] = num * num * 5; } break; default: break; } }); randomizationItems.push(newItem); }); botConfig.lootItemResourceRandomization["pmc"] = { food: { resourcePercent: 50, chanceMaxResourcePercent: 90, }, meds: { resourcePercent: 50, chanceMaxResourcePercent: 70, }, }; botConfig.equipment.pmc["forceStock"] = advancedConfig.forceStock; botConfig.equipment.pmc.randomisation = randomizationItems; // console.log(JSON.stringify(randomizationItems)); }; export const buildInitialUsecAppearance = ( appearance: IAppearance, items: Record ) => { appearance.feet = { "5cde95ef7d6c8b04713c4f2d": 15, }; appearance.body = { "5cde95d97d6c8b647a3769b0": 15, }; Object.keys(items).forEach((itemId) => { const item = items[itemId]; if (item?._props?.Side?.includes("Usec")) switch (true) { case item._props.BodyPart === "Head": if (!appearance.head[itemId]) appearance.head[itemId] = 10; break; case item._props.BodyPart === "Hands": if (!appearance.hands[itemId]) appearance.hands[itemId] = 10; break; default: break; } }); }; export const buildInitialBearAppearance = ( appearance: IAppearance, items: Record ) => { appearance.feet = { "5cc085bb14c02e000e67a5c5": 10, }; appearance.body = { "5cc0858d14c02e000c6bea66": 10, }; Object.keys(items).forEach((itemId) => { const item = items[itemId]; if (item?._props?.Side?.includes("Bear")) switch (true) { case item._props.BodyPart === "Head": if (!appearance.head[itemId]) appearance.head[itemId] = 10; break; case item._props.BodyPart === "Hands": if (!appearance.hands[itemId]) appearance.hands[itemId] = 10; break; // case item._parent === "5fc100cf95572123ae738483": // if (!appearance.voice.includes(item._name)) appearance.voice.push(item._name) // break; default: break; } }); }; export const buildClothingWeighting = ( suit: ISuit[], items: Record, botConfig: IBotConfig, usecAppearance: IAppearance, bearAppearance: IAppearance ) => { buildInitialUsecAppearance(usecAppearance, items); buildInitialBearAppearance(bearAppearance, items); const levels = Object.values(levelRange); suit.forEach( ({ suiteId, requirements: { profileLevel, loyaltyLevel } = {} }) => { if (!profileLevel || !suiteId || loyaltyLevel === undefined) return; if (profileLevel === 0) profileLevel = 1; const index = levels.findIndex(({ min, max }) => { if (profileLevel >= min && profileLevel <= max) { return true; } }); if (index === -1) return console.log( "Unable to find index for clothing item", items[suiteId]?._name ); const clothingAdjust = botConfig.equipment.pmc.weightingAdjustmentsByBotLevel[index].clothing; if (index === undefined) return console.log("Empty index for: ", suiteId); if (items[suiteId]?._props?.Body) { switch (true) { case !!items[suiteId]?._name?.toLowerCase().includes("bear"): bearAppearance.body[items[suiteId]._props.Body] = 1; break; case !!items[suiteId]?._name?.toLowerCase().includes("usec"): usecAppearance.body[items[suiteId]._props.Body] = 1; break; default: bearAppearance.body[items[suiteId]._props.Body] = 1; usecAppearance.body[items[suiteId]._props.Body] = 1; break; } if (!clothingAdjust?.edit["body"]) clothingAdjust.edit["body"] = {}; clothingAdjust.edit["body"][items[suiteId]._props.Body] = 10 + index * 30; } if (items[suiteId]?._props?.Feet) { switch (true) { case !!items[suiteId]?._name?.toLowerCase().includes("bear"): bearAppearance.feet[items[suiteId]._props.Feet] = 1; break; case !!items[suiteId]?._name?.toLowerCase().includes("usec"): usecAppearance.feet[items[suiteId]._props.Feet] = 1; break; default: bearAppearance.feet[items[suiteId]._props.Feet] = 1; usecAppearance.feet[items[suiteId]._props.Feet] = 1; break; } if (!clothingAdjust?.edit["feet"]) clothingAdjust.edit["feet"] = {}; clothingAdjust.edit["feet"][items[suiteId]._props.Feet] = 10 + index * 30; } } ); // console.log(JSON.stringify(clothingAdjust)) // saveToFile(items, "/customization.json") // saveToFile(bearAppearance, "/bear.json") // saveToFile(usecAppearance, "/usec.json") // saveToFile(clothingAdjust, "/clothingWeighting.json") }; export const weaponTypes = { "5447b6254bdc2dc3278b4568": [SightType.AssaultScope, SightType.OpticScope], // SniperRifle "5447b6194bdc2d67278b4567": [SightType.AssaultScope, SightType.OpticScope], // MarksmanRifle "5447b5fc4bdc2d87278b4567": [SightType.Collimator, SightType.AssaultScope], // AssaultCarbine "5447b5f14bdc2d61278b4567": [ SightType.CompactCollimator, SightType.Collimator, SightType.AssaultScope, ], // AssaultRifle "5447bed64bdc2d97278b4568": [ SightType.CompactCollimator, SightType.Collimator, ], // MachineGun "5447b5e04bdc2d62278b4567": [ SightType.CompactCollimator, SightType.Collimator, ], // Smg "5447bee84bdc2dc3278b4569": [ SightType.CompactCollimator, SightType.Collimator, ], // SpecialWeapon "5447b6094bdc2dc3278b4567": [ SightType.CompactCollimator, SightType.Collimator, ], // Shotgun "5447b5cf4bdc2d65278b4567": [ SightType.CompactCollimator, SightType.Collimator, ], // Pistol "617f1ef5e8b54b0998387733": [ SightType.CompactCollimator, SightType.Collimator, ], // Revolver "5447bedf4bdc2d87278b4568": [ SightType.CompactCollimator, SightType.Collimator, ], // GrenadeLauncher }; export const buildWeaponSightWhitelist = ( items: Record, botConfig: IBotConfig, { 1: a, 2: b, 3: c, 4: d, 5: e }: TradersMasterList ) => { delete botConfig.equipment.pmc.weaponSightWhitelist; // botConfig.equipment.pmc.weaponSightWhitelist = {}; return; const sightWhitelist = botConfig.equipment.pmc.weaponSightWhitelist; const traderItems = [...new Set([...a, ...b, ...c, ...d, ...e])]; //, ...d const blacklist = new Set(InternalBlacklist); traderItems.forEach((id) => { if (blacklist.has(id)) return; if (checkParentRecursive(id, items, Object.values(SightType))) { for (const key in weaponTypes) { const sightsToCheck = weaponTypes[key]; if (checkParentRecursive(id, items, sightsToCheck)) { if (!sightWhitelist[key]) sightWhitelist[key] = []; sightWhitelist[key].push(id); } } } }); // console.log(JSON.stringify(sightWhitelist)) }; export const buildBlacklist = ( items: Record, botConfig: IBotConfig, mods: { "1": {}; "2": {}; "3": {}; "4": {}; "5": {} } ) => { delete botConfig.equipment.pmc.blacklist[0].equipment.mod_magazine; const currentBlacklist = cloneDeep(botConfig.equipment.pmc.blacklist[0]); botConfig.equipment.pmc.blacklist = []; const blacklist = botConfig.equipment.pmc.blacklist; // const itemsToAddToBlacklist = ["mod_scope", "mod_magazine"] numList.forEach((num, index) => { const modList = mods[num]; const range = levelRange[num]; const loyalty = num; const base = { ...cloneDeep(currentBlacklist), levelRange: range }; if (index < 2) { numList.splice(0, index + 2).forEach((numInner) => { Object.keys(mods[numInner]).forEach((key) => { if (!base.equipment[key]) base.equipment[key] = []; base.equipment[key].push(...mods[numInner][key]); }); }); } blacklist.push(base); }); }; export const deleteBlacklistedItemsFromInventory = ( inventory: IInventory, blacklist: Set ) => { Object.keys(inventory.items).forEach((key) => { Object.keys(inventory.items[key]).forEach((id) => { if (blacklist.has(id)) delete inventory.items[key][id]; }); }); Object.keys(inventory.Ammo).forEach((calibre) => { Object.keys(inventory.Ammo[calibre]).forEach((ammoKey) => { if (blacklist.has(ammoKey)) { delete inventory.Ammo[calibre][ammoKey]; // console.log(calibre, ammoKey, inventory.Ammo[calibre][ammoKey]); } }); }); Object.keys(inventory.mods).forEach((key) => { if (blacklist.has(key)) { delete inventory.mods[key]; } else { Object.keys(inventory.mods?.[key]).forEach((modtype) => { if (inventory.mods[key][modtype]?.length) { inventory.mods[key][modtype].filter((id) => !blacklist.has(id)); } }); } }); }; export const ensureAllAmmoInSecuredContainer = (inventory: IInventory) => { const ammo = Object.keys(inventory.Ammo) .map((calbr) => Object.keys(inventory.Ammo[calbr])) .flat(); inventory?.items?.SecuredContainer || {}; ammo.forEach((id) => { if (!inventory?.items?.SecuredContainer?.[id]) { inventory.items.SecuredContainer[id] = 1; } }); // const sortedAmmo = ammo.sort( // (a, b) => getAmmoWeighting(items[a]) - getAmmoWeighting(items[b]) // ); // saveToFile({ sortedAmmo }, "refDBS/ammoList.json"); }; export const fixEmptyChancePlates = (botConfig: IBotConfig) => { const armorPlateWeighting = botConfig.equipment.pmc.armorPlateWeighting; for (const key in armorPlateWeighting) { for (const subKey in armorPlateWeighting[key]) { if (!armorPlateWeighting[key][subKey]?.min) { for (const num in armorPlateWeighting[key][subKey]) { if (armorPlateWeighting[key][subKey][num] === 0) { armorPlateWeighting[key][subKey][num] = 1; } } } } } }; export const addBossSecuredContainer = (inventory: IInventory) => { inventory.equipment.SecuredContainer = { "5c0a794586f77461c458f892": 1, }; }; export const combinedForbiddenBullets = new Set( Object.values(advancedConfig.forbiddenBullets).flat(1) ); export const blacklistedItems = new Set([ ...config.customBlacklist, ...InternalBlacklist, ]);