This commit is contained in:
GetParanoid 2025-07-18 18:11:28 -05:00
parent 7aa7ac1092
commit 081b038df5
99 changed files with 18010 additions and 1 deletions

View file

@ -0,0 +1,490 @@
"use strict";
/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable @typescript-eslint/brace-style */
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/*
* If you are reading this, I hope you are enjoying Scorpion
*
*
* I have worked on this mod for several months and have tried my best to make it as easy to read and clean as possible
* I may not always do things in the best way, but I do try!
* If you have any questions please reach out to me in the SPT Discord - do not DM me
*
*/
const tsyringe_1 = require("C:/snapshot/project/node_modules/tsyringe");
const ConfigTypes_1 = require("C:/snapshot/project/obj/models/enums/ConfigTypes");
const jsonc_1 = require("C:/snapshot/project/node_modules/jsonc");
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
// Custom Imports
const traderHelpers_1 = require("./traderHelpers");
const Traders_1 = require("C:/snapshot/project/obj/models/enums/Traders");
const baseJson = require("../db/base.json");
const questJson = require("../db/questassort.json");
const assortJson = require("../db/assort.json");
const productionJson = require("../db/production.json");
const weaponCompatibility = require("../config/ModdedWeaponCompatibility.json");
const scorpionQuests = require("../../Virtual's Custom Quest Loader/database/quests/Scorpion_quests.json");
let realismDetected;
const loadMessage = {
0: "Scorpion has brought his crew into Tarkov",
1: "One of us..one of us..one of us",
2: "Welcome to the team, you're one of us meow ♡",
3: "Call Kenny Loggins because you're in the danger zone",
4: "Can I offer you a nice egg in this trying time?",
5: "Good news everyone! We have over 100 quests!",
6: "Never half-ass two things. Whole-ass one thing.",
7: "Thanks for signing up for Cat Facts! You will now receive fun daily facts about CATS!",
8: "Thanks for signing up for Dog Facts! You will now receive fun daily facts about DOGS!",
9: "A big ball of wibbly wobbly, timey wimey stuff",
10: "(╯°□°)╯︵ ┻━┻ ",
11: "┬─┬ノ( º _ ºノ)",
12: "Treat others how you want to be treated",
13: "No act of kindness, no matter how small, is ever wasted",
14: "Reticulating Splines...",
15: "Unfolding Foldy Chairs...",
16: "Pressurizing Fruit Punch Barrel Hydraulics...",
17: "Fabricating Imaginary Infrastructure...",
18: "We apologize again for the fault in the subtitles. Those responsible for sacking the people who have just been sacked, have been sacked.",
19: "Are you suggesting coconuts migrate?",
20: "We are now the knights who say ekki-ekki-ekki-pitang-zoom-boing!",
21: "Knight jumps queen! Bishop jumps queen! Pawns jump queen!",
22: "Hello. My name is Inigo Montoya. You killed my father. Prepare to die.",
23: "I spent the last few years building up an immunity to iocane powder.",
24: "Rodents Of Unusual Size? I don't think they exist.",
25: "Always try to be nice, but never fail to be kind",
26: "Never be cruel, never be cowardly",
27: "Who do I need to ban? (◣_◢)",
28: "This loading message is sponsored by Raid: Shadow Legends"
};
class Scorpion {
mod;
logger;
traderHelper;
static fileSystemSync = tsyringe_1.container.resolve("FileSystemSync");
static config = jsonc_1.jsonc.parse(Scorpion.fileSystemSync.read(node_path_1.default.resolve(__dirname, "../config/config.jsonc")));
// Set the name of mod for logging purposes
constructor() {
this.mod = "acidphantasm-scorpion";
}
/*
* Some work needs to be done prior to SPT code being loaded
*
* TLDR:
* Resolve SPT Types
* Set trader refresh, config, image, flea settings
* Register Dynamic Router for Randomization Config
*
*/
preSptLoad(container) {
// Get a logger
this.logger = container.resolve("WinstonLogger");
// Get SPT code/data we need later
const dynamicRouterModService = container.resolve("DynamicRouterModService");
const preSptModLoader = container.resolve("PreSptModLoader");
const databaseService = container.resolve("DatabaseService");
const ragfairOfferGenerator = container.resolve("RagfairOfferGenerator");
const imageRouter = container.resolve("ImageRouter");
const configServer = container.resolve("ConfigServer");
const traderConfig = configServer.getConfig(ConfigTypes_1.ConfigTypes.TRADER);
const ragfairConfig = configServer.getConfig(ConfigTypes_1.ConfigTypes.RAGFAIR);
// Set config values to local variables for validation & use
let minRefresh = Scorpion.config.traderRefreshMin;
let maxRefresh = Scorpion.config.traderRefreshMax;
const addToFlea = Scorpion.config.addTraderToFlea;
if (minRefresh >= maxRefresh || maxRefresh <= 2) {
minRefresh = 1800;
maxRefresh = 3600;
this.logger.error(`[${this.mod}] [Config Issue] Refresh timers have been reset to default.`);
}
// Create helper class and use it to register our traders image/icon + set its stock refresh time
this.traderHelper = new traderHelpers_1.TraderHelper();
const currentDate = new Date();
const month = currentDate.getMonth();
const day = currentDate.getDate();
if (month == 3 && day == 1) {
baseJson.nickname = "ScorpionXYZ";
baseJson.name = "ScorpionXYZ";
baseJson.avatar = "/files/trader/avatar/6688d464bc40c867f60e7d7e_aprilfools.jpg";
this.traderHelper.registerProfileImage(baseJson, this.mod, preSptModLoader, imageRouter, "6688d464bc40c867f60e7d7e_aprilfools.jpg");
}
else
this.traderHelper.registerProfileImage(baseJson, this.mod, preSptModLoader, imageRouter, "6688d464bc40c867f60e7d7e.jpg");
this.traderHelper.setTraderUpdateTime(traderConfig, baseJson, minRefresh, maxRefresh);
// Add trader to trader enum
Traders_1.Traders[baseJson._id] = baseJson._id;
// Add trader to flea market
if (addToFlea) {
ragfairConfig.traders[baseJson._id] = true;
}
else {
ragfairConfig.traders[baseJson._id] = false;
}
dynamicRouterModService.registerDynamicRouter("ScorpionRefreshStock", [
{
url: "/client/items/prices/6688d464bc40c867f60e7d7e",
action: async (url, info, sessionId, output) => {
const trader = databaseService.getTables().traders["6688d464bc40c867f60e7d7e"];
const assortItems = trader.assort.items;
let updateFleaOffers = false;
if (!realismDetected) {
if (Scorpion.config.randomizeBuyRestriction) {
if (Scorpion.config.debugLogging) {
this.logger.info(`[${this.mod}] Refreshing Scorpion Stock with Randomized Buy Restrictions.`);
}
updateFleaOffers = true;
this.randomizeBuyRestriction(assortItems);
}
if (Scorpion.config.randomizeStockAvailable) {
if (Scorpion.config.debugLogging) {
this.logger.info(`[${this.mod}] Refreshing Scorpion Stock with Randomized Stock Availability.`);
}
updateFleaOffers = true;
this.randomizeStockAvailable(assortItems);
}
if (updateFleaOffers)
ragfairOfferGenerator.generateFleaOffersForTrader("6688d464bc40c867f60e7d7e");
}
return output;
}
}
], "spt");
}
/*
* Some work needs to be done after loading SPT code
*
* TLDR:
* Resolve SPT Types
* Add Modded Weapons to Quests
* Mod Detection to enable/disable Assort Configuration options
* Apply Assort Configurations
* Add trader to dictionary, locales, and assort
*
*/
postDBLoad(container) {
const start = performance.now();
// Resolve SPT classes we'll use
const databaseService = container.resolve("DatabaseService");
const jsonUtil = container.resolve("JsonUtil");
const logger = container.resolve("WinstonLogger");
const quests = databaseService.getTables().templates.quests;
//Set local variables for assortJson
const assortPriceTable = assortJson.barter_scheme;
const assortItemTable = assortJson.items;
const assortLoyaltyTable = assortJson.loyal_level_items;
//Run Modded Weapon Compatibility
this.moddedWeaponCompatibility();
//Enable event quests
if (Scorpion.config.eventQuestsAlwaysActive) {
this.eventQuestsAlwaysActive(quests, scorpionQuests);
}
//Check Mod Compatibility
this.modDetection();
//Push Production Schemes
this.pushProductionUnlocks();
//Update Assort
if (Scorpion.config.priceMultiplier !== 1) {
this.setPriceMultiplier(assortPriceTable);
}
if (Scorpion.config.randomizeBuyRestriction) {
this.randomizeBuyRestriction(assortItemTable);
}
if (Scorpion.config.randomizeStockAvailable) {
this.randomizeStockAvailable(assortItemTable);
}
if (Scorpion.config.unlimitedStock) {
this.setUnlimitedStock(assortItemTable);
}
if (Scorpion.config.unlimitedBuyRestriction) {
this.setUnlimitedBuyRestriction(assortItemTable);
}
if (Scorpion.config.removeLoyaltyRestriction) {
this.disableLoyaltyRestrictions(assortLoyaltyTable);
}
// Set local variable for assort to pass to traderHelper regardless of priceMultiplier config
const newAssort = assortJson;
// Get a reference to the database tables
const tables = databaseService.getTables();
// Add new trader to the trader dictionary in DatabaseServer
// Add quest assort
// Add trader to locale file, ensures trader text shows properly on screen
this.traderHelper.addTraderToDb(baseJson, tables, jsonUtil, newAssort);
tables.traders[baseJson._id].questassort = questJson;
this.traderHelper.addTraderToLocales(baseJson, tables, baseJson.name, baseJson._id, baseJson.nickname, baseJson.location, "I'm sellin', what are you buyin'?");
this.logger.debug(`[${this.mod}] loaded... `);
const timeTaken = performance.now() - start;
if (Scorpion.config.debugLogging) {
logger.log(`[${this.mod}] Trader load took ${timeTaken.toFixed(3)}ms.`, "cyan");
}
logger.log(`[${this.mod}] ${this.getRandomLoadMessage()}`, "cyan");
}
/*
*
* All functions are below this comment
*
* Most of these functions should be self explanatory
*
*/
setRealismDetection(i) {
realismDetected = i;
if (realismDetected && Scorpion.config.randomizeBuyRestriction || realismDetected && Scorpion.config.randomizeStockAvailable) {
this.logger.log(`[${this.mod}] SPT-Realism detected, disabling randomizeBuyRestriction and/or randomizeStockAvailable:`, "cyan");
}
}
setPriceMultiplier(assortPriceTable) {
let priceMultiplier = Scorpion.config.priceMultiplier;
if (priceMultiplier <= 0) {
priceMultiplier = 1;
this.logger.error(`[${this.mod}] priceMultiplier cannot be set to zero.`);
}
for (const itemID in assortPriceTable) {
for (const item of assortPriceTable[itemID]) {
if (item[0].count <= 15) {
if (Scorpion.config.debugLogging) {
this.logger.log(`[${this.mod}] itemID: [${itemID}] No price change, it's a barter trade.`, "cyan");
}
continue;
}
const count = item[0].count;
const newPrice = Math.round(count * priceMultiplier);
item[0].count = newPrice;
if (Scorpion.config.debugLogging) {
this.logger.log(`[${this.mod}] itemID: [${itemID}] Price Changed to: [${newPrice}]`, "cyan");
}
}
}
}
randomizeBuyRestriction(assortItemTable) {
const randomUtil = tsyringe_1.container.resolve("RandomUtil");
if (!realismDetected) // If realism is not detected, continue, else do nothing
{
for (const item in assortItemTable) {
if (assortItemTable[item].parentId !== "hideout" || assortItemTable[item].upd.BuyRestrictionMax <= 3) {
continue; // Skip setting count, it's a weapon attachment or armour plate
}
const itemID = assortItemTable[item]._id;
const oldRestriction = assortItemTable[item].upd.BuyRestrictionMax;
const newRestriction = randomUtil.randInt(4, oldRestriction + 40);
assortItemTable[item].upd.BuyRestrictionMax = newRestriction;
if (Scorpion.config.debugLogging) {
this.logger.log(`[${this.mod}] Item: [${itemID}] Buy Restriction Changed to: [${newRestriction}]`, "cyan");
}
}
}
}
randomizeStockAvailable(assortItemTable) {
const randomUtil = tsyringe_1.container.resolve("RandomUtil");
if (!realismDetected) // If realism is not detected, continue, else do nothing
{
for (const item in assortItemTable) {
if (assortItemTable[item].parentId !== "hideout") {
continue; // Skip setting count, it's a weapon attachment or armour plate
}
const outOfStockRoll = randomUtil.getChance100(Scorpion.config.outOfStockChance);
if (outOfStockRoll) {
const itemID = assortItemTable[item]._id;
assortItemTable[item].upd.StackObjectsCount = 0;
if (Scorpion.config.debugLogging) {
this.logger.log(`[${this.mod}] Item: [${itemID}] Marked out of stock`, "cyan");
}
}
else {
if (assortItemTable[item].upd.StackObjectsCount <= 10)
assortItemTable[item].upd.StackObjectsCount = 250;
const itemID = assortItemTable[item]._id;
const originalStock = assortItemTable[item].upd.StackObjectsCount;
const newStock = randomUtil.randInt(3, Math.round(originalStock * 0.75));
if (Scorpion.config.debugLogging) {
this.logger.log(`[${this.mod}] Item: [${itemID}] Original Count: ${originalStock} | Stock Count changed to: [${newStock}]`, "cyan");
}
assortItemTable[item].upd.StackObjectsCount = newStock;
}
}
}
}
setUnlimitedStock(assortItemTable) {
for (const item in assortItemTable) {
if (assortItemTable[item].parentId !== "hideout") {
continue; // Skip setting count, it's a weapon attachment or armour plate
}
assortItemTable[item].upd.StackObjectsCount = 9999999;
assortItemTable[item].upd.UnlimitedCount = true;
}
if (Scorpion.config.debugLogging) {
this.logger.log(`[${this.mod}] Item stock counts are now unlimited`, "cyan");
}
}
setUnlimitedBuyRestriction(assortItemTable) {
for (const item in assortItemTable) {
if (assortItemTable[item].parentId !== "hideout") {
continue; // Skip setting count, it's a weapon attachment or armour plate
}
delete assortItemTable[item].upd.BuyRestrictionMax;
delete assortItemTable[item].upd.BuyRestrictionCurrent;
}
if (Scorpion.config.debugLogging) {
this.logger.log(`[${this.mod}] Item buy restrictions are now unlimited`, "cyan");
}
}
disableLoyaltyRestrictions(assortLoyaltyTable) {
for (const item in assortLoyaltyTable) {
delete assortLoyaltyTable[item];
}
if (Scorpion.config.debugLogging) {
this.logger.log(`[${this.mod}] All Loyalty Level requirements are removed`, "cyan");
}
}
modDetection() {
const preSptModLoader = tsyringe_1.container.resolve("PreSptModLoader");
const vcqlCheck = preSptModLoader.getImportedModsNames().includes("Virtual's Custom Quest Loader");
const realismCheck = preSptModLoader.getImportedModsNames().includes("SPT-Realism");
const vcqlDllPath = node_path_1.default.resolve(__dirname, "../../../../BepInEx/plugins/VCQLQuestZones.dll");
const heliCrashSamSWAT = node_path_1.default.resolve(__dirname, "../../../../BepInEx/plugins/SamSWAT.HeliCrash/SamSWAT.HeliCrash.dll");
const heliCrashTyrian = node_path_1.default.resolve(__dirname, "../../../../BepInEx/plugins/SamSWAT.HeliCrash.TyrianReboot/SamSWAT.HeliCrash.TyrianReboot.dll");
const heliCrashArys = node_path_1.default.resolve(__dirname, "../../../../BepInEx/plugins/SamSWAT.HeliCrash.ArysReloaded/SamSWAT.HeliCrash.ArysReloaded.dll");
// VCQL Zones DLL is missing
if (!node_fs_1.default.existsSync(vcqlDllPath)) {
this.logger.error(`[${this.mod}] VCQL Zones DLL missing. Custom Trader quests may not work properly.`);
}
// Outdated HeliCrash is installed
if (node_fs_1.default.existsSync(heliCrashSamSWAT) || node_fs_1.default.existsSync(heliCrashTyrian)) {
this.logger.error(`[${this.mod}] Outdated HeliCrash Mod Detected. You will experience issues with Custom Trader quest zones.`);
}
// Arys HeliCrash is installed
if (node_fs_1.default.existsSync(heliCrashArys)) {
this.logger.warning(`[${this.mod}] HeliCrash Mod Detected. You may experience issues with Custom Trader quest zones.`);
}
// VCQL package.json is missing
if (!vcqlCheck) {
this.logger.error(`[${this.mod}] VCQL not detected. Install VCQL and re-install ${this.mod}.`);
}
// This is completely unneccessary and I'll fix it, eventually - probably
if (Scorpion.config.randomizeBuyRestriction || Scorpion.config.randomizeStockAvailable) {
this.setRealismDetection(realismCheck);
}
else {
this.setRealismDetection(realismCheck);
}
}
moddedWeaponCompatibility() {
const databaseService = tsyringe_1.container.resolve("DatabaseService");
const questTable = databaseService.getTables().templates.quests;
const quests = Object.values(questTable);
let questType;
let weaponType;
let wasAdded;
if (weaponCompatibility.AssaultRifles.length >= 1) {
weaponType = weaponCompatibility.AssaultRifles;
questType = quests.filter(x => x.QuestName.includes("Weapon Proficiency - ARs"));
wasAdded = true;
this.moddedWeaponPushToArray(questType, weaponType);
}
if (weaponCompatibility.SubmachineGuns.length >= 1) {
weaponType = weaponCompatibility.SubmachineGuns;
questType = quests.filter(x => x.QuestName.includes("Weapon Proficiency - SMGs"));
wasAdded = true;
this.moddedWeaponPushToArray(questType, weaponType);
}
if (weaponCompatibility.Snipers.length >= 1) {
weaponType = weaponCompatibility.Snipers;
questType = quests.filter(x => x.QuestName.includes("Weapon Proficiency - Snipers"));
wasAdded = true;
this.moddedWeaponPushToArray(questType, weaponType);
}
if (weaponCompatibility.Marksman.length >= 1) {
weaponType = weaponCompatibility.Marksman;
questType = quests.filter(x => x.QuestName.includes("Weapon Proficiency - Marksman"));
wasAdded = true;
this.moddedWeaponPushToArray(questType, weaponType);
}
if (weaponCompatibility.Shotguns.length >= 1) {
weaponType = weaponCompatibility.Shotguns;
questType = quests.filter(x => x.QuestName.includes("Weapon Proficiency - Shotguns"));
wasAdded = true;
this.moddedWeaponPushToArray(questType, weaponType);
}
if (weaponCompatibility.Pistols.length >= 1) {
weaponType = weaponCompatibility.Pistols;
questType = quests.filter(x => x.QuestName.includes("Weapon Proficiency - Pistols"));
wasAdded = true;
this.moddedWeaponPushToArray(questType, weaponType);
}
if (weaponCompatibility.LargeMachineGuns.length >= 1) {
weaponType = weaponCompatibility.LargeMachineGuns;
questType = quests.filter(x => x.QuestName.includes("Weapon Proficiency - LMGs"));
wasAdded = true;
this.moddedWeaponPushToArray(questType, weaponType);
}
if (weaponCompatibility.Carbines.length >= 1) {
weaponType = weaponCompatibility.Carbines;
questType = quests.filter(x => x.QuestName.includes("Weapon Proficiency - Carbines"));
wasAdded = true;
this.moddedWeaponPushToArray(questType, weaponType);
}
if (weaponCompatibility.Melee.length >= 1) {
weaponType = weaponCompatibility.Melee;
questType = quests.filter(x => x.QuestName.includes("Weapon Proficiency - Melee"));
wasAdded = true;
this.moddedWeaponPushToArray(questType, weaponType);
}
if (weaponCompatibility.Explosives.length >= 1) {
weaponType = weaponCompatibility.Explosives;
questType = quests.filter(x => x.QuestName.includes("Weapon Proficiency - Explosives"));
wasAdded = true;
this.moddedWeaponPushToArray(questType, weaponType);
}
if (wasAdded) {
this.logger.log(`[${this.mod}] Custom Weapons added to proficiency quests. Enjoy!`, "cyan");
}
}
moddedWeaponPushToArray(questTable, weaponType) {
for (const quest in questTable) {
for (const condition in questTable[quest].conditions.AvailableForFinish) {
for (const item in questTable[quest].conditions.AvailableForFinish[condition].counter.conditions) {
for (const id of weaponType) {
questTable[quest].conditions.AvailableForFinish[condition].counter.conditions[item].weapon.push(id);
}
}
}
if (Scorpion.config.debugLogging) {
this.logger.log(`[${this.mod}] ${questTable[quest].QuestName} --- Added ${weaponType}`, "cyan");
}
}
}
eventQuestsAlwaysActive(questTable, quests) {
let eventCount = 0;
for (const quest in quests) {
if (quests[quest]?.startMonth) {
const currentDate = new Date();
const questStartDate = new Date(currentDate.getFullYear(), quests[quest].startMonth - 1, quests[quest].startDay);
const questEndDate = new Date(currentDate.getFullYear(), quests[quest].endMonth - 1, quests[quest].endDay);
if (currentDate < questStartDate || currentDate > questEndDate) {
delete quests[quest].startMonth;
delete quests[quest].endMonth;
delete quests[quest].startDay;
delete quests[quest].endDay;
questTable[quest] = quests[quest];
eventCount++;
}
}
}
this.logger.log(`[${this.mod}] Reactivated ${eventCount} Event Quests from Scorpion - Enjoy!`, "cyan");
this.logger.log(`[${this.mod}] !!! Remember to fix your config.jsonc when you update this mod to keep event quest progress !!!`, "cyan");
}
pushProductionUnlocks() {
const databaseService = tsyringe_1.container.resolve("DatabaseService");
const recipesTable = databaseService.getTables().hideout.production.recipes;
for (const item of productionJson) {
recipesTable.push(item);
}
}
getRandomLoadMessage() {
const value = loadMessage[Math.floor(Math.random() * Object.keys(loadMessage).length)];
return value;
}
}
module.exports = { mod: new Scorpion() };
//# sourceMappingURL=mod.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,124 @@
"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.TraderHelper = void 0;
const questAssort = __importStar(require("../db/questassort.json"));
class TraderHelper {
/**
* Add profile picture to our trader
* @param baseJson json file for trader (db/base.json)
* @param preSptModLoader mod loader class - used to get the mods file path
* @param imageRouter image router class - used to register the trader image path so we see their image on trader page
* @param traderImageName Filename of the trader icon to use
*/
registerProfileImage(baseJson, modName, preSptModLoader, imageRouter, traderImageName) {
// Reference the mod "res" folder
const imageFilepath = `./${preSptModLoader.getModPath(modName)}res`;
// Register a route to point to the profile picture - remember to remove the .jpg from it
imageRouter.addRoute(baseJson.avatar.replace(".jpg", ""), `${imageFilepath}/${traderImageName}`);
}
/**
* Add record to trader config to set the refresh time of trader in seconds (default is 60 minutes)
* @param traderConfig trader config to add our trader to
* @param baseJson json file for trader (db/base.json)
* @param refreshTimeSecondsMin How many seconds between trader stock refresh min time
* @param refreshTimeSecondsMax How many seconds between trader stock refresh max time
*/
setTraderUpdateTime(traderConfig, baseJson, refreshTimeSecondsMin, refreshTimeSecondsMax) {
// Add refresh time in seconds to config
const traderRefreshRecord = {
traderId: baseJson._id,
seconds: {
min: refreshTimeSecondsMin,
max: refreshTimeSecondsMax
}
};
traderConfig.updateTime.push(traderRefreshRecord);
}
/**
* Add our new trader to the database
* @param traderDetailsToAdd trader details
* @param tables database
* @param jsonUtil json utility class
*/
// rome-ignore lint/suspicious/noExplicitAny: traderDetailsToAdd comes from base.json, so no type
addTraderToDb(traderDetailsToAdd, tables, jsonUtil, newAssort) {
// Add trader to trader table, key is the traders id
tables.traders[traderDetailsToAdd._id] = {
assort: jsonUtil.deserialize(jsonUtil.serialize(newAssort)), // assorts are the 'offers' trader sells, can be a single item (e.g. carton of milk) or multiple items as a collection (e.g. a gun)
base: jsonUtil.deserialize(jsonUtil.serialize(traderDetailsToAdd)), // Deserialise/serialise creates a copy of the json and allows us to cast it as an ITraderBase
questassort: jsonUtil.deserialize(jsonUtil.serialize(questAssort)) // questassort is empty as trader has no assorts unlocked by quests
};
}
/**
* Create basic data for trader + add empty assorts table for trader
* @param tables SPT db
* @param jsonUtil SPT JSON utility class
* @returns ITraderAssort
*/
createAssortTable() {
// Create a blank assort object, ready to have items added
const assortTable = {
nextResupply: 0,
items: [],
barter_scheme: {},
loyal_level_items: {}
};
return assortTable;
}
/**
* Add traders name/location/description to the locale table
* @param baseJson json file for trader (db/base.json)
* @param tables database tables
* @param fullName Complete name of trader
* @param firstName First name of trader
* @param nickName Nickname of trader
* @param location Location of trader (e.g. "Here in the cat shop")
* @param description Description of trader
*/
addTraderToLocales(baseJson, tables, fullName, firstName, nickName, location, description) {
// For each language, add locale for the new trader
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;
}
}
}
exports.TraderHelper = TraderHelper;
//# sourceMappingURL=traderHelpers.js.map

View file

@ -0,0 +1,10 @@
{
"version": 3,
"file": "traderHelpers.js",
"sourceRoot": "",
"sources": [
"traderHelpers.ts"
],
"names": [],
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,oEAA8D;AAE9D,MAAa,YAAY;IAErB;;;;;;OAMG;IACI,oBAAoB,CAAC,QAAa,EAAE,OAAe,EAAE,eAAgC,EAAE,WAAwB,EAAE,eAAuB;QAE3I,iCAAiC;QACjC,MAAM,aAAa,GAAG,KAAK,eAAe,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC;QAEpE,yFAAyF;QACzF,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,GAAG,aAAa,IAAI,eAAe,EAAE,CAAC,CAAC;IACrG,CAAC;IAED;;;;;;OAMG;IACI,mBAAmB,CAAC,YAA2B,EAAE,QAAa,EAAE,qBAA6B,EAAE,qBAA6B;QAE/H,wCAAwC;QACxC,MAAM,mBAAmB,GAAe;YACpC,QAAQ,EAAE,QAAQ,CAAC,GAAG;YACtB,OAAO,EAAE;gBACL,GAAG,EAAE,qBAAqB;gBAC1B,GAAG,EAAE,qBAAqB;aAC7B;SAAE,CAAC;QAER,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACtD,CAAC;IAED;;;;;OAKG;IACH,iGAAiG;IAC1F,aAAa,CAAC,kBAAuB,EAAE,MAAuB,EAAE,QAAkB,EAAE,SAAc;QAErG,oDAAoD;QACpD,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG;YACrC,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,CAAkB,EAAE,mIAAmI;YACjN,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAgB,EAAE,8FAA8F;YACjL,WAAW,EAAE,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAE,mEAAmE;SAC1I,CAAC;IACN,CAAC;IAED;;;;;OAKG;IACK,iBAAiB;QAErB,0DAA0D;QAC1D,MAAM,WAAW,GAAkB;YAC/B,YAAY,EAAE,CAAC;YACf,KAAK,EAAE,EAAE;YACT,aAAa,EAAE,EAAE;YACjB,iBAAiB,EAAE,EAAE;SACxB,CAAA;QAED,OAAO,WAAW,CAAC;IACvB,CAAC;IAED;;;;;;;;;OASG;IACI,kBAAkB,CAAC,QAAa,EAAE,MAAuB,EAAE,QAAgB,EAAE,SAAiB,EAAE,QAAgB,EAAE,QAAgB,EAAE,WAAmB;QAE1J,mDAAmD;QACnD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAA6B,CAAC;QACjF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,WAAW,CAAC,GAAG,QAAQ,CAAC;YAC9C,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,YAAY,CAAC,GAAG,SAAS,CAAC;YAChD,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,WAAW,CAAC,GAAG,QAAQ,CAAC;YAC9C,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,WAAW,CAAC,GAAG,QAAQ,CAAC;YAC9C,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,cAAc,CAAC,GAAG,WAAW,CAAC;QACxD,CAAC;IACL,CAAC;CACJ;AAhGD,oCAgGC"
}