This commit is contained in:
GetParanoid 2025-07-18 16:25:09 -05:00
parent 57c563a139
commit 3755d6e2a6
22 changed files with 1570 additions and 0 deletions

View file

@ -0,0 +1,413 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const itemTemplate = require("../templates/item_template.json");
const configJson = require("../config.json");
const modTGC_items_json_1 = __importDefault(require("../database/modTGC_items.json"));
const modTGC_clothes_json_1 = __importDefault(require("../database/modTGC_clothes.json"));
const globals_json_1 = __importDefault(require("../database/globals.json"));
const assort_json_1 = __importDefault(require("../database/traders/668aaff35fd574b6dcc4a686/assort.json"));
const suits_json_1 = __importDefault(require("../database/traders/668aaff35fd574b6dcc4a686/suits.json"));
class TGCItems {
db;
mydb;
logger;
jsonUtil;
async postDBLoad(container) {
this.logger = container.resolve("WinstonLogger");
this.jsonUtil = container.resolve("JsonUtil");
const databaseServer = container.resolve("DatabaseServer");
const modLoader = container.resolve("PreSptModLoader");
//Mod Info
const modFolderName = "MoxoPixel-TacticalGearComponent";
const modFullName = "Tactical Gear Component";
//Trader IDs
const traders = {
"PAINTERSHOP": "668aaff35fd574b6dcc4a686"
};
//Currency IDs
const currencies = {
"roubles": "5449016a4bdc2d6f028b456f",
"dollars": "5696686a4bdc2da3298b456a",
"euros": "569668774bdc2da2298b4568",
"bitcoin": "59faff1d86f7746c51718c9c",
"gp": "5d235b4d86f7742e017bc88a"
};
//Get the server database and our custom database
this.db = databaseServer.getTables();
this.mydb = {
modTgcItems: modTGC_items_json_1.default,
modTgcClothes: modTGC_clothes_json_1.default,
globals: globals_json_1.default,
traders: {
"668aaff35fd574b6dcc4a686": {
assort: assort_json_1.default,
suits: suits_json_1.default
}
}
};
this.logger.info("Loading: " + modFullName);
const secureContainerIds = [
"665ee77ccf2d642e98220bca",
"5857a8bc2459772bad15db29",
"64f6f4c5911bcdfe8b03b0dc",
"544a11ac4bdc2d470e8b456a",
"5857a8b324597729ab0a0e7d",
"59db794186f77448bc595262",
"664a55d84a90fc2c8a6305c9",
"5c093ca986f7740a1867ab12",
"676008db84e242067d0dc4c9"
];
const armbandId = "55d7217a4bdc2d86028b456d";
//Items
if (this.mydb.modTgcItems && typeof this.mydb.modTgcItems === "object" && Object.keys(this.mydb.modTgcItems).length > 0) {
for (const [modTGCID, modTGCItem] of Object.entries(this.mydb.modTgcItems)) {
//Items + Handbook
if (typeof modTGCItem === 'object' && "clone" in modTGCItem) {
this.cloneItem(modTGCItem.clone, modTGCID);
this.copyToFilters(modTGCItem.clone, modTGCID);
if ("PutInArmband" in modTGCItem && this.db.templates.items[armbandId]) {
this.db.templates.items[armbandId]._props.Slots[14]._props.filters[0].Filter.push(modTGCID);
}
if (configJson.PouchesInSecureContainer && "putInSecureContainer" in modTGCItem) {
for (const id of secureContainerIds) {
const item = this.db.templates.items[id];
if (item && item._props && item._props.Grids && item._props.Grids[0] && item._props.Grids[0]._props && item._props.Grids[0]._props.filters && item._props.Grids[0]._props.filters[0] && item._props.Grids[0]._props.filters[0].Filter) {
item._props.Grids[0]._props.filters[0].Filter.push(modTGCID);
}
}
}
}
else
this.createItem(modTGCID);
//Locales (Languages)
this.addLocales(modTGCID, modTGCItem);
}
}
else {
this.logger.warning("modTgcItems is missing or not an object in the mod database.");
}
//Item Filters
if (this.mydb.modTgcItems && typeof this.mydb.modTgcItems === "object" && Object.keys(this.mydb.modTgcItems).length > 0) {
for (const modTGCID in this.mydb.modTgcItems)
this.addToFilters(modTGCID);
}
//Clothing
if (this.mydb.modTgcClothes && typeof this.mydb.modTgcClothes === "object" && Object.keys(this.mydb.modTgcClothes).length > 0) {
for (const [modTGCID, modTGCArticle] of Object.entries(this.mydb.modTgcClothes)) {
//Articles + Handbook
if (typeof modTGCArticle === 'object' && "clone" in modTGCArticle) {
this.cloneClothing(modTGCArticle.clone, modTGCID);
}
//Locales (Languages)
this.addLocales(modTGCID, undefined, modTGCArticle);
}
}
else {
this.logger.warning("modTgcClothes is missing or not an object in the mod database.");
}
//Presets
if (this.mydb.globals && this.mydb.globals.ItemPresets) {
for (const preset in this.mydb.globals.ItemPresets) {
this.db.globals.ItemPresets[preset] = this.mydb.globals.ItemPresets[preset];
}
}
else {
this.logger.warning("modTGC: globals.ItemPresets is missing in the mod database.");
}
//Traders
for (const trader in traders) {
if (this.mydb.traders[traders[trader]] && this.mydb.traders[traders[trader]].suits) {
this.addTraderSuits(traders[trader]);
}
else {
this.logger.warning(`No suits for trader ${trader}`);
}
if (this.mydb.traders[traders[trader]] && this.mydb.traders[traders[trader]].assort) {
this.addTraderAssort(traders[trader]);
}
else {
this.logger.warning(`No assort for trader ${trader}`);
}
}
}
cloneItem(itemToClone, modTGCID) {
//If the item is enabled in the json
if (this.mydb.modTgcItems[modTGCID].enable == true) {
//Get a clone of the original item from the database
let modTGCItemOut = this.jsonUtil.clone(this.db.templates.items[itemToClone]);
//Change the necessary item attributes using the info in our database file modTgcItems.json
modTGCItemOut._id = modTGCID;
modTGCItemOut = this.compareAndReplace(modTGCItemOut, this.mydb.modTgcItems[modTGCID]["item"]);
//Add the new item to the database
this.db.templates.items[modTGCID] = modTGCItemOut;
//Create the handbook entry for the items
const handbookEntry = {
"Id": modTGCID,
"ParentId": this.mydb.modTgcItems[modTGCID]["handbook"]["ParentId"],
"Price": this.mydb.modTgcItems[modTGCID]["handbook"]["Price"]
};
//Add the handbook entry to the database
this.db.templates.handbook.Items.push(handbookEntry);
}
}
createItem(itemToCreate) {
//Create an item from scratch instead of cloning it
//Requires properly formatted entry in modTgcItems.json with NO "clone" attribute
//Get the new item object from the json
const newItem = this.mydb.modTgcItems[itemToCreate];
//If the item is enabled in the json
if (newItem.enable) {
//Check the structure of the new item in modTgcItems
const [pass, checkedItem] = this.checkItem(newItem);
if (!pass)
return;
//Add the new item to the database
this.db.templates.items[itemToCreate] = checkedItem;
//Create the handbook entry for the items
const handbookEntry = {
"Id": itemToCreate,
"ParentId": newItem["handbook"]["ParentId"],
"Price": newItem["handbook"]["Price"]
};
//Add the handbook entry to the database
this.db.templates.handbook.Items.push(handbookEntry);
}
}
checkItem(itemToCheck) {
let pass = true;
for (const level1 in itemTemplate) {
if (itemTemplate.hasOwnProperty(level1) && !(level1 in itemToCheck.item)) {
this.logger.error("ERROR - Missing attribute: \"" + level1 + "\" in your item entry!");
pass = false;
}
}
for (const prop in itemToCheck.item._props) {
if (itemToCheck.item._props.hasOwnProperty(prop) && !(prop in itemTemplate._props)) {
this.logger.warning("WARNING - Attribute: \"" + prop + "\" not found in item template!");
}
}
const itemOUT = {
"_id": itemToCheck.item._id,
"_name": itemToCheck.item._name,
"_parent": itemToCheck.item._parent,
"_props": itemToCheck.item._props,
"_type": itemToCheck.item._type,
"_proto": itemToCheck.item._proto
};
return [pass, itemOUT];
}
compareAndReplace(originalItem, attributesToChange) {
for (const key in attributesToChange) {
if (attributesToChange.hasOwnProperty(key)) {
if ((["boolean", "string", "number"].includes(typeof attributesToChange[key])) || Array.isArray(attributesToChange[key])) {
if (key in originalItem) {
originalItem[key] = attributesToChange[key];
}
else {
this.logger.warning("(Item: " + originalItem._id + ") WARNING: Could not find the attribute: \"" + key + "\" in the original item, make sure this is intended!");
originalItem[key] = attributesToChange[key];
}
}
else {
originalItem[key] = this.compareAndReplace(originalItem[key], attributesToChange[key]);
}
}
}
return originalItem;
}
getFilters(item) {
//Get the slots, chambers, cartridges, and conflicting items objects and return them.
const slots = (typeof this.db.templates.items[item]._props.Slots === "undefined") ? [] : this.db.templates.items[item]._props.Slots;
const chambers = (typeof this.db.templates.items[item]._props.Chambers === "undefined") ? [] : this.db.templates.items[item]._props.Chambers;
const cartridges = (typeof this.db.templates.items[item]._props.Cartridges === "undefined") ? [] : this.db.templates.items[item]._props.Cartridges;
const filters = slots.concat(chambers, cartridges);
const conflictingItems = (typeof this.db.templates.items[item]._props.ConflictingItems === "undefined") ? [] : this.db.templates.items[item]._props.ConflictingItems;
return [filters, conflictingItems];
}
copyToFilters(itemClone, modTGCID) {
//Find the original item in all compatible and conflict filters and add the clone to those filters as well
for (const item in this.db.templates.items) {
if (item in this.mydb.modTgcItems)
continue;
const [filters, conflictingItems] = this.getFilters(item);
for (const filter of filters) {
for (const id of filter._props.filters[0].Filter) {
if (id === itemClone)
filter._props.filters[0].Filter.push(modTGCID);
}
}
for (const conflictID of conflictingItems)
if (conflictID === itemClone)
conflictingItems.push(modTGCID);
}
}
addToFilters(modTGCID) {
//Add a new item to compatibility & conflict filters of pre-existing items
//Add additional compatible and conflicting items to new item filters (manually adding more than the ones that were cloned)
const modTGCNewItem = this.mydb.modTgcItems[modTGCID];
//If the item is enabled in the json
if (modTGCNewItem.enable) {
this.logger.debug("addToFilters: " + modTGCID);
//Manually add items into an THISMOD item's filters
if ("addToThisItemsFilters" in modTGCNewItem) {
const modTGCItemFilters = this.getFilters(modTGCID)[0];
let modTGCConflictingItems = this.getFilters(modTGCID)[1];
for (const modSlotName in modTGCNewItem.addToThisItemsFilters) {
if (modSlotName === "conflicts")
modTGCConflictingItems = modTGCConflictingItems.concat(modTGCNewItem.addToThisItemsFilters.conflicts);
else {
for (const filter in modTGCItemFilters) {
if (modSlotName === modTGCItemFilters[filter]._name) {
const slotFilter = modTGCItemFilters[filter]._props.filters[0].Filter;
const newFilter = slotFilter.concat(modTGCNewItem.addToThisItemsFilters[modSlotName]);
modTGCItemFilters[filter]._props.filters[0].Filter = newFilter;
}
}
}
}
}
//Manually add THISMOD items to pre-existing item filters.
if ("addToExistingItemFilters" in modTGCNewItem) {
for (const modSlotName in modTGCNewItem.addToExistingItemFilters) {
if (modSlotName === "conflicts") {
for (const conflictingItem of modTGCNewItem.addToExistingItemFilters[modSlotName]) {
const conflictingItems = this.getFilters(conflictingItem)[1];
conflictingItems.push(modTGCID);
}
}
else {
for (const compatibleItem of modTGCNewItem.addToExistingItemFilters[modSlotName]) {
const filters = this.getFilters(compatibleItem)[0];
for (const filter of filters) {
if (modSlotName === filter._name)
filter._props.filters[0].Filter.push(modTGCID);
}
}
}
}
}
}
}
cloneClothing(itemToClone, modTGCID) {
if (this.mydb.modTgcClothes[modTGCID].enable || !("enable" in this.mydb.modTgcClothes[modTGCID])) {
//Get a clone of the original item from the database
let tgcClothingOut = this.jsonUtil.clone(this.db.templates.customization[itemToClone]);
//Change the necessary clothing item attributes using the info in our database file modTgcClothes.json
tgcClothingOut._id = modTGCID;
tgcClothingOut._name = modTGCID;
tgcClothingOut = this.compareAndReplace(tgcClothingOut, this.mydb.modTgcClothes[modTGCID]["customization"]);
//Add the new item to the database
this.db.templates.customization[modTGCID] = tgcClothingOut;
this.logger.debug("Clothing item " + modTGCID + " created as a clone of " + itemToClone + " and added to database.");
}
}
addTraderAssort(trader) {
if (this.mydb.traders[trader] &&
this.mydb.traders[trader].assort &&
this.db.traders[trader] &&
this.db.traders[trader].assort) {
// Merge items
if (Array.isArray(this.mydb.traders[trader].assort.items)) {
for (const item of this.mydb.traders[trader].assort.items) {
this.db.traders[trader].assort.items.push(item);
}
}
// Merge barter_scheme
if (typeof this.mydb.traders[trader].assort.barter_scheme === "object") {
Object.assign(this.db.traders[trader].assort.barter_scheme, this.mydb.traders[trader].assort.barter_scheme);
}
// Merge loyal_level_items
if (typeof this.mydb.traders[trader].assort.loyal_level_items === "object") {
Object.assign(this.db.traders[trader].assort.loyal_level_items, this.mydb.traders[trader].assort.loyal_level_items);
}
}
else {
this.logger.warning(`Trader ${trader} does not exist in SPT database or has no assort property. Cannot add assort.`);
}
}
addTraderSuits(trader) {
// Only do anything if a suits.json file is included for trader in this mod
if (this.mydb.traders[trader] &&
typeof this.mydb.traders[trader].suits !== "undefined" &&
this.db.traders[trader] &&
this.db.traders[trader].base) {
// Enable customization for that trader
this.db.traders[trader].base.customization_seller = true;
// Create the suits array if it doesn't already exist in SPT database so we can push to it
if (typeof this.db.traders[trader].suits === "undefined")
this.db.traders[trader].suits = [];
// Push all suits
for (const suit of this.mydb.traders[trader].suits)
this.db.traders[trader].suits.push(suit);
}
else {
this.logger.warning(`Trader ${trader} does not exist in SPT database or has no base property. Cannot add suits.`);
}
}
addLocales(modTGCID, modTGCItem, modTGCArticle) {
const name = modTGCID + " Name";
const shortname = modTGCID + " ShortName";
const description = modTGCID + " Description";
const isItem = typeof modTGCItem !== "undefined";
const modTGCEntry = isItem ? modTGCItem : modTGCArticle;
for (const localeID in this.db.locales.global) //For each possible locale/language in SPT's database
{
let localeEntry;
if (isItem && "locales" in modTGCEntry) {
if (localeID in modTGCEntry.locales) //If the language is entered in modTgcItems, use that
{
localeEntry = {
"Name": modTGCEntry.locales[localeID].Name,
"ShortName": modTGCEntry.locales[localeID].ShortName,
"Description": modTGCEntry.locales[localeID].Description
};
}
else //Otherwise use english as the default
{
localeEntry = {
"Name": modTGCEntry.locales.en.Name,
"ShortName": modTGCEntry.locales.en.ShortName,
"Description": modTGCEntry.locales.en.Description
};
}
this.db.locales.global[localeID][name] = localeEntry.Name;
this.db.locales.global[localeID][shortname] = localeEntry.ShortName;
this.db.locales.global[localeID][description] = localeEntry.Description;
}
else if (!isItem && "locales" in modTGCEntry) {
const locales = modTGCEntry.locales;
if (localeID in locales) {
localeEntry = {
"Name": locales[localeID].Name,
"Description": locales[localeID].Description || ""
};
}
else {
localeEntry = {
"Name": locales.en.Name,
"Description": locales.en.Description || ""
};
}
this.db.locales.global[localeID][name] = localeEntry.Name;
this.db.locales.global[localeID][description] = localeEntry.Description;
}
else {
if (isItem)
this.logger.warning("WARNING: Missing locale entry for item: " + modTGCID);
else
this.logger.debug("No locale entries for item/clothing: " + modTGCID);
}
//Also add the necessary preset locale entries if they exist
if (isItem && modTGCItem.presets) {
for (const preset in modTGCItem.presets) {
this.db.locales.global[localeID][preset] = modTGCItem.presets[preset];
}
}
}
}
}
module.exports = { mod: new TGCItems() };
//# sourceMappingURL=mod.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,438 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CustomItemsManager = void 0;
const ConfigTypes_1 = require("C:/snapshot/project/obj/models/enums/ConfigTypes");
/**
* Manages creation of custom items for the Painter mod
*/
class CustomItemsManager {
logger;
constructor(logger) {
this.logger = logger;
}
/**
* Create all custom items for the Painter mod
*/
createCustomItems(customItemService, configServer, tables, inventoryConfig, enableLootBoxes) {
// Create figurines
this.createFigurines(customItemService, configServer, tables);
// Create loot boxes if enabled
if (enableLootBoxes) {
this.createLootBoxes(customItemService, tables, inventoryConfig);
}
}
/**
* Create Batman and Golden Turd figurines
*/
createFigurines(customItemService, configServer, tables) {
const batmanFigurine = {
itemTplToClone: "655c67782a1356436041c9c5",
overrideProperties: {
Name: "Batman figurine",
ShortName: "Batman",
Description: "Rare larger figurine of Batman, a superhero of the American comic book publisher DC Comics, Batman.",
Prefab: {
"path": "figurine_batman.bundle",
"rcid": ""
},
CanRequireOnRagfair: false,
CanSellOnRagfair: true
},
parentId: "57864a3d24597754843f8721",
newId: "672e2e75d78fe9e90c8cb393",
fleaPriceRoubles: 154000,
handbookPriceRoubles: 154000,
handbookParentId: "5b47574386f77428ca22b2f1",
locales: {
en: {
name: "Batman figurine",
shortName: "Batman",
description: "Rare larger figurine of Batman, a superhero of the American comic book publisher DC Comics, Batman."
}
}
};
const dodoFigurine = {
itemTplToClone: "59e3647686f774176a362507",
overrideProperties: {
Name: "Golden Turd figurine",
ShortName: "Turd",
Description: "Awarded to the master of annoying tasks, it is said that it was made from the golden poop of a dodo bird.",
Prefab: {
"path": "dodo338383899.bundle",
"rcid": ""
},
CanRequireOnRagfair: false,
CanSellOnRagfair: false,
Weight: 69,
ExaminedByDefault: false
},
parentId: "57864a3d24597754843f8721",
newId: "684db00229850b2f1f7832c1",
fleaPriceRoubles: 69,
handbookPriceRoubles: 69,
handbookParentId: "5b47574386f77428ca22b2f1",
locales: {
en: {
name: "Golden Turd figurine",
shortName: "Turd",
description: "Awarded to the master of annoying tasks, it is said that it was made from the golden poop of a dodo bird."
}
}
};
const mosFigurine = {
itemTplToClone: "59e3647686f774176a362507",
overrideProperties: {
Name: "Moscovium (Material 115)",
ShortName: "MC-115",
Description: "Sealed compound made from Moscovium, a synthetic element with atomic number 115, known for its unique properties. Does it bend space and time? Who knows.",
Prefab: {
"path": "mos115.bundle",
"rcid": ""
},
CanRequireOnRagfair: false,
CanSellOnRagfair: false,
Weight: 69,
ExaminedByDefault: false
},
parentId: "57864a3d24597754843f8721",
newId: "685867727d49afb420c2b29e",
fleaPriceRoubles: 69,
handbookPriceRoubles: 69,
handbookParentId: "5b47574386f77428ca22b2f1",
locales: {
en: {
name: "Moscovium (Material 115)",
shortName: "MC-115",
description: "Sealed compound made from Moscovium, a synthetic element with atomic number 115, known for its unique properties. Does it bend space and time? Who knows."
}
}
};
customItemService.createItemFromClone(batmanFigurine);
customItemService.createItemFromClone(dodoFigurine);
customItemService.createItemFromClone(mosFigurine);
this.logger.info("Painter custom items added");
// Add figurines to Hall of Fame
this.addToHallOfFame(tables, "672e2e75d78fe9e90c8cb393", "655c67782a1356436041c9c5", "Batman figurine");
this.addToHallOfFame(tables, "684db00229850b2f1f7832c1", "59e3647686f774176a362507", "Golden Turd figurine");
this.addToHallOfFame(tables, "685867727d49afb420c2b29e", "59e3647686f774176a362507", "Moscovium (Material 115)");
// Prevent dodoFigurine from being lootable
this.preventDodoFromBeingLootable(configServer);
this.preventMosFromBeingLootable(configServer);
}
/**
* Create mystery loot boxes
*/
createLootBoxes(customItemService, tables, inventoryConfig) {
const mysteryBoxOne = {
itemTplToClone: "6489b2b131a2135f0d7d0fcb",
overrideProperties: {
Name: "Painter's Special Delivery",
ShortName: "Painter Lootbox",
Description: "A lootbox filled with various items, including some of the most sought after barter items.",
Weight: 25,
Prefab: {
"path": "mysterybox.bundle",
"rcid": ""
},
Width: 4,
Height: 4,
BackgroundColor: "blue",
CanRequireOnRagfair: false,
CanSellOnRagfair: false
},
parentId: "62f109593b54472778797866",
newId: "668ff5bde41a0cce3b142464",
fleaPriceRoubles: 500000,
handbookPriceRoubles: 500000,
handbookParentId: "5b5f6fa186f77409407a7eb7",
locales: {
en: {
name: "Painter's Special Delivery",
shortName: "Painter Lootbox",
description: "A lootbox filled with 20 items, including some of the most sought after barter items. Get a LEDX or go broke. The choise is yours."
}
}
};
customItemService.createItemFromClone(mysteryBoxOne);
// Change item _name to remove it from the *actual* sealed weapon crate logic, this removes it from airdrops and allows easier access to change the contents
const customIteminDB = tables.templates.items["668ff5bde41a0cce3b142464"];
customIteminDB._name = "668ff5bde41a0cce3b142464";
// Configure loot pool for mystery box
this.configureMysteryBoxLoot(inventoryConfig);
const mysteryBoxTwo = {
itemTplToClone: "6489981f7063b903ff4b8565",
overrideProperties: {
Name: "Painter's War Box",
ShortName: "Painter Warbox",
Description: "A lootbox filled with various items, some of the most sought after military items.",
Weight: 30,
Prefab: {
"path": "mysterybox_2.bundle",
"rcid": ""
},
Width: 4,
Height: 3,
BackgroundColor: "blue",
CanRequireOnRagfair: false,
CanSellOnRagfair: false
},
parentId: "62f109593b54472778797866",
newId: "6699546547ad52e0fccf6da9",
fleaPriceRoubles: 500000,
handbookPriceRoubles: 500000,
handbookParentId: "5b5f6fa186f77409407a7eb7",
locales: {
en: {
name: "Painter's War Box",
shortName: "Painter Warbox",
description: "A lootbox filled with various items, some of the most sought after military items."
}
}
};
customItemService.createItemFromClone(mysteryBoxTwo);
this.logger.info("Painter loot boxes added");
}
/**
* Configure the mystery box loot pool with various high-value items
*/
configureMysteryBoxLoot(inventoryConfig) {
inventoryConfig.randomLootContainers["668ff5bde41a0cce3b142464"] = {
rewardCount: 20,
foundInRaid: true,
rewardTplPool: {
"5bc9be8fd4351e00334cae6e": 5,
"5d03794386f77420415576f5": 1,
"5672cb124bdc2d1a0f8b4568": 10,
"6389c85357baa773a825b356": 1,
"59faf98186f774067b6be103": 5,
"5d1b32c186f774252167a530": 5,
"590de71386f774347051a052": 5,
"590de7e986f7741b096e5f32": 5,
"573475fb24597737fb1379e1": 10,
"6389c6c7dbfd5e4b95197e68": 5,
"5e2af4d286f7746d4159f07a": 5,
"62a0a098de7ac8199358053b": 5,
"62a091170b9d3c46de5b6cf2": 5,
"5bc9c049d4351e44f824d360": 5,
"62a08f4c4f842e1bd12d9d62": 5,
"57347c5b245977448d35f6e1": 10,
"59e361e886f774176c10a2a5": 5,
"62a0a043cf4a99369e2624a5": 5,
"59e3606886f77417674759a5": 5,
"56742c324bdc2d150f8b456d": 10,
"5c1265fc86f7743f896a21c2": 5,
"5d1b309586f77425227d1676": 10,
"59e3639286f7741777737013": 1,
"619cbfeb6b8a1b37a54eebfa": 5,
"5c06779c86f77426e00dd782": 10,
"5e54f6af86f7742199090bf3": 5,
"5af0484c86f7740f02001f7f": 10,
"60391a8b3364dc22b04d0ce5": 5,
"62a09ee4cf4a99369e262453": 10,
"5c06782b86f77426df5407d2": 10,
"5733279d245977289b77ec24": 5,
"59e3658a86f7741776641ac4": 5,
"573474f924597738002c6174": 5,
"5c1267ee86f77416ec610f72": 5,
"57347b8b24597737dd42e192": 10,
"59e358a886f7741776641ac3": 5,
"590c2c9c86f774245b1f03f2": 10,
"5e2af41e86f774755a234b67": 5,
"59e35cbb86f7741778269d83": 5,
"5734779624597737e04bf329": 10,
"56742c284bdc2d98058b456d": 10,
"5e2aee0a86f774755a234b62": 5,
"590a386e86f77429692b27ab": 5,
"5bc9b9ecd4351e3bac122519": 5,
"5d1b3f2d86f774253763b735": 5,
"590a373286f774287540368b": 5,
"57347c1124597737fb1379e3": 10,
"5734781f24597737e04bf32a": 5,
"5672cb304bdc2dc2088b456a": 5,
"59e35de086f7741778269d84": 5,
"5d1b2fa286f77425227d1674": 5,
"6389c70ca33d8c4cdf4932c6": 5,
"590a3cd386f77436f20848cb": 10,
"5d1b371186f774253763a656": 5,
"6389c7f115805221fb410466": 1,
"63a0b208f444d32d6f03ea1e": 1,
"5bc9b355d4351e6d1509862a": 5,
"5d63d33b86f7746ea9275524": 10,
"5d4042a986f7743185265463": 10,
"5e2af47786f7746d404f3aaa": 5,
"5d1b2f3f86f774252167a52c": 1,
"5b43575a86f77424f443fe62": 5,
"590a3efd86f77437d351a25b": 5,
"590c595c86f7747884343ad7": 5,
"5672cb724bdc2dc2088b456b": 5,
"5bc9b720d4351e450201234b": 5,
"62a09cfe4f842e1bd12da3e4": 5,
"5734758f24597738025ee253": 5,
"5bc9bc53d4351e00367fbcee": 5,
"5d235a5986f77443f6329bc6": 5,
"57347ca924597744596b4e71": 1,
"5e2aedd986f7746d404f3aa4": 5,
"5d6fc78386f77449d825f9dc": 5,
"5d6fc87386f77449db3db94e": 5,
"590c5a7286f7747884343aea": 5,
"5d1b317c86f7742523398392": 5,
"573478bc24597738002c6175": 5,
"5e2af2bc86f7746d3f3c33fc": 5,
"5734795124597738002c6176": 10,
"5d0377ce86f774186372f689": 1,
"5e2af29386f7746d4159f077": 5,
"5c0530ee86f774697952d952": 1,
"5d1b392c86f77425243e98fe": 10,
"60b0f7057897d47c5b04ab94": 5,
"60b0f561c4449e4cb624c1d7": 5,
"590a391c86f774385a33c404": 5,
"573476d324597737da2adc13": 10,
"5b4335ba86f7744d2837a264": 5,
"619cc01e0a7c3a1a2731940c": 5,
"5d40419286f774318526545f": 10,
"5d1b36a186f7742523398433": 1,
"61bf7b6302b3924be92fa8c3": 10,
"6389c7750ef44505c87f5996": 1,
"5d0375ff86f774186372f685": 1,
"5d0376a486f7747d8050965c": 1,
"5c052f6886f7746b1e3db148": 1,
"619cbf476b8a1b37a54eebf8": 5,
"5d03784a86f774203e7e0c4d": 1,
"5d0378d486f77420421a5ff4": 1,
"5d40425986f7743185265461": 10,
"5d1b2ffd86f77425243e8d17": 10,
"5d0379a886f77420407aa271": 1,
"5bc9c377d4351e3bac12251b": 5,
"5af0534a86f7743b6f354284": 5,
"5d4041f086f7743cac3f22a7": 5,
"59e3556c86f7741776641ac2": 10,
"5e2af02c86f7746d420957d4": 10,
"590c31c586f774245e3141b2": 10,
"59e35ef086f7741777737012": 10,
"59e35abd86f7741778269d82": 5,
"59e3596386f774176c10a2a2": 5,
"5c12688486f77426843c7d32": 5,
"573477e124597737dd42e191": 10,
"5d03775b86f774203e7e0c4b": 1,
"5d1b313086f77425227d1678": 10,
"59faff1d86f7746c51718c9c": 1,
"59e366c186f7741778269d85": 10,
"5d1b3a5d86f774252167ba22": 5,
"619cbfccbedcde2f5b3f7bdd": 5,
"590c2b4386f77425357b6123": 10,
"5af04b6486f774195a3ebb49": 10,
"5c052e6986f7746b207bc3c9": 1,
"5af0561e86f7745f5f3ad6ac": 5,
"59e36c6f86f774176c10a2a7": 5,
"57347c2e24597744902c94a1": 5,
"5d1b327086f7742525194449": 5,
"62a09cb7a04c0c5c6e0a84f8": 5,
"590a3b0486f7743954552bdb": 1,
"577e1c9d2459773cd707c525": 5,
"59fafb5d86f774067a6f2084": 1,
"5d1c774f86f7746d6620f8db": 10,
"57347baf24597738002c6178": 10,
"60391afc25aff57af81f7085": 1,
"5e54f62086f774219b0f1937": 5,
"590a358486f77429692b2790": 5,
"5e2aef7986f7746d3f3c33f5": 5,
"5e2af4a786f7746d3f3c3400": 5,
"59faf7ca86f7740dbe19f6c2": 5,
"5d1b31ce86f7742523398394": 10,
"5d40412b86f7743cb332ac3a": 5,
"590c2d8786f774245b1f03f3": 10,
"57347c77245977448d35f6e2": 10,
"62a0a0bb621468534a797ad5": 5,
"61bf83814088ec1a363d7097": 5,
"590c35a486f774273531c822": 10,
"5d1b39a386f774252339976f": 10,
"5bc9bdb8d4351e003562b8a1": 5,
"5e2af00086f7746d3f3c33f7": 10,
"5c13cd2486f774072c757944": 10,
"590a3c0a86f774385a33c450": 10,
"5734770f24597738025ee254": 10,
"5e2af37686f774755a234b65": 10,
"5c12620d86f7743f8b198b72": 1,
"5c13cef886f774072e618e82": 10,
"590c2e1186f77425357b6124": 5,
"57347c93245977448d35f6e3": 10,
"60391b0fb847c71012789415": 5,
"57347cd0245977445a2d6ff1": 10,
"5e2af22086f7746d3f3c33fa": 10,
"5c052fb986f7746b2101e909": 1,
"590a3d9c86f774385926e510": 10,
"5909e99886f7740c983b9984": 10,
"5f745ee30acaeb0d490d8c5b": 5,
"5c05308086f7746b2101e90b": 1,
"5c05300686f7746dce784e5d": 1,
"5d1b385e86f774252167b98a": 5,
"590c5bbd86f774785762df04": 10,
"590c5c9f86f77477c91c36e7": 10,
"5d1c819a86f774771b0acd6c": 5,
"573476f124597737e04bf328": 10,
"59e3647686f774176a362507": 5,
"5d1b304286f774253763a528": 5,
"590c311186f77424d1667482": 5,
"590c346786f77423e50ed342": 10,
"56742c2e4bdc2d95058b456d": 10
}
};
}
/**
* Add custom figurines to Hall of Fame filters
*/
addToHallOfFame(tables, newItemId, originalItemId, itemName) {
const hallOfFame1 = tables.templates.items["63dbd45917fff4dee40fe16e"];
const hallOfFame2 = tables.templates.items["65424185a57eea37ed6562e9"];
const hallOfFame3 = tables.templates.items["6542435ea57eea37ed6562f0"];
const hallOfFames = [hallOfFame1, hallOfFame2, hallOfFame3];
let totalAdditions = 0;
hallOfFames.forEach((hall) => {
if (hall && hall._props && hall._props.Slots) {
let additionsThisHall = 0;
for (const slot of hall._props.Slots) {
if (slot._props && slot._props.filters) {
for (const filter of slot._props.filters) {
// Only add the new item if the original cloned item is already in this filter
if (filter.Filter && filter.Filter.includes(originalItemId) && !filter.Filter.includes(newItemId)) {
filter.Filter.push(newItemId);
additionsThisHall++;
totalAdditions++;
}
}
}
}
if (additionsThisHall > 0) {
this.logger.debug(`Added ${itemName} to ${additionsThisHall} slot(s) in ${hall._name}`);
}
}
});
if (totalAdditions > 0) {
this.logger.debug(`Successfully added ${itemName} (${newItemId}) to ${totalAdditions} total Hall of Fame slot(s)`);
}
else {
this.logger.debug(`WARNING: No Hall of Fame slots found for ${itemName} - original item ${originalItemId} may not be in any Hall of Fame filters`);
}
}
/**
* Prevent the Golden Turd figurine from being lootable
*/
preventDodoFromBeingLootable(configServer) {
const itemConfig = configServer.getConfig(ConfigTypes_1.ConfigTypes.ITEM);
const dodoFigurineId = "684db00229850b2f1f7832c1";
// Add to lootable item blacklist to prevent it from spawning in any loot containers or loose loot
if (!itemConfig.lootableItemBlacklist.includes(dodoFigurineId)) {
itemConfig.lootableItemBlacklist.push(dodoFigurineId);
}
}
preventMosFromBeingLootable(configServer) {
const itemConfig = configServer.getConfig(ConfigTypes_1.ConfigTypes.ITEM);
const mosFigurineId = "685867727d49afb420c2b29e";
// Add to lootable item blacklist to prevent it from spawning in any loot containers or loose loot
if (!itemConfig.lootableItemBlacklist.includes(mosFigurineId)) {
itemConfig.lootableItemBlacklist.push(mosFigurineId);
}
}
}
exports.CustomItemsManager = CustomItemsManager;
//# sourceMappingURL=CustomItemsManager.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,236 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const ConfigTypes_1 = require("C:/snapshot/project/obj/models/enums/ConfigTypes");
const Traders_1 = require("C:/snapshot/project/obj/models/enums/Traders");
const CustomItemsManager_1 = require("./CustomItemsManager");
const configJson = __importStar(require("../config.json"));
const baseJson = __importStar(require("../db/base.json"));
const assortJson = __importStar(require("../db/assort.json"));
const path = __importStar(require("path"));
const fs = __importStar(require("fs"));
const modPath = path.normalize(path.join(__dirname, ".."));
class PainterTrader {
mod;
logger;
configServer;
ragfairConfig;
constructor() {
this.mod = "aMoxoPixel-Painter";
}
preSptLoad(container) {
this.logger = container.resolve("WinstonLogger");
const PreSptModLoader = container.resolve("PreSptModLoader");
const imageRouter = container.resolve("ImageRouter");
const configServer = container.resolve("ConfigServer");
const traderConfig = configServer.getConfig(ConfigTypes_1.ConfigTypes.TRADER);
const questConfig = configServer.getConfig(ConfigTypes_1.ConfigTypes.QUEST);
if (!traderConfig.moddedTraders) {
traderConfig.moddedTraders = { clothingService: [] };
}
if (configJson.enableRepeatableQuests) {
const PainterRepeatQuests = {
traderId: "668aaff35fd574b6dcc4a686",
name: "painter",
questTypes: ["Completion", "Exploration", "Elimination"],
rewardBaseWhitelist: [
"543be6564bdc2df4348b4568",
"5448e5284bdc2dcb718b4567",
"5485a8684bdc2da71d8b4567",
"57864a3d24597754843f8721",
"55818af64bdc2d5b648b4570",
"57864e4c24597754843f8723",
"57864a66245977548f04a81f",
"57864ee62459775490116fc1",
"590c745b86f7743cc433c5f2"
],
rewardCanBeWeapon: true,
weaponRewardChancePercent: 20
};
questConfig.repeatableQuests[0].traderWhitelist.push(PainterRepeatQuests); // Daily quests
questConfig.repeatableQuests[1].traderWhitelist.push(PainterRepeatQuests); // Weekly quests
this.logger.info("Painter repeatable quests added to quest config");
}
this.registerProfileImage(PreSptModLoader, imageRouter);
this.setupTraderUpdateTime(traderConfig);
this.setupTraderServices(traderConfig);
Traders_1.Traders["668aaff35fd574b6dcc4a686"] = "668aaff35fd574b6dcc4a686";
}
postDBLoad(container) {
this.configServer = container.resolve("ConfigServer");
this.ragfairConfig = this.configServer.getConfig(ConfigTypes_1.ConfigTypes.RAGFAIR);
const configServer = container.resolve("ConfigServer");
const imageRouter = container.resolve("ImageRouter");
const jsonUtil = container.resolve("JsonUtil");
const databaseServer = container.resolve("DatabaseServer");
const databaseService = container.resolve("DatabaseService");
const customItem = container.resolve("CustomItemService");
const inventoryConfig = configServer.getConfig(ConfigTypes_1.ConfigTypes.INVENTORY);
const tables = databaseService.getTables();
if (configJson.enableRepeatableQuests) {
const repeatableQuests = databaseServer.getTables().templates.repeatableQuests;
const rqLocales = databaseServer.getTables().locales.global.en;
if (repeatableQuests.templates.Elimination) {
repeatableQuests.templates.Elimination.successMessageText = "A damn beast you are, hehe. Good work, here's your share.";
repeatableQuests.templates.Elimination.description = "I have a mission for you. I need you to eliminate some trash from Tarkov's streets. You up for it?";
}
if (repeatableQuests.templates.Completion) {
repeatableQuests.templates.Completion.successMessageText = "There you are! You got everything? Good stuff.";
repeatableQuests.templates.Completion.description = "I have a mission for you. I need you to gather some items for me. You up for it?";
}
if (repeatableQuests.templates.Exploration) {
repeatableQuests.templates.Exploration.successMessageText = "Marvelous, young man. Thank you for some fine work.";
repeatableQuests.templates.Exploration.description = "Ah, mercenary, do you want to do a good deed? My clients are asking to ensure a safe area to conduct a specific secret operation. I would like to appoint you for this, as you are the most competent of the local workers. You will have to survey the area and report back to me. Good luck.";
}
// Update localization files
rqLocales["616041eb031af660100c9967 successMessageText 668aaff35fd574b6dcc4a686 0"] = "Marvelous, young man. Thank you for the work.";
rqLocales["616041eb031af660100c9967 description 668aaff35fd574b6dcc4a686 0"] = "Ah, mercenary, do you want to do a good deed? My clients are asking to ensure a safe area to conduct a specific secret operation. I would like to appoint you for this, as you are the most competent of the local workers. You will have to survey the area and report back to me. Good luck.";
rqLocales["61604635c725987e815b1a46 successMessageText 668aaff35fd574b6dcc4a686 0"] = "There you are! You got everything? Good stuff.";
rqLocales["61604635c725987e815b1a46 description 668aaff35fd574b6dcc4a686 0"] = "I have a mission for you. I need you to gather some items for me. You up for it?";
rqLocales["616052ea3054fc0e2c24ce6e successMessageText 668aaff35fd574b6dcc4a686 0"] = "A damn beast you are, hehe. Good work, here's your share.";
rqLocales["616052ea3054fc0e2c24ce6e description 668aaff35fd574b6dcc4a686 0"] = "I have a mission for you. I need you to eliminate some trash from Tarkov's streets. You up for it?";
this.logger.info("Painter repeatable quest messages added to localization files");
}
this.addTraderToDb(baseJson, tables, jsonUtil);
this.addTraderToLocales(tables, baseJson.name, "Ivan Samoylov", baseJson.nickname, baseJson.location, "Ivan Samoylov is a master craftsman renowned for his exceptional skill in creating exquisite weapon cosmetics. With an innate talent for blending artistry and functionality, he transforms ordinary weapons into mesmerizing works of art.");
this.ragfairConfig.traders[baseJson._id] = true;
this.importQuests(tables);
this.importQuestLocales(tables);
this.routeQuestImages(imageRouter);
// Create all custom items using the CustomItemsManager
const customItemsManager = new CustomItemsManager_1.CustomItemsManager(this.logger);
customItemsManager.createCustomItems(customItem, configServer, tables, inventoryConfig, configJson.enableLootBoxes);
}
registerProfileImage(preSptModLoader, imageRouter) {
const imageFilepath = `./${preSptModLoader.getModPath(this.mod)}res`;
imageRouter.addRoute(baseJson.avatar.replace(".jpg", ""), `${imageFilepath}/painter.jpg`);
}
setupTraderUpdateTime(traderConfig) {
const traderRefreshRecord = { traderId: baseJson._id, seconds: { min: 2000, max: 6600 } };
traderConfig.updateTime.push(traderRefreshRecord);
}
setupTraderServices(traderConfig) {
const traderId = baseJson._id;
if (!traderConfig.moddedTraders) {
traderConfig.moddedTraders = { clothingService: [] };
}
traderConfig.moddedTraders.clothingService.push(traderId);
}
addTraderToDb(traderDetailsToAdd, tables, jsonUtil) {
tables.traders[traderDetailsToAdd._id] = {
assort: jsonUtil.deserialize(jsonUtil.serialize(assortJson)),
base: jsonUtil.deserialize(jsonUtil.serialize(traderDetailsToAdd)),
questassort: {
started: {},
success: {
"672e2804a0529208b4e10e18": "668aad3c3ff8f5b258e3a65b",
"672e284a363b798192b802af": "668c18eb12542b3c3ff6e20f",
"672e289bb4096716fcb918a7": "668c18eb12542b3c3ff6e20f"
},
fail: {}
}
};
}
addTraderToLocales(tables, fullName, firstName, nickName, location, description) {
const locales = Object.values(tables.locales.global);
for (const locale of locales) {
locale[`${baseJson._id} FullName`] = fullName;
locale[`${baseJson._id} FirstName`] = firstName;
locale[`${baseJson._id} Nickname`] = nickName;
locale[`${baseJson._id} Location`] = location;
locale[`${baseJson._id} Description`] = description;
}
}
loadFiles(dirPath, extName, cb) {
if (!fs.existsSync(dirPath))
return;
const dir = fs.readdirSync(dirPath, { withFileTypes: true });
dir.forEach(item => {
const itemPath = path.normalize(`${dirPath}/${item.name}`);
if (item.isDirectory())
this.loadFiles(itemPath, extName, cb);
else if (extName.includes(path.extname(item.name)))
cb(itemPath);
});
}
importQuests(tables) {
this.loadFiles(`${modPath}/db/quests/`, [".json"], function (filePath) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const item = require(filePath);
if (Object.keys(item).length < 1)
return;
for (const quest in item) {
tables.templates.quests[quest] = item[quest];
}
});
}
importQuestLocales(tables) {
const serverLocales = ["ch", "cz", "en", "es", "es-mx", "fr", "ge", "hu", "it", "jp", "pl", "po", "ru", "sk", "tu"];
const addedLocales = {};
for (const locale of serverLocales) {
this.loadFiles(`${modPath}/db/locales/${locale}`, [".json"], function (filePath) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const localeFile = require(filePath);
if (Object.keys(localeFile).length < 1)
return;
for (const currentItem in localeFile) {
tables.locales.global[locale][currentItem] = localeFile[currentItem];
if (!Object.keys(addedLocales).includes(locale))
addedLocales[locale] = {};
addedLocales[locale][currentItem] = localeFile[currentItem];
}
});
}
for (const locale of serverLocales) {
if (locale == "en")
continue;
for (const englishItem in addedLocales["en"]) {
if (locale in addedLocales) {
if (englishItem in addedLocales[locale])
continue;
}
if (tables.locales.global[locale] != undefined)
tables.locales.global[locale][englishItem] = addedLocales["en"][englishItem];
}
}
}
routeQuestImages(imageRouter) {
this.loadFiles(`${modPath}/res/quests/`, [".png", ".jpg"], function (filePath) {
imageRouter.addRoute(`/files/quest/icon/${path.basename(filePath, path.extname(filePath))}`, filePath);
});
}
}
module.exports = { mod: new PainterTrader() };
//# sourceMappingURL=mod.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,41 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.mod = void 0;
const tsyringe_1 = require("C:/snapshot/project/node_modules/tsyringe");
const jsonc_1 = require("C:/snapshot/project/node_modules/jsonc");
const path_1 = __importDefault(require("path"));
class BossesHaveLegaMedals {
logger;
static fileSystemSync = tsyringe_1.container.resolve("FileSystemSync");
static config = jsonc_1.jsonc.parse(BossesHaveLegaMedals.fileSystemSync.read(path_1.default.resolve(__dirname, "../config/config.jsonc")));
postDBLoad(container) {
const databaseService = container.resolve("DatabaseService");
this.logger = container.resolve("WinstonLogger");
const tables = databaseService.getTables();
let chance = BossesHaveLegaMedals.config.legaMedalChance;
if (chance <= 0)
chance = 1;
for (const botType in tables.bots.types) {
if (!botType.includes("boss") || botType == "bosstest") {
continue;
}
const bossPockets = tables.bots.types[botType].inventory.items.Pockets;
const bossTotal = Object.values(bossPockets).reduce((a, b) => a + b, 0);
let value = 0;
let guess = 0;
let rollChance = 0;
guess = chance / 100 * bossTotal;
value = Math.round((chance / 100) * (bossTotal + guess));
rollChance = value / (bossTotal + value);
//this.logger.debug(`[BossesHaveLegaMedals] ${botType}: ${(bossTotal + value)} --- if value: ${value} then chance is ${rollChance}`);
if (BossesHaveLegaMedals.config.debugLogging)
this.logger.debug(`[BossesHaveLegaMedals] ${botType}: Chance is ${Number(rollChance).toLocaleString(undefined, { style: 'percent', minimumFractionDigits: 2 })}`);
bossPockets["6656560053eaaa7a23349c86"] = value;
}
}
}
exports.mod = new BossesHaveLegaMedals();
//# sourceMappingURL=mod.js.map

View file

@ -0,0 +1,10 @@
{
"version": 3,
"file": "mod.js",
"sourceRoot": "",
"sources": [
"mod.ts"
],
"names": [],
"mappings": ";;;;;;AAAA,wEAA2F;AAM3F,kEAA+D;AAC/D,gDAAwB;AAGxB,MAAM,oBAAoB;IAEd,MAAM,CAAS;IAEf,MAAM,CAAC,cAAc,GAAG,oBAAS,CAAC,OAAO,CAAiB,gBAAgB,CAAC,CAAC;IAC5E,MAAM,CAAC,MAAM,GAAW,aAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,cAAc,CAAC,IAAI,CAAC,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,wBAAwB,CAAC,CAAC,CAAC,CAAC;IAElI,UAAU,CAAC,SAA8B;QAE5C,MAAM,eAAe,GAAG,SAAS,CAAC,OAAO,CAAkB,iBAAiB,CAAC,CAAC;QAC9E,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,OAAO,CAAU,eAAe,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAoB,eAAe,CAAC,SAAS,EAAE,CAAC;QAE5D,IAAI,MAAM,GAAG,oBAAoB,CAAC,MAAM,CAAC,eAAe,CAAC;QACzD,IAAI,MAAM,IAAI,CAAC;YAAE,MAAM,GAAG,CAAC,CAAC;QAE5B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,EACvC,CAAC;YACG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,IAAI,UAAU,EACtD,CAAC;gBACG,SAAS;YACb,CAAC;YACD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;YACvE,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;YAExE,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,IAAI,UAAU,GAAG,CAAC,CAAC;YAEnB,KAAK,GAAG,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC;YACjC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC;YACzD,UAAU,GAAG,KAAK,GAAG,CAAC,SAAS,GAAG,KAAK,CAAC,CAAA;YACxC,qIAAqI;YACrI,IAAI,oBAAoB,CAAC,MAAM,CAAC,YAAY;gBAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,OAAO,eAAe,MAAM,CAAC,UAAU,CAAC,CAAC,cAAc,CAAC,SAAS,EAAC,EAAC,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAC,CAAC,EAAC,CAAC,EAAE,CAAC,CAAC;YAC5M,WAAW,CAAC,0BAA0B,CAAC,GAAG,KAAK,CAAC;QACpD,CAAC;IACL,CAAC;;AASQ,QAAA,GAAG,GAAG,IAAI,oBAAoB,EAAE,CAAC"
}

View file

@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mod = void 0;
class RefSPTFriendlyQuests {
customQuestTable = require("../db/Ref_quests.json");
postDBLoad(container) {
const databaseService = container.resolve("DatabaseService");
const tables = databaseService.getTables();
const localeTable = tables.locales.global;
const questTable = tables.templates.quests;
const refTraderID = "6617beeaa9cfa777ca915b7c";
const refBase = tables.traders[refTraderID].base;
const refQuestAssort = tables.traders[refTraderID].questassort;
//Update assort to have quest reward
refQuestAssort["success"]["66c1beaefa6e5a0c120f0d08"] = "668caeedbdb70c05d702f1b6";
questTable["66058cc1da30b620a34e6e86"] = this.customQuestTable["66058cc1da30b620a34e6e86"]; //tgh p1
questTable["66058cc208308761cf390993"] = this.customQuestTable["66058cc208308761cf390993"]; //tgh p2
questTable["66058cc5bb83da7ba474aba9"] = this.customQuestTable["66058cc5bb83da7ba474aba9"]; //tgh p3
for (const language in localeTable) {
localeTable[language]["668caeedbdb70c05d702f0fc"] = "Eliminate PMCs"; // tgh p1
localeTable[language]["662ba78e19c86d3199ae0a93"] = "Eliminate PMCs"; // tgh p2
localeTable[language]["662ba61d3ed61b6b78187b71"] = "Eliminate PMCs"; // tgh p3
}
// Change LL4 requirements for Ref to be 1.00
refBase.loyaltyLevels[3].minStanding = 1.0;
}
}
exports.mod = new RefSPTFriendlyQuests();
//# sourceMappingURL=mod.js.map

View file

@ -0,0 +1,10 @@
{
"version": 3,
"file": "mod.js",
"sourceRoot": "",
"sources": [
"mod.ts"
],
"names": [],
"mappings": ";;;AAOA,MAAM,oBAAoB;IAEd,gBAAgB,GAA2B,OAAO,CAAC,uBAAuB,CAAC,CAAA;IAE5E,UAAU,CAAC,SAA8B;QAE5C,MAAM,eAAe,GAAG,SAAS,CAAC,OAAO,CAAkB,iBAAiB,CAAC,CAAC;QAC9E,MAAM,MAAM,GAAoB,eAAe,CAAC,SAAS,EAAE,CAAC;QAC5D,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;QAC3C,MAAM,WAAW,GAAG,0BAA0B,CAAC;QAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC;QACjD,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC;QAE/D,oCAAoC;QACpC,cAAc,CAAC,SAAS,CAAC,CAAC,0BAA0B,CAAC,GAAG,0BAA0B,CAAE;QAEpF,UAAU,CAAC,0BAA0B,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,0BAA0B,CAAC,CAAC,CAAC,QAAQ;QACpG,UAAU,CAAC,0BAA0B,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,0BAA0B,CAAC,CAAC,CAAC,QAAQ;QACpG,UAAU,CAAC,0BAA0B,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,0BAA0B,CAAC,CAAC,CAAC,QAAQ;QAEpG,KAAK,MAAM,QAAQ,IAAI,WAAW,EAClC,CAAC;YACG,WAAW,CAAC,QAAQ,CAAC,CAAC,0BAA0B,CAAC,GAAG,gBAAgB,CAAA,CAAC,SAAS;YAC9E,WAAW,CAAC,QAAQ,CAAC,CAAC,0BAA0B,CAAC,GAAG,gBAAgB,CAAA,CAAC,SAAS;YAC9E,WAAW,CAAC,QAAQ,CAAC,CAAC,0BAA0B,CAAC,GAAG,gBAAgB,CAAA,CAAC,SAAS;QAClF,CAAC;QAED,6CAA6C;QAC7C,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,GAAG,CAAC;IAC/C,CAAC;CACJ;AAEY,QAAA,GAAG,GAAG,IAAI,oBAAoB,EAAE,CAAC"
}

View file

@ -0,0 +1,65 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.mod = void 0;
const jsonc_1 = require("C:/snapshot/project/node_modules/jsonc");
const path = __importStar(require("path"));
class Mod {
postDBLoad(container) {
const LocaleHelper = container.resolve("LocaleService");
const locale = LocaleHelper.getDesiredGameLocale();
const localeDB = LocaleHelper.getLocaleDb();
const fileSystem = container.resolve("FileSystemSync");
//Config Variables
const hearingColor = "#598559";
const ambientColor = "#f59542";
//load config file
const headsetConfigs = jsonc_1.jsonc.parse(fileSystem.read(path.resolve(__dirname, "../config/headset-config.json")));
//Update function
const headsetDescUpdate = (itemID, Hearing, Ambient) => {
const headsetDesc = localeDB[`${itemID} Description`];
const headsetDescNew = headsetDesc +
`\n\n <color=${hearingColor}>Rated Hearing Distance: ${Hearing} meters</color>\n` +
` <color=${ambientColor}>Ambient Noise Canceling: -${Ambient}db</color>`;
localeDB[`${itemID} Description`] = headsetDescNew;
};
// Loop and apply
for (const [itemID, hearing, ambient] of headsetConfigs) {
headsetDescUpdate(itemID, hearing, ambient);
}
}
}
exports.mod = new Mod();
//# sourceMappingURL=mod.js.map

View file

@ -0,0 +1,10 @@
{
"version": 3,
"file": "mod.js",
"sourceRoot": "",
"sources": [
"mod.ts"
],
"names": [],
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,kEAA+D;AAC/D,2CAA6B;AAE7B,MAAM,GAAG;IAEE,UAAU,CAAC,SAA8B;QAC5C,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAgB,eAAe,CAAC,CAAC;QACvE,MAAM,MAAM,GAAkB,YAAY,CAAC,oBAAoB,EAAE,CAAC;QAClE,MAAM,QAAQ,GAA2B,YAAY,CAAC,WAAW,EAAE,CAAC;QACpE,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAiB,gBAAgB,CAAC,CAAC;QAEvE,kBAAkB;QAClB,MAAM,YAAY,GAAG,SAAS,CAAC;QAC/B,MAAM,YAAY,GAAG,SAAS,CAAC;QAC/B,kBAAkB;QAClB,MAAM,cAAc,GAA+B,aAAK,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,+BAA+B,CAAC,CAAC,CAAC,CAAC;QAE1I,iBAAiB;QACjB,MAAM,iBAAiB,GAAG,CAAC,MAAc,EAAE,OAAe,EAAE,OAAe,EAAQ,EAAE;YACjF,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,MAAM,cAAc,CAAC,CAAC;YACtD,MAAM,cAAc,GAAG,WAAW;gBAC9B,eAAe,YAAY,4BAA4B,OAAO,mBAAmB;gBACjF,WAAW,YAAY,8BAA8B,OAAO,YAAY,CAAC;YAC7E,QAAQ,CAAC,GAAG,MAAM,cAAc,CAAC,GAAG,cAAc,CAAC;QACvD,CAAC,CAAA;QAED,iBAAiB;QACjB,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,cAAc,EAAE,CAAC;YACtD,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;IAEL,CAAC;CACJ;AAEY,QAAA,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC"
}

View file

@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.assortUnlocks = void 0;
const assortUnlocks = (container) => {
const logger = container.resolve("PrimaryLogger");
const staticRouterModService = container.resolve("StaticRouterModService");
const databaseService = container.resolve("DatabaseService");
const loadAssortmentUnlocks = () => {
const traders = databaseService.getTraders();
const quests = databaseService.getQuests();
const result = {};
for (const traderId in traders) {
const trader = traders[traderId];
if (trader.questassort) {
for (const questStatus in trader.questassort) {
// Explicitly check that quest status is an expected value - some mods accidently import in such a way that adds a "default" value
if (!["started", "success", "fail"].includes(questStatus)) {
continue;
}
for (const assortId in trader.questassort[questStatus]) {
const questId = trader.questassort[questStatus][assortId];
if (!quests[questId]) {
logger.warning(`UIFixes: Trader ${traderId} questassort references unknown quest ${JSON.stringify(questId)}! Check that whatever mod added that trader and/or quest is installed correctly.`);
continue;
}
result[assortId] = quests[questId].name;
}
}
}
}
return result;
};
staticRouterModService.registerStaticRouter("UIFixesRoutes", [
{
url: "/uifixes/assortUnlocks",
action: async (url, info, sessionId, output) => {
return JSON.stringify(loadAssortmentUnlocks());
}
}
], "custom-static-ui-fixes");
};
exports.assortUnlocks = assortUnlocks;
//# sourceMappingURL=assortUnlocks.js.map

View file

@ -0,0 +1,10 @@
{
"version": 3,
"file": "assortUnlocks.js",
"sourceRoot": "",
"sources": [
"assortUnlocks.ts"
],
"names": [],
"mappings": ";;;AAMO,MAAM,aAAa,GAAG,CAAC,SAA8B,EAAE,EAAE;IAC5D,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAU,eAAe,CAAC,CAAC;IAC3D,MAAM,sBAAsB,GAAG,SAAS,CAAC,OAAO,CAAyB,wBAAwB,CAAC,CAAC;IACnG,MAAM,eAAe,GAAG,SAAS,CAAC,OAAO,CAAkB,iBAAiB,CAAC,CAAC;IAE9E,MAAM,qBAAqB,GAAG,GAAG,EAAE;QAC/B,MAAM,OAAO,GAAG,eAAe,CAAC,UAAU,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,EAAE,CAAC;QAC3C,MAAM,MAAM,GAA2B,EAAE,CAAC;QAE1C,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;YACjC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;gBACrB,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;oBAC3C,kIAAkI;oBAClI,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;wBACxD,SAAS;oBACb,CAAC;oBAED,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC;wBACrD,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,CAAC;wBAE1D,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;4BACnB,MAAM,CAAC,OAAO,CACV,mBAAmB,QAAQ,yCAAyC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,kFAAkF,CAChL,CAAC;4BACF,SAAS;wBACb,CAAC;wBAED,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC;oBAC5C,CAAC;gBACL,CAAC;YACL,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC,CAAC;IAEF,sBAAsB,CAAC,oBAAoB,CACvC,eAAe,EACf;QACI;YACI,GAAG,EAAE,wBAAwB;YAC7B,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE;gBAC3C,OAAO,IAAI,CAAC,SAAS,CAAC,qBAAqB,EAAE,CAAC,CAAC;YACnD,CAAC;SACJ;KACJ,EACD,wBAAwB,CAC3B,CAAC;AACN,CAAC,CAAC;AAlDW,QAAA,aAAa,iBAkDxB"
}

View file

@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.keepQuickBinds = void 0;
const keepQuickBinds = (container) => {
const logger = container.resolve("PrimaryLogger");
const cloner = container.resolve("RecursiveCloner");
container.afterResolution("InRaidHelper", (_, inRaidHelper) => {
const original = inRaidHelper.deleteInventory;
inRaidHelper.deleteInventory = (pmcData, sessionId) => {
// Copy the existing quickbinds
const fastPanel = cloner.clone(pmcData.Inventory.fastPanel);
// Nukes the inventory and the fastpanel
const result = original.call(inRaidHelper, pmcData, sessionId);
// Restore the quickbinds for items that still exist
try {
for (const index in fastPanel) {
if (pmcData.Inventory.items.find(i => i._id == fastPanel[index])) {
pmcData.Inventory.fastPanel[index] = fastPanel[index];
}
}
}
catch (error) {
logger.error(`UIFixes: Failed to restore quickbinds\n ${error}`);
}
return result;
};
}, { frequency: "Always" });
};
exports.keepQuickBinds = keepQuickBinds;
//# sourceMappingURL=keepQuickBinds.js.map

View file

@ -0,0 +1,10 @@
{
"version": 3,
"file": "keepQuickBinds.js",
"sourceRoot": "",
"sources": [
"keepQuickBinds.ts"
],
"names": [],
"mappings": ";;;AAMO,MAAM,cAAc,GAAG,CAAC,SAA8B,EAAE,EAAE;IAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAU,eAAe,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAU,iBAAiB,CAAC,CAAC;IAE7D,SAAS,CAAC,eAAe,CACrB,cAAc,EACd,CAAC,CAAC,EAAE,YAA0B,EAAE,EAAE;QAC9B,MAAM,QAAQ,GAAG,YAAY,CAAC,eAAe,CAAC;QAE9C,YAAY,CAAC,eAAe,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE;YAClD,+BAA+B;YAC/B,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YAE5D,wCAAwC;YACxC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;YAE/D,oDAAoD;YACpD,IAAI,CAAC;gBACD,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;oBAC5B,IAAI,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;wBAC/D,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;oBAC1D,CAAC;gBACL,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,2CAA2C,KAAK,EAAE,CAAC,CAAC;YACrE,CAAC;YAED,OAAO,MAAM,CAAC;QAClB,CAAC,CAAC;IACN,CAAC,EACD,EAAE,SAAS,EAAE,QAAQ,EAAE,CAC1B,CAAC;AACN,CAAC,CAAC;AAhCW,QAAA,cAAc,kBAgCzB"
}

View file

@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.linkedSlotSearch = void 0;
const linkedSlotSearch = (container) => {
const logger = container.resolve("PrimaryLogger");
const itemHelper = container.resolve("ItemHelper");
const databaseService = container.resolve("DatabaseService");
container.afterResolution("RagfairLinkedItemService", (_, linkedItemService) => {
const original = linkedItemService.getLinkedItems;
linkedItemService.getLinkedItems = linkedSearchId => {
const [tpl, slotName] = linkedSearchId.split(":", 2);
if (slotName) {
logger.info(`UIFixes: Finding items for specific slot ${tpl}:${slotName}`);
const allItems = databaseService.getItems();
const resultSet = getSpecificFilter(allItems[tpl], slotName);
// Default Inventory, for equipment slots
if (tpl === "55d7217a4bdc2d86028b456d") {
const categories = [...resultSet];
const items = Object.keys(allItems).filter(tpl => itemHelper.isOfBaseclasses(tpl, categories));
// Send the categories along too, some of them might actually be items
return new Set(items.concat(categories));
}
return resultSet;
}
return original.call(linkedItemService, tpl);
};
}, { frequency: "Always" });
};
exports.linkedSlotSearch = linkedSlotSearch;
const getSpecificFilter = (item, slotName) => {
const results = new Set();
// For whatever reason, all chamber slots have the name "patron_in_weapon"
const groupName = slotName === "patron_in_weapon" ? "Chambers" : "Slots";
const group = item._props[groupName] ?? [];
const sub = group.find(slot => slot._name === slotName);
for (const filter of sub?._props?.filters ?? []) {
for (const f of filter.Filter) {
results.add(f);
}
}
return results;
};
//# sourceMappingURL=linkedSlotSearch.js.map

View file

@ -0,0 +1,10 @@
{
"version": 3,
"file": "linkedSlotSearch.js",
"sourceRoot": "",
"sources": [
"linkedSlotSearch.ts"
],
"names": [],
"mappings": ";;;AAQO,MAAM,gBAAgB,GAAG,CAAC,SAA8B,EAAE,EAAE;IAC/D,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAU,eAAe,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAa,YAAY,CAAC,CAAC;IAC/D,MAAM,eAAe,GAAG,SAAS,CAAC,OAAO,CAAkB,iBAAiB,CAAC,CAAC;IAE9E,SAAS,CAAC,eAAe,CACrB,0BAA0B,EAC1B,CAAC,CAAC,EAAE,iBAA2C,EAAE,EAAE;QAC/C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,cAAc,CAAC;QAElD,iBAAiB,CAAC,cAAc,GAAG,cAAc,CAAC,EAAE;YAChD,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAErD,IAAI,QAAQ,EAAE,CAAC;gBACX,MAAM,CAAC,IAAI,CAAC,4CAA4C,GAAG,IAAI,QAAQ,EAAE,CAAC,CAAC;gBAC3E,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAC;gBAC5C,MAAM,SAAS,GAAG,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;gBAE7D,yCAAyC;gBACzC,IAAI,GAAG,KAAK,0BAA0B,EAAE,CAAC;oBACrC,MAAM,UAAU,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;oBAClC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;oBAE/F,sEAAsE;oBACtE,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;gBAC7C,CAAC;gBAED,OAAO,SAAS,CAAC;YACrB,CAAC;YAED,OAAO,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QACjD,CAAC,CAAC;IACN,CAAC,EACD,EAAE,SAAS,EAAE,QAAQ,EAAE,CAC1B,CAAC;AACN,CAAC,CAAC;AAnCW,QAAA,gBAAgB,oBAmC3B;AAEF,MAAM,iBAAiB,GAAG,CAAC,IAAmB,EAAE,QAAgB,EAAe,EAAE;IAC7E,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAElC,0EAA0E;IAC1E,MAAM,SAAS,GAAG,QAAQ,KAAK,kBAAkB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC;IACzE,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IAE3C,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC;IACxD,KAAK,MAAM,MAAM,IAAI,GAAG,EAAE,MAAM,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;QAC9C,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACnB,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC"
}

View file

@ -0,0 +1,27 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.mod = void 0;
const assortUnlocks_1 = require("./assortUnlocks");
const keepQuickBinds_1 = require("./keepQuickBinds");
const linkedSlotSearch_1 = require("./linkedSlotSearch");
const putToolsBack_1 = require("./putToolsBack");
const config_json_1 = __importDefault(require("../config/config.json"));
class UIFixes {
preSptLoad(container) {
// Keep quickbinds for items that aren't actually lost on death
(0, keepQuickBinds_1.keepQuickBinds)(container);
// Better tool return - starting production
if (config_json_1.default.putToolsBack) {
(0, putToolsBack_1.putToolsBack)(container);
}
// Slot-specific linked search
(0, linkedSlotSearch_1.linkedSlotSearch)(container);
// Show unlocking quest on locked offers
(0, assortUnlocks_1.assortUnlocks)(container);
}
}
exports.mod = new UIFixes();
//# sourceMappingURL=mod.js.map

View file

@ -0,0 +1,10 @@
{
"version": 3,
"file": "mod.js",
"sourceRoot": "",
"sources": [
"mod.ts"
],
"names": [],
"mappings": ";;;;;;AAIA,mDAAgD;AAChD,qDAAkD;AAClD,yDAAsD;AACtD,iDAA8C;AAE9C,wEAA2C;AAE3C,MAAM,OAAO;IACF,UAAU,CAAC,SAA8B;QAC5C,+DAA+D;QAC/D,IAAA,+BAAc,EAAC,SAAS,CAAC,CAAC;QAE1B,2CAA2C;QAC3C,IAAI,qBAAM,CAAC,YAAY,EAAE,CAAC;YACtB,IAAA,2BAAY,EAAC,SAAS,CAAC,CAAC;QAC5B,CAAC;QAED,8BAA8B;QAC9B,IAAA,mCAAgB,EAAC,SAAS,CAAC,CAAC;QAE5B,wCAAwC;QACxC,IAAA,6BAAa,EAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;CACJ;AAEY,QAAA,GAAG,GAAG,IAAI,OAAO,EAAE,CAAC"
}

View file

@ -0,0 +1,95 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.putToolsBack = void 0;
const returnToProperty = "uifixes.returnTo";
const putToolsBack = (container) => {
const logger = container.resolve("PrimaryLogger");
const cloner = container.resolve("RecursiveCloner");
const itemHelper = container.resolve("ItemHelper");
container.afterResolution("HideoutHelper", (_, hideoutHelper) => {
const original = hideoutHelper.registerProduction;
hideoutHelper.registerProduction = (pmcData, body, sessionID) => {
const result = original.call(hideoutHelper, pmcData, body, sessionID);
// The items haven't been deleted yet, augment the list with their parentId
try {
const bodyAsSingle = body;
if (bodyAsSingle && bodyAsSingle.tools?.length > 0) {
const requestTools = bodyAsSingle.tools;
const tools = pmcData.Hideout.Production[body.recipeId].sptRequiredTools;
for (let i = 0; i < tools.length; i++) {
const originalTool = pmcData.Inventory.items.find(x => x._id === requestTools[i].id);
// If the tool is in the stash itself, skip it. Same check as InventoryHelper.isItemInStash
if (originalTool.parentId === pmcData.Inventory.stash &&
originalTool.slotId === "hideout") {
continue;
}
tools[i][returnToProperty] = [originalTool.parentId, originalTool.slotId];
}
}
}
catch (error) {
logger.error(`UIFixes: Failed to save tool origin\n ${error}`);
}
return result;
};
}, { frequency: "Always" });
// Better tool return - returning the tool
container.afterResolution("InventoryHelper", (_, inventoryHelper) => {
const original = inventoryHelper.addItemToStash;
inventoryHelper.addItemToStash = (sessionId, request, pmcData, output) => {
const itemWithModsToAddClone = cloner.clone(request.itemWithModsToAdd);
// If a tool marked with uifixes is there, try to return it to its original container
const tool = itemWithModsToAddClone[0];
if (tool[returnToProperty]) {
try {
const [containerId, slotId] = tool[returnToProperty];
// Clean the item
delete tool[returnToProperty];
const [foundContainerFS2D, foundSlotId] = findGridFS2DForItems(inventoryHelper, containerId, slotId, itemWithModsToAddClone, pmcData);
if (foundContainerFS2D) {
// At this point everything should succeed
inventoryHelper.placeItemInContainer(foundContainerFS2D, itemWithModsToAddClone, containerId, foundSlotId);
// protected function, bypass typescript
inventoryHelper["setFindInRaidStatusForItem"](itemWithModsToAddClone, request.foundInRaid);
// Add item + mods to output and profile inventory
output.profileChanges[sessionId].items.new.push(...itemWithModsToAddClone);
pmcData.Inventory.items.push(...itemWithModsToAddClone);
logger.debug(`Added ${itemWithModsToAddClone[0].upd?.StackObjectsCount ?? 1} item: ${itemWithModsToAddClone[0]._tpl} with: ${itemWithModsToAddClone.length - 1} mods to ${containerId}`);
return;
}
}
catch (error) {
logger.error(`UIFixes: Encounted an error trying to put tool back.\n ${error}`);
}
logger.info("UIFixes: Unable to put tool back in its original container, returning it to stash.");
}
return original.call(inventoryHelper, sessionId, request, pmcData, output);
};
}, { frequency: "Always" });
function findGridFS2DForItems(inventoryHelper, containerId, startingGrid, items, pmcData) {
const container = pmcData.Inventory.items.find(x => x._id === containerId);
if (!container) {
return;
}
const [foundTemplate, containerTemplate] = itemHelper.getItem(container._tpl);
if (!foundTemplate || !containerTemplate) {
return;
}
let originalGridIndex = containerTemplate._props.Grids.findIndex(g => g._name === startingGrid);
if (originalGridIndex < 0) {
originalGridIndex = 0;
}
// Loop through grids, starting from the original grid
for (let gridIndex = originalGridIndex; gridIndex < containerTemplate._props.Grids.length + originalGridIndex; gridIndex++) {
const grid = containerTemplate._props.Grids[gridIndex % containerTemplate._props.Grids.length];
const gridItems = pmcData.Inventory.items.filter(x => x.parentId === containerId && x.slotId === grid._name);
const containerFS2D = inventoryHelper.getContainerMap(grid._props.cellsH, grid._props.cellsV, gridItems, containerId);
// will change the array so clone it
if (inventoryHelper.canPlaceItemInContainer(cloner.clone(containerFS2D), items)) {
return [containerFS2D, grid._name];
}
}
}
};
exports.putToolsBack = putToolsBack;
//# sourceMappingURL=putToolsBack.js.map

View file

@ -0,0 +1,10 @@
{
"version": 3,
"file": "putToolsBack.js",
"sourceRoot": "",
"sources": [
"putToolsBack.ts"
],
"names": [],
"mappings": "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"
}