feat(looting bots)
This commit is contained in:
parent
6aac2af208
commit
6a8ce2b606
6 changed files with 260 additions and 0 deletions
BIN
BepInEx/plugins/skwizzy.LootingBots.dll
Normal file
BIN
BepInEx/plugins/skwizzy.LootingBots.dll
Normal file
Binary file not shown.
16
user/mods/Skwizzy-LootingBots-ServerMod/README.md
Normal file
16
user/mods/Skwizzy-LootingBots-ServerMod/README.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
## Description ##
|
||||
A server side mod that serves two main purposes for LootingBots.
|
||||
|
||||
1. Marks all items with DiscardLimits as InsuranceDisabled. It then disables the DiscardLimit settings for the server via the EnableDiscardLimits option in Server/database/globals.json. SPT PMC bots by default spawn with loot already in their backpacks, this loot is not marked Found In Raid and thus is subject to BSG's RMT protection logic. With discard limits enabled, when a bot drops their backback to swap to a new one any loot with discard limits in their bag will be deleted immediately when the bag is dropped. To avoid this we set the EnableDiscardLimits to false, and also make sure to flag all items with a DiscardLimit >= 0 as InsuranceDisabled to prevent items suchs as keys and cases to be insured.
|
||||
|
||||
2. Provide the option to clear out the loot that PMC/Scav bots start with in their backpacks. This does not include meds, ammo, grenades ect. These options can be found in the `LootingBots-ServerMod/config/config.json`.
|
||||
- `pmcSpawnWithLoot` - When set to `true`, PMCs will spawn with loot in their bags/pockets (default SPT behavior)
|
||||
- `scavSpawnWithLoot` - When set to `true`, Scavs will spawn with loot in the bags/pockets (default SPT behavior)
|
||||
|
||||
Default config:
|
||||
```
|
||||
{
|
||||
"pmcSpawnWithLoot": false,
|
||||
"scavSpawnWithLoot": true
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"pmcSpawnWithLoot": true,
|
||||
"scavSpawnWithLoot": true
|
||||
}
|
||||
23
user/mods/Skwizzy-LootingBots-ServerMod/package.json
Normal file
23
user/mods/Skwizzy-LootingBots-ServerMod/package.json
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "LootingBots-ServerMod",
|
||||
"version": "1.5.2",
|
||||
"main": "src/mod.js",
|
||||
"license": "MIT",
|
||||
"author": "Skwizzy",
|
||||
"sptVersion": "~3.11",
|
||||
"scripts": {
|
||||
"setup": "npm i",
|
||||
"build": "node ./packageBuild.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.18.18",
|
||||
"@typescript-eslint/eslint-plugin": "5.46.1",
|
||||
"@typescript-eslint/parser": "5.46.1",
|
||||
"bestzip": "2.2.1",
|
||||
"eslint": "8.30.0",
|
||||
"fs-extra": "11.1.0",
|
||||
"glob": "8.0.3",
|
||||
"tsyringe": "4.7.0",
|
||||
"typescript": "4.9.4"
|
||||
}
|
||||
}
|
||||
122
user/mods/Skwizzy-LootingBots-ServerMod/src/enums.ts
Normal file
122
user/mods/Skwizzy-LootingBots-ServerMod/src/enums.ts
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
export const enum ParentClasses {
|
||||
WEAPON = "5422acb9af1c889c16000029",
|
||||
ARMORVEST = "5448e54d4bdc2dcc718b4568",
|
||||
ARMOREDEQUIPMENT = "57bef4c42459772e8d35a53b",
|
||||
HEADWEAR = "5a341c4086f77401f2541505",
|
||||
FACECOVER = "5a341c4686f77469e155819e",
|
||||
CHESTRIG = "5448e5284bdc2dcb718b4567",
|
||||
BACKPACK = "5448e53e4bdc2d60728b4567",
|
||||
VISORS = "5448e5724bdc2ddf718b4568",
|
||||
FOOD = "5448e8d04bdc2ddf718b4569",
|
||||
DRINK = "5448e8d64bdc2dce718b4568",
|
||||
BARTER_ITEM = "5448eb774bdc2d0a728b4567",
|
||||
INFO = "5448ecbe4bdc2d60728b4568",
|
||||
MEDKIT = "5448f39d4bdc2d0a728b4568",
|
||||
DRUGS = "5448f3a14bdc2d27728b4569",
|
||||
STIMULATOR = "5448f3a64bdc2d60728b456a",
|
||||
MEDICAL = "5448f3ac4bdc2dce718b4569",
|
||||
MEDICAL_SUPPLIES = "57864c8c245977548867e7f1",
|
||||
MOD = "5448fe124bdc2da5018b4567",
|
||||
FUNCTIONAL_MOD = "550aa4154bdc2dd8348b456b",
|
||||
FUEL = "5d650c3e815116009f6201d2",
|
||||
GEAR_MOD = "55802f3e4bdc2de7118b4584",
|
||||
STOCK = "55818a594bdc2db9688b456a",
|
||||
FOREGRIP = "55818af64bdc2d5b648b4570",
|
||||
MASTER_MOD = "55802f4a4bdc2ddb688b4569",
|
||||
MOUNT = "55818b224bdc2dde698b456f",
|
||||
MUZZLE = "5448fe394bdc2d0d028b456c",
|
||||
SIGHTS = "5448fe7a4bdc2d6f028b456b",
|
||||
MEDS = "543be5664bdc2dd4348b4569",
|
||||
MONEY = "543be5dd4bdc2deb348b4569",
|
||||
NIGHTVISION = "5a2c3a9486f774688b05e574",
|
||||
THEMALVISION = "5d21f59b6dbe99052b54ef83",
|
||||
KEY = "543be5e94bdc2df1348b4568",
|
||||
KEY_MECHANICAL = "5c99f98d86f7745c314214b3",
|
||||
KEYCARD = "5c164d2286f774194c5e69fa",
|
||||
EQUIPMENT = "543be5f84bdc2dd4348b456a",
|
||||
THROW_WEAPON = "543be6564bdc2df4348b4568",
|
||||
FOOD_DRINK = "543be6674bdc2df1348b4569",
|
||||
PISTOL = "5447b5cf4bdc2d65278b4567",
|
||||
SMG = "5447b5e04bdc2d62278b4567",
|
||||
ASSAULT_RIFLE = "5447b5f14bdc2d61278b4567",
|
||||
ASSAULT_CARBINE = "5447b5fc4bdc2d87278b4567",
|
||||
SHOTGUN = "5447b6094bdc2dc3278b4567",
|
||||
MARKSMAN_RIFLE = "5447b6194bdc2d67278b4567",
|
||||
SNIPER_RIFLE = "5447b6254bdc2dc3278b4568",
|
||||
MACHINE_GUN = "5447bed64bdc2d97278b4568",
|
||||
GRENADE_LAUNCHER = "5447bedf4bdc2d87278b4568",
|
||||
SPECIAL_WEAPON = "5447bee84bdc2dc3278b4569",
|
||||
SPEC_ITEM = "5447e0e74bdc2d3c308b4567",
|
||||
KNIFE = "5447e1d04bdc2dff2f8b4567",
|
||||
AMMO = "5485a8684bdc2da71d8b4567",
|
||||
AMMO_BOX = "543be5cb4bdc2deb348b4568",
|
||||
LOOT_CONTAINER = "566965d44bdc2d814c8b4571",
|
||||
MOD_CONTAINER = "5448bf274bdc2dfc2f8b456a",
|
||||
SEARCHABLE_ITEM = "566168634bdc2d144c8b456c",
|
||||
STASH = "566abbb64bdc2d144c8b457d",
|
||||
SORTING_TABLE = "6050cac987d3f925bf016837",
|
||||
LOCKABLE_CONTAINER = "5671435f4bdc2d96058b4569",
|
||||
SIMPLE_CONTAINER = "5795f317245977243854e041",
|
||||
INVENTORY = "55d720f24bdc2d88028b456d",
|
||||
STATIONARY_CONTAINER = "567583764bdc2d98058b456e",
|
||||
POCKETS = "557596e64bdc2dc2118b4571",
|
||||
ARMBAND = "5b3f15d486f77432d0509248",
|
||||
DOG_TAG_USEC = "59f32c3b86f77472a31742f0",
|
||||
DOG_TAG_BEAR = "59f32bb586f774757e1e8442",
|
||||
JEWELRY = "57864a3d24597754843f8721",
|
||||
ELECTRONICS = "57864a66245977548f04a81f",
|
||||
BUILDING_MATERIAL = "57864ada245977548638de91",
|
||||
TOOL = "57864bb7245977548b3b66c2",
|
||||
HOUSEHOLD_GOODS = "57864c322459775490116fbf",
|
||||
LUBRICANT = "57864e4c24597754843f8723",
|
||||
BATTERY = "57864ee62459775490116fc1",
|
||||
ASSAULT_SCOPE = "55818add4bdc2d5b648b456f",
|
||||
TACTICAL_COMBO = "55818b164bdc2ddc698b456c",
|
||||
FLASHLIGHT = "55818b084bdc2d5b648b4571",
|
||||
MAGAZINE = "5448bc234bdc2d3c308b4569",
|
||||
LIGHT_LASER = "55818b0e4bdc2dde698b456e",
|
||||
FLASH_HIDER = "550aa4bf4bdc2dd6348b456b",
|
||||
COLLIMATOR = "55818ad54bdc2ddc698b4569",
|
||||
COMPACT_COLLIMATOR = "55818acf4bdc2dde698b456b",
|
||||
COMPENSATOR = "550aa4af4bdc2dd4348b456e",
|
||||
OPTIC_SCOPE = "55818ae44bdc2dde698b456c",
|
||||
SPECIAL_SCOPE = "55818aeb4bdc2ddc698b456a",
|
||||
OTHER = "590c745b86f7743cc433c5f2",
|
||||
SILENCER = "550aa4cd4bdc2dd8348b456c",
|
||||
PORTABLE_RANGE_FINDER = "61605ddea09d851a0a0c1bbc",
|
||||
ITEM = "54009119af1c881c07000029",
|
||||
CYLINDER_MAGAZINE = "610720f290b75a49ff2e5e25",
|
||||
MAP = "567849dd4bdc2d150f8b456e",
|
||||
REPAIRKITS = "616eb7aea207f41933308f46",
|
||||
COMPASS = "5f4fbaaca5573a5ac31db429",
|
||||
HEADSET = "5645bcb74bdc2ded0b8b4578",
|
||||
GASBLOCK = "56ea9461d2720b67698b456f"
|
||||
}
|
||||
|
||||
export const enum Calibers {
|
||||
_9x19mm = "Caliber9x19PARA",
|
||||
_9x18mm = "Caliber9x18PM",
|
||||
_9x21mm = "Caliber9x21",
|
||||
_9x39mm = "Caliber9x39",
|
||||
_45ACP = "Caliber1143x23ACP",
|
||||
_46x30mm = "Caliber46x30",
|
||||
_57x28mm = "Caliber57x28",
|
||||
_762x25mm = "Caliber762x25TT",
|
||||
_366TKM = "Caliber366TKM",
|
||||
_762x39mm = "Caliber762x39",
|
||||
_762x51mm = "Caliber762x51",
|
||||
_762x54rmm = "Caliber762x54R",
|
||||
_300BLK = "Caliber762x35",
|
||||
_556x45mm = "Caliber556x45NATO",
|
||||
_545x39mm = "Caliber545x39",
|
||||
_127x55mm = "Caliber127x55",
|
||||
_338mag = "Caliber86x70",
|
||||
_357mag = "Caliber9x33R",
|
||||
_127x108mm = "Caliber127x108",
|
||||
_40x46mm = "Caliber40x46",
|
||||
_40x53mm = "Caliber40mmRU",
|
||||
_26x75mm = "Caliber26x75",
|
||||
_12ga = "Caliber12g",
|
||||
_20ga = "Caliber20g",
|
||||
_23x75mm = "Caliber23x75"
|
||||
}
|
||||
95
user/mods/Skwizzy-LootingBots-ServerMod/src/mod.ts
Normal file
95
user/mods/Skwizzy-LootingBots-ServerMod/src/mod.ts
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
import { DependencyContainer } from "tsyringe";
|
||||
|
||||
import { IPostDBLoadMod } from "@spt/models/external/IPostDBLoadMod";
|
||||
import { DatabaseServer } from "@spt/servers/DatabaseServer";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { IPmcConfig } from "@spt/models/spt/config/IPmcConfig";
|
||||
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
|
||||
|
||||
|
||||
import config from "../config/config.json";
|
||||
|
||||
class DisableDiscardLimits implements IPostDBLoadMod {
|
||||
public postDBLoad(container: DependencyContainer): void {
|
||||
const databaseServer = container.resolve<DatabaseServer>("DatabaseServer");
|
||||
const configServer = container.resolve<ConfigServer>("ConfigServer");
|
||||
const pmcConfig = configServer.getConfig<IPmcConfig>(ConfigTypes.PMC);
|
||||
const botConfig = configServer.getConfig<IBotConfig>(ConfigTypes.BOT);
|
||||
|
||||
const { logInfo } = useLogger(container);
|
||||
|
||||
const tables = databaseServer.getTables();
|
||||
|
||||
/**
|
||||
* Set the item generation weights for backpackLoot, vestLoot, and pocketLoot to zero to prevent extra loot items from spawning on the specified bot type
|
||||
* @param botTypes
|
||||
*/
|
||||
const emptyInventory = (botTypes: string[]) => {
|
||||
botTypes.forEach((type) => {
|
||||
logInfo(`Removing loot from ${type}`);
|
||||
const backpackWeights = tables.bots.types[type].generation.items.backpackLoot.weights;
|
||||
const vestWeights = tables.bots.types[type].generation.items.vestLoot.weights;
|
||||
const pocketWeights = tables.bots.types[type].generation.items.pocketLoot.weights;
|
||||
|
||||
clearWeights(backpackWeights);
|
||||
clearWeights(vestWeights);
|
||||
clearWeights(pocketWeights);
|
||||
});
|
||||
};
|
||||
|
||||
if (!config.pmcSpawnWithLoot) {
|
||||
emptyInventory(["usec", "bear"]);
|
||||
// Do not allow weapons to spawn in PMC bags
|
||||
pmcConfig.looseWeaponInBackpackLootMinMax.max = 0;
|
||||
|
||||
// Clear weights in pmc randomisation
|
||||
botConfig.equipment?.pmc?.randomisation?.forEach(details => {
|
||||
const generation = details?.generation;
|
||||
clearWeights(generation?.backpackLoot?.weights);
|
||||
clearWeights(generation?.pocketLoot?.weights);
|
||||
clearWeights(generation?.vestLoot?.weights);
|
||||
});
|
||||
}
|
||||
|
||||
if (!config.scavSpawnWithLoot) {
|
||||
emptyInventory(["assault"]);
|
||||
}
|
||||
|
||||
logInfo("Marking items with DiscardLimits as InsuranceDisabled");
|
||||
for (let itemId in tables.templates.items) {
|
||||
const template = tables.templates.items[itemId];
|
||||
/**
|
||||
* When we set DiscardLimitsEnabled to false further down, this will cause some items to be able to be insured when they normally should not be.
|
||||
* The DiscardLimit property is used by BSG for RMT protections and their code internally treats things with discard limits as not insurable.
|
||||
* For items that have a DiscardLimit >= 0, we need to manually flag them as InsuranceDisabled to make sure they still cannot be insured by the player.
|
||||
* Do not disable insurance if the item is marked as always available for insurance.
|
||||
*/
|
||||
if (
|
||||
template._props.DiscardLimit >= 0 &&
|
||||
!template._props.IsAlwaysAvailableForInsurance
|
||||
) {
|
||||
template._props.InsuranceDisabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
tables.globals.config.DiscardLimitsEnabled = false;
|
||||
logInfo("Global config DiscardLimitsEnabled set to false");
|
||||
}
|
||||
}
|
||||
|
||||
function clearWeights(weights: Record<string, number> = {}) {
|
||||
Object.keys(weights).forEach(weight => weights[weight] = 0);
|
||||
}
|
||||
|
||||
function useLogger(container: DependencyContainer) {
|
||||
const logger = container.resolve<ILogger>("WinstonLogger");
|
||||
return {
|
||||
logInfo: (message: string) => {
|
||||
logger.info(`[LootingBots-ServerMod] ${message}`);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { mod: new DisableDiscardLimits() };
|
||||
Loading…
Add table
Add a link
Reference in a new issue