Compare commits

..

No commits in common. "e616094edabffdcdcc191516eec07b7c1094027f" and "4a3a3de300a03f83d06d7e92b02843bcc8d4c16f" have entirely different histories.

10 changed files with 82 additions and 247 deletions

View File

@ -1,4 +0,0 @@
import path from "path";
export const rootDir = path.join(__dirname, "../..");
export const repoDir = path.basename(rootDir) == "build" ? path.join(rootDir, "..") : rootDir;

View File

@ -1,8 +1,9 @@
import express from "express"; import express from "express";
import path from "path"; import path from "path";
import { repoDir, rootDir } from "@/src/helpers/pathHelper";
const webuiRouter = express.Router(); const webuiRouter = express.Router();
const rootDir = path.join(__dirname, "../..");
const repoDir = path.basename(rootDir) == "build" ? path.join(rootDir, "..") : rootDir;
// Redirect / to /webui/ // Redirect / to /webui/
webuiRouter.get("/", (_req, res) => { webuiRouter.get("/", (_req, res) => {

View File

@ -1,6 +1,5 @@
import path from "path"; import path from "path";
import fs from "fs"; import fs from "fs";
import { repoDir } from "@/src/helpers/pathHelper";
interface IBuildConfig { interface IBuildConfig {
version: string; version: string;
@ -14,6 +13,8 @@ export const buildConfig: IBuildConfig = {
matchmakingBuildId: "" matchmakingBuildId: ""
}; };
const rootDir = path.join(__dirname, "../..");
const repoDir = path.basename(rootDir) == "build" ? path.join(rootDir, "..") : rootDir;
const buildConfigPath = path.join(repoDir, "static/data/buildConfig.json"); const buildConfigPath = path.join(repoDir, "static/data/buildConfig.json");
if (fs.existsSync(buildConfigPath)) { if (fs.existsSync(buildConfigPath)) {
Object.assign(buildConfig, JSON.parse(fs.readFileSync(buildConfigPath, "utf-8")) as IBuildConfig); Object.assign(buildConfig, JSON.parse(fs.readFileSync(buildConfigPath, "utf-8")) as IBuildConfig);

View File

@ -1,9 +1,10 @@
import path from "path";
import fs from "fs"; import fs from "fs";
import fsPromises from "fs/promises"; import fsPromises from "fs/promises";
import path from "path";
import { repoDir } from "@/src/helpers/pathHelper";
import { logger } from "@/src/utils/logger"; import { logger } from "@/src/utils/logger";
const rootDir = path.join(__dirname, "../..");
const repoDir = path.basename(rootDir) == "build" ? path.join(rootDir, "..") : rootDir;
const configPath = path.join(repoDir, "config.json"); const configPath = path.join(repoDir, "config.json");
export const config = JSON.parse(fs.readFileSync(configPath, "utf-8")) as IConfig; export const config = JSON.parse(fs.readFileSync(configPath, "utf-8")) as IConfig;

View File

@ -69,7 +69,7 @@ import { addStartingGear } from "@/src/controllers/api/giveStartingGearControlle
import { addQuestKey, completeQuest } from "@/src/services/questService"; import { addQuestKey, completeQuest } from "@/src/services/questService";
import { handleBundleAcqusition } from "./purchaseService"; import { handleBundleAcqusition } from "./purchaseService";
import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json"; import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
import { getRandomElement, getRandomInt, SRng } from "./rngService"; import { getRandomElement, getRandomInt } from "./rngService";
import { createMessage } from "./inboxService"; import { createMessage } from "./inboxService";
export const createInventory = async ( export const createInventory = async (
@ -230,8 +230,7 @@ export const addItem = async (
inventory: TInventoryDatabaseDocument, inventory: TInventoryDatabaseDocument,
typeName: string, typeName: string,
quantity: number = 1, quantity: number = 1,
premiumPurchase: boolean = false, premiumPurchase: boolean = false
seed?: bigint
): Promise<IInventoryChanges> => { ): Promise<IInventoryChanges> => {
// Bundles are technically StoreItems but a) they don't have a normal counterpart, and b) they are used in non-StoreItem contexts, e.g. email attachments. // Bundles are technically StoreItems but a) they don't have a normal counterpart, and b) they are used in non-StoreItem contexts, e.g. email attachments.
if (typeName in ExportBundles) { if (typeName in ExportBundles) {
@ -381,31 +380,21 @@ export const addItem = async (
defaultOverwrites.Features = EquipmentFeatures.DOUBLE_CAPACITY; defaultOverwrites.Features = EquipmentFeatures.DOUBLE_CAPACITY;
} }
if (weapon.maxLevelCap == 40 && typeName.indexOf("BallasSword") == -1) { if (weapon.maxLevelCap == 40 && typeName.indexOf("BallasSword") == -1) {
if (!seed) {
seed = BigInt(Math.round(Math.random() * Number.MAX_SAFE_INTEGER));
}
const rng = new SRng(seed);
const tag = rng.randomElement([
"InnateElectricityDamage",
"InnateFreezeDamage",
"InnateHeatDamage",
"InnateImpactDamage",
"InnateMagDamage",
"InnateRadDamage",
"InnateToxinDamage"
]);
const WeaponUpgradeValueAttenuationExponent = 2.25;
let value = Math.pow(rng.randomFloat(), WeaponUpgradeValueAttenuationExponent);
if (value >= 0.941428) {
value = 1;
}
defaultOverwrites.UpgradeType = "/Lotus/Weapons/Grineer/KuvaLich/Upgrades/InnateDamageRandomMod"; defaultOverwrites.UpgradeType = "/Lotus/Weapons/Grineer/KuvaLich/Upgrades/InnateDamageRandomMod";
defaultOverwrites.UpgradeFingerprint = JSON.stringify({ defaultOverwrites.UpgradeFingerprint = JSON.stringify({
compat: typeName, compat: typeName,
buffs: [ buffs: [
{ {
Tag: tag, Tag: getRandomElement([
Value: Math.trunc(value * 0x40000000) "InnateElectricityDamage",
"InnateFreezeDamage",
"InnateHeatDamage",
"InnateImpactDamage",
"InnateMagDamage",
"InnateRadDamage",
"InnateToxinDamage"
]),
Value: Math.trunc(Math.random() * 0x40000000)
} }
] ]
}); });

View File

@ -51,7 +51,6 @@ export const handlePurchase = async (
logger.debug("purchase request", purchaseRequest); logger.debug("purchase request", purchaseRequest);
const prePurchaseInventoryChanges: IInventoryChanges = {}; const prePurchaseInventoryChanges: IInventoryChanges = {};
let seed: bigint | undefined;
if (purchaseRequest.PurchaseParams.Source == 7) { if (purchaseRequest.PurchaseParams.Source == 7) {
const rawManifest = getVendorManifestByOid(purchaseRequest.PurchaseParams.SourceId!); const rawManifest = getVendorManifestByOid(purchaseRequest.PurchaseParams.SourceId!);
if (rawManifest) { if (rawManifest) {
@ -75,9 +74,6 @@ export const handlePurchase = async (
prePurchaseInventoryChanges prePurchaseInventoryChanges
); );
} }
if (offer.LocTagRandSeed !== undefined) {
seed = BigInt(offer.LocTagRandSeed);
}
if (!config.noVendorPurchaseLimits && ItemId) { if (!config.noVendorPurchaseLimits && ItemId) {
inventory.RecentVendorPurchases ??= []; inventory.RecentVendorPurchases ??= [];
let vendorPurchases = inventory.RecentVendorPurchases.find( let vendorPurchases = inventory.RecentVendorPurchases.find(
@ -140,10 +136,7 @@ export const handlePurchase = async (
const purchaseResponse = await handleStoreItemAcquisition( const purchaseResponse = await handleStoreItemAcquisition(
purchaseRequest.PurchaseParams.StoreItem, purchaseRequest.PurchaseParams.StoreItem,
inventory, inventory,
purchaseRequest.PurchaseParams.Quantity, purchaseRequest.PurchaseParams.Quantity
undefined,
undefined,
seed
); );
combineInventoryChanges(purchaseResponse.InventoryChanges, prePurchaseInventoryChanges); combineInventoryChanges(purchaseResponse.InventoryChanges, prePurchaseInventoryChanges);
@ -331,8 +324,7 @@ export const handleStoreItemAcquisition = async (
inventory: TInventoryDatabaseDocument, inventory: TInventoryDatabaseDocument,
quantity: number = 1, quantity: number = 1,
durability: TRarity = "COMMON", durability: TRarity = "COMMON",
ignorePurchaseQuantity: boolean = false, ignorePurchaseQuantity: boolean = false
seed?: bigint
): Promise<IPurchaseResponse> => { ): Promise<IPurchaseResponse> => {
let purchaseResponse = { let purchaseResponse = {
InventoryChanges: {} InventoryChanges: {}
@ -353,7 +345,7 @@ export const handleStoreItemAcquisition = async (
} }
switch (storeCategory) { switch (storeCategory) {
default: { default: {
purchaseResponse = { InventoryChanges: await addItem(inventory, internalName, quantity, true, seed) }; purchaseResponse = { InventoryChanges: await addItem(inventory, internalName, quantity, true) };
break; break;
} }
case "Types": case "Types":

View File

@ -127,13 +127,4 @@ export class SRng {
} }
return min; return min;
} }
randomElement<T>(arr: T[]): T {
return arr[this.randomInt(0, arr.length - 1)];
}
randomFloat(): number {
this.state = (0x5851f42d4c957f2dn * this.state + 0x14057b7ef767814fn) & 0xffffffffffffffffn;
return (Number(this.state >> 38n) & 0xffffff) * 0.000000059604645;
}
} }

View File

@ -1,47 +1,69 @@
import fs from "fs";
import path from "path";
import { repoDir } from "@/src/helpers/pathHelper";
import { CRng, mixSeeds } from "@/src/services/rngService"; import { CRng, mixSeeds } from "@/src/services/rngService";
import { IMongoDate } from "@/src/types/commonTypes"; import { IMongoDate } from "@/src/types/commonTypes";
import { IVendorManifest, IVendorManifestPreprocessed } from "@/src/types/vendorTypes"; import { IVendorManifest, IVendorManifestPreprocessed } from "@/src/types/vendorTypes";
import { JSONParse } from "json-with-bigint";
const getVendorManifestJson = (name: string): IVendorManifest => { import ArchimedeanVendorManifest from "@/static/fixed_responses/getVendorInfo/ArchimedeanVendorManifest.json";
return JSONParse(fs.readFileSync(path.join(repoDir, `static/fixed_responses/getVendorInfo/${name}.json`), "utf-8")); import DeimosEntratiFragmentVendorProductsManifest from "@/static/fixed_responses/getVendorInfo/DeimosEntratiFragmentVendorProductsManifest.json";
}; import DeimosFishmongerVendorManifest from "@/static/fixed_responses/getVendorInfo/DeimosFishmongerVendorManifest.json";
import DeimosHivemindCommisionsManifestFishmonger from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestFishmonger.json";
import DeimosHivemindCommisionsManifestPetVendor from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestPetVendor.json";
import DeimosHivemindCommisionsManifestProspector from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestProspector.json";
import DeimosHivemindCommisionsManifestTokenVendor from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestTokenVendor.json";
import DeimosHivemindCommisionsManifestWeaponsmith from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestWeaponsmith.json";
import DeimosHivemindTokenVendorManifest from "@/static/fixed_responses/getVendorInfo/DeimosHivemindTokenVendorManifest.json";
import DeimosPetVendorManifest from "@/static/fixed_responses/getVendorInfo/DeimosPetVendorManifest.json";
import DeimosProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/DeimosProspectorVendorManifest.json";
import DuviriAcrithisVendorManifest from "@/static/fixed_responses/getVendorInfo/DuviriAcrithisVendorManifest.json";
import EntratiLabsEntratiLabsCommisionsManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabsCommisionsManifest.json";
import EntratiLabsEntratiLabVendorManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabVendorManifest.json";
import GuildAdvertisementVendorManifest from "@/static/fixed_responses/getVendorInfo/GuildAdvertisementVendorManifest.json";
import HubsIronwakeDondaVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsIronwakeDondaVendorManifest.json";
import HubsPerrinSequenceWeaponVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsPerrinSequenceWeaponVendorManifest.json";
import HubsRailjackCrewMemberVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsRailjackCrewMemberVendorManifest.json";
import MaskSalesmanManifest from "@/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json";
import Nova1999ConquestShopManifest from "@/static/fixed_responses/getVendorInfo/Nova1999ConquestShopManifest.json";
import OstronFishmongerVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronFishmongerVendorManifest.json";
import OstronPetVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronPetVendorManifest.json";
import OstronProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronProspectorVendorManifest.json";
import RadioLegionIntermission12VendorManifest from "@/static/fixed_responses/getVendorInfo/RadioLegionIntermission12VendorManifest.json";
import SolarisDebtTokenVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorManifest.json";
import SolarisDebtTokenVendorRepossessionsManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorRepossessionsManifest.json";
import SolarisFishmongerVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisFishmongerVendorManifest.json";
import SolarisProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisProspectorVendorManifest.json";
import TeshinHardModeVendorManifest from "@/static/fixed_responses/getVendorInfo/TeshinHardModeVendorManifest.json";
import ZarimanCommisionsManifestArchimedean from "@/static/fixed_responses/getVendorInfo/ZarimanCommisionsManifestArchimedean.json";
const vendorManifests: IVendorManifest[] = [ const vendorManifests: IVendorManifest[] = [
getVendorManifestJson("ArchimedeanVendorManifest"), ArchimedeanVendorManifest,
getVendorManifestJson("DeimosEntratiFragmentVendorProductsManifest"), DeimosEntratiFragmentVendorProductsManifest,
getVendorManifestJson("DeimosFishmongerVendorManifest"), DeimosFishmongerVendorManifest,
getVendorManifestJson("DeimosHivemindCommisionsManifestFishmonger"), DeimosHivemindCommisionsManifestFishmonger,
getVendorManifestJson("DeimosHivemindCommisionsManifestPetVendor"), DeimosHivemindCommisionsManifestPetVendor,
getVendorManifestJson("DeimosHivemindCommisionsManifestProspector"), DeimosHivemindCommisionsManifestProspector,
getVendorManifestJson("DeimosHivemindCommisionsManifestTokenVendor"), DeimosHivemindCommisionsManifestTokenVendor,
getVendorManifestJson("DeimosHivemindCommisionsManifestWeaponsmith"), DeimosHivemindCommisionsManifestWeaponsmith,
getVendorManifestJson("DeimosHivemindTokenVendorManifest"), DeimosHivemindTokenVendorManifest,
getVendorManifestJson("DeimosPetVendorManifest"), DeimosPetVendorManifest,
getVendorManifestJson("DeimosProspectorVendorManifest"), DeimosProspectorVendorManifest,
getVendorManifestJson("DuviriAcrithisVendorManifest"), DuviriAcrithisVendorManifest,
getVendorManifestJson("EntratiLabsEntratiLabsCommisionsManifest"), EntratiLabsEntratiLabsCommisionsManifest,
getVendorManifestJson("EntratiLabsEntratiLabVendorManifest"), EntratiLabsEntratiLabVendorManifest,
getVendorManifestJson("GuildAdvertisementVendorManifest"), // uses preprocessing GuildAdvertisementVendorManifest, // uses preprocessing
getVendorManifestJson("HubsIronwakeDondaVendorManifest"), // uses preprocessing HubsIronwakeDondaVendorManifest, // uses preprocessing
getVendorManifestJson("HubsPerrinSequenceWeaponVendorManifest"), HubsPerrinSequenceWeaponVendorManifest,
getVendorManifestJson("HubsRailjackCrewMemberVendorManifest"), HubsRailjackCrewMemberVendorManifest,
getVendorManifestJson("InfestedLichWeaponVendorManifest"), MaskSalesmanManifest,
getVendorManifestJson("MaskSalesmanManifest"), Nova1999ConquestShopManifest,
getVendorManifestJson("Nova1999ConquestShopManifest"), OstronFishmongerVendorManifest,
getVendorManifestJson("OstronFishmongerVendorManifest"), OstronPetVendorManifest,
getVendorManifestJson("OstronPetVendorManifest"), OstronProspectorVendorManifest,
getVendorManifestJson("OstronProspectorVendorManifest"), RadioLegionIntermission12VendorManifest,
getVendorManifestJson("RadioLegionIntermission12VendorManifest"), SolarisDebtTokenVendorManifest,
getVendorManifestJson("SolarisDebtTokenVendorManifest"), SolarisDebtTokenVendorRepossessionsManifest,
getVendorManifestJson("SolarisDebtTokenVendorRepossessionsManifest"), SolarisFishmongerVendorManifest,
getVendorManifestJson("SolarisFishmongerVendorManifest"), SolarisProspectorVendorManifest,
getVendorManifestJson("SolarisProspectorVendorManifest"), TeshinHardModeVendorManifest, // uses preprocessing
getVendorManifestJson("TeshinHardModeVendorManifest"), // uses preprocessing ZarimanCommisionsManifestArchimedean
getVendorManifestJson("ZarimanCommisionsManifestArchimedean")
]; ];
export const getVendorManifestByTypeName = (typeName: string): IVendorManifest | undefined => { export const getVendorManifestByTypeName = (typeName: string): IVendorManifest | undefined => {

View File

@ -19,7 +19,6 @@ interface IItemManifest {
PurchaseQuantityLimit?: number; PurchaseQuantityLimit?: number;
RotatedWeekly?: boolean; RotatedWeekly?: boolean;
AllowMultipurchase: boolean; AllowMultipurchase: boolean;
LocTagRandSeed?: number | bigint;
Id: IOid; Id: IOid;
} }

View File

@ -1,157 +0,0 @@
{
"VendorInfo": {
"_id": {
"$oid": "67dadc30e4b6e0e5979c8d84"
},
"TypeName": "/Lotus/Types/Game/VendorManifests/TheHex/InfestedLichWeaponVendorManifest",
"ItemManifest": [
{
"StoreItem": "/Lotus/StoreItems/Weapons/Infested/InfestedLich/LongGuns/1999InfShotgun/1999InfShotgunWeapon",
"ItemPrices": [
{
"ItemCount": 10,
"ItemType": "/Lotus/Types/Items/MiscItems/CodaWeaponBucks",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999999999"
}
},
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"LocTagRandSeed": 65079176837546984,
"Id": {
"$oid": "67e9da12793a120dbbc1c193"
}
},
{
"StoreItem": "/Lotus/StoreItems/Weapons/Infested/InfestedLich/Melee/CodaCaustacyst/CodaCaustacyst",
"ItemPrices": [
{
"ItemCount": 10,
"ItemType": "/Lotus/Types/Items/MiscItems/CodaWeaponBucks",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999999999"
}
},
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"LocTagRandSeed": 5687904240491804000,
"Id": {
"$oid": "67e9da12793a120dbbc1c194"
}
},
{
"StoreItem": "/Lotus/StoreItems/Weapons/Infested/InfestedLich/Melee/CodaPathocyst/CodaPathocyst",
"ItemPrices": [
{
"ItemCount": 10,
"ItemType": "/Lotus/Types/Items/MiscItems/CodaWeaponBucks",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999999999"
}
},
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"LocTagRandSeed": 6177144662234093000,
"Id": {
"$oid": "67e9da12793a120dbbc1c195"
}
},
{
"StoreItem": "/Lotus/StoreItems/Weapons/Infested/InfestedLich/Pistols/CodaTysis",
"ItemPrices": [
{
"ItemCount": 10,
"ItemType": "/Lotus/Types/Items/MiscItems/CodaWeaponBucks",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999999999"
}
},
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"LocTagRandSeed": 1988275604378227700,
"Id": {
"$oid": "67e9da12793a120dbbc1c196"
}
},
{
"StoreItem": "/Lotus/StoreItems/Weapons/Infested/InfestedLich/LongGuns/CodaSynapse",
"ItemPrices": [
{
"ItemCount": 10,
"ItemType": "/Lotus/Types/Items/MiscItems/CodaWeaponBucks",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999999999"
}
},
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"LocTagRandSeed": 8607452585593957000,
"Id": {
"$oid": "67e9da12793a120dbbc1c197"
}
},
{
"StoreItem": "/Lotus/StoreItems/Weapons/Infested/InfestedLich/Melee/CodaHirudo",
"ItemPrices": [
{
"ItemCount": 10,
"ItemType": "/Lotus/Types/Items/MiscItems/CodaWeaponBucks",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999999999"
}
},
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"LocTagRandSeed": 8385013066220909000,
"Id": {
"$oid": "67e9da12793a120dbbc1c198"
}
}
],
"PropertyTextHash": "77093DD05A8561A022DEC9A4B9BB4A56",
"RandomSeedType": "VRST_WEAPON",
"RequiredGoalTag": "",
"WeaponUpgradeValueAttenuationExponent": 2.25,
"Expiry": {
"$date": {
"$numberLong": "9999999999999"
}
}
}
}