chore(webui): improving inconsistent, long string #2344
							
								
								
									
										8
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -18,7 +18,7 @@
 | 
				
			|||||||
        "morgan": "^1.10.0",
 | 
					        "morgan": "^1.10.0",
 | 
				
			||||||
        "ncp": "^2.0.0",
 | 
					        "ncp": "^2.0.0",
 | 
				
			||||||
        "typescript": "^5.5",
 | 
					        "typescript": "^5.5",
 | 
				
			||||||
        "warframe-public-export-plus": "^0.5.66",
 | 
					        "warframe-public-export-plus": "^0.5.67",
 | 
				
			||||||
        "warframe-riven-info": "^0.1.2",
 | 
					        "warframe-riven-info": "^0.1.2",
 | 
				
			||||||
        "winston": "^3.17.0",
 | 
					        "winston": "^3.17.0",
 | 
				
			||||||
        "winston-daily-rotate-file": "^5.0.0"
 | 
					        "winston-daily-rotate-file": "^5.0.0"
 | 
				
			||||||
@ -3814,9 +3814,9 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/warframe-public-export-plus": {
 | 
					    "node_modules/warframe-public-export-plus": {
 | 
				
			||||||
      "version": "0.5.66",
 | 
					      "version": "0.5.67",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.66.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.67.tgz",
 | 
				
			||||||
      "integrity": "sha512-AU7XQA96OfYrLm2RioCwDjjdI3IrsmUiqebXyE+bpM0iST+4x/NHu8LTRT4Oygfo/2OBtDYhib7G6re0EeAe5g=="
 | 
					      "integrity": "sha512-LsnZD2E5PTA+5MK9kDGvM/hFDtg8sb0EwQ4hKH5ILqrSgz30a9W8785v77RSsL1AEVF8dfb/lZcSTCJq1DZHzQ=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/warframe-riven-info": {
 | 
					    "node_modules/warframe-riven-info": {
 | 
				
			||||||
      "version": "0.1.2",
 | 
					      "version": "0.1.2",
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@
 | 
				
			|||||||
    "morgan": "^1.10.0",
 | 
					    "morgan": "^1.10.0",
 | 
				
			||||||
    "ncp": "^2.0.0",
 | 
					    "ncp": "^2.0.0",
 | 
				
			||||||
    "typescript": "^5.5",
 | 
					    "typescript": "^5.5",
 | 
				
			||||||
    "warframe-public-export-plus": "^0.5.66",
 | 
					    "warframe-public-export-plus": "^0.5.67",
 | 
				
			||||||
    "warframe-riven-info": "^0.1.2",
 | 
					    "warframe-riven-info": "^0.1.2",
 | 
				
			||||||
    "winston": "^3.17.0",
 | 
					    "winston": "^3.17.0",
 | 
				
			||||||
    "winston-daily-rotate-file": "^5.0.0"
 | 
					    "winston-daily-rotate-file": "^5.0.0"
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,7 @@ export const saveDialogueController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
        inventory.DialogueHistory.Dialogues ??= [];
 | 
					        inventory.DialogueHistory.Dialogues ??= [];
 | 
				
			||||||
        const dialogue = getDialogue(inventory, request.DialogueName);
 | 
					        const dialogue = getDialogue(inventory, request.DialogueName);
 | 
				
			||||||
        dialogue.Rank = request.Rank;
 | 
					        dialogue.Rank = request.Rank;
 | 
				
			||||||
        dialogue.Chemistry = request.Chemistry;
 | 
					        dialogue.Chemistry += request.Chemistry;
 | 
				
			||||||
        dialogue.QueuedDialogues = request.QueuedDialogues;
 | 
					        dialogue.QueuedDialogues = request.QueuedDialogues;
 | 
				
			||||||
        for (const bool of request.Booleans) {
 | 
					        for (const bool of request.Booleans) {
 | 
				
			||||||
            dialogue.Booleans.push(bool);
 | 
					            dialogue.Booleans.push(bool);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,14 @@
 | 
				
			|||||||
// First, init config.
 | 
					// First, init config.
 | 
				
			||||||
import { config, loadConfig } from "@/src/services/configService";
 | 
					import { config, loadConfig } from "@/src/services/configService";
 | 
				
			||||||
 | 
					import fs from "fs";
 | 
				
			||||||
try {
 | 
					try {
 | 
				
			||||||
    loadConfig();
 | 
					    loadConfig();
 | 
				
			||||||
} catch (e) {
 | 
					} catch (e) {
 | 
				
			||||||
    console.log("ERROR: Failed to load config.json. You can copy config.json.example to create your config.json.");
 | 
					    if (fs.existsSync("config.json")) {
 | 
				
			||||||
 | 
					        console.log("Failed to load config.json: " + (e as Error).message);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        console.log("Failed to load config.json. You can copy config.json.example to create your config.json.");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    process.exit(1);
 | 
					    process.exit(1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ fs.watchFile(configPath, () => {
 | 
				
			|||||||
        try {
 | 
					        try {
 | 
				
			||||||
            loadConfig();
 | 
					            loadConfig();
 | 
				
			||||||
        } catch (e) {
 | 
					        } catch (e) {
 | 
				
			||||||
            logger.error("Failed to reload config.json. Did you delete it?! Execution cannot continue.");
 | 
					            logger.error("FATAL ERROR: Config failed to be reloaded: " + (e as Error).message);
 | 
				
			||||||
            process.exit(1);
 | 
					            process.exit(1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        validateConfig();
 | 
					        validateConfig();
 | 
				
			||||||
 | 
				
			|||||||
@ -66,15 +66,7 @@ import {
 | 
				
			|||||||
} from "@/src/helpers/nemesisHelpers";
 | 
					} from "@/src/helpers/nemesisHelpers";
 | 
				
			||||||
import { Loadout } from "../models/inventoryModels/loadoutModel";
 | 
					import { Loadout } from "../models/inventoryModels/loadoutModel";
 | 
				
			||||||
import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes";
 | 
					import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes";
 | 
				
			||||||
import {
 | 
					import { getLiteSortie, getSortie, idToBountyCycle, idToDay, idToWeek, pushClassicBounties } from "./worldStateService";
 | 
				
			||||||
    getLiteSortie,
 | 
					 | 
				
			||||||
    getSortie,
 | 
					 | 
				
			||||||
    getWorldState,
 | 
					 | 
				
			||||||
    idToBountyCycle,
 | 
					 | 
				
			||||||
    idToDay,
 | 
					 | 
				
			||||||
    idToWeek,
 | 
					 | 
				
			||||||
    pushClassicBounties
 | 
					 | 
				
			||||||
} from "./worldStateService";
 | 
					 | 
				
			||||||
import { config } from "./configService";
 | 
					import { config } from "./configService";
 | 
				
			||||||
import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
 | 
					import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
 | 
				
			||||||
import { ISyndicateMissionInfo } from "../types/worldStateTypes";
 | 
					import { ISyndicateMissionInfo } from "../types/worldStateTypes";
 | 
				
			||||||
@ -1266,9 +1258,9 @@ export const addMissionRewards = async (
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (rewardInfo.challengeMissionId) {
 | 
					    if (rewardInfo.challengeMissionId) {
 | 
				
			||||||
        const [syndicateTag, tierStr, chemistryStr] = rewardInfo.challengeMissionId.split("_");
 | 
					        const [syndicateTag, tierStr, chemistryBuddyStr] = rewardInfo.challengeMissionId.split("_");
 | 
				
			||||||
        const tier = Number(tierStr);
 | 
					        const tier = Number(tierStr);
 | 
				
			||||||
        const chemistry = Number(chemistryStr);
 | 
					        const chemistryBuddy = Number(chemistryBuddyStr);
 | 
				
			||||||
        const isSteelPath = missions?.Tier;
 | 
					        const isSteelPath = missions?.Tier;
 | 
				
			||||||
        if (syndicateTag === "ZarimanSyndicate") {
 | 
					        if (syndicateTag === "ZarimanSyndicate") {
 | 
				
			||||||
            let medallionAmount = tier + 1;
 | 
					            let medallionAmount = tier + 1;
 | 
				
			||||||
@ -1285,22 +1277,19 @@ export const addMissionRewards = async (
 | 
				
			|||||||
            if (isSteelPath) standingAmount *= 1.5;
 | 
					            if (isSteelPath) standingAmount *= 1.5;
 | 
				
			||||||
            addStanding(inventory, syndicateTag, standingAmount, AffiliationMods);
 | 
					            addStanding(inventory, syndicateTag, standingAmount, AffiliationMods);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (syndicateTag == "HexSyndicate" && chemistry && tier < 6) {
 | 
					        if (syndicateTag == "HexSyndicate" && tier < 6) {
 | 
				
			||||||
            const seed = getWorldState().SyndicateMissions.find(x => x.Tag == "HexSyndicate")!.Seed;
 | 
					            const buddy = chemistryBuddies[chemistryBuddy];
 | 
				
			||||||
            const { nodes, buddies } = getHexBounties(seed);
 | 
					 | 
				
			||||||
            const buddy = buddies[tier];
 | 
					 | 
				
			||||||
            logger.debug(`Hex seed is ${seed}, giving chemistry for ${buddy}`);
 | 
					 | 
				
			||||||
            if (missions?.Tag != nodes[tier]) {
 | 
					 | 
				
			||||||
                logger.warn(
 | 
					 | 
				
			||||||
                    `Uh-oh, tier ${tier} bounty should've been on ${nodes[tier]} but you were just on ${missions?.Tag}`
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            const tomorrowAt0Utc = config.noKimCooldowns
 | 
					 | 
				
			||||||
                ? Date.now()
 | 
					 | 
				
			||||||
                : (Math.trunc(Date.now() / 86400_000) + 1) * 86400_000;
 | 
					 | 
				
			||||||
            const dialogue = getDialogue(inventory, buddy);
 | 
					            const dialogue = getDialogue(inventory, buddy);
 | 
				
			||||||
            dialogue.Chemistry += chemistry;
 | 
					            if (Date.now() >= dialogue.BountyChemExpiry.getTime()) {
 | 
				
			||||||
            dialogue.BountyChemExpiry = new Date(tomorrowAt0Utc);
 | 
					                logger.debug(`Giving 20 chemistry for ${buddy}`);
 | 
				
			||||||
 | 
					                const tomorrowAt0Utc = config.noKimCooldowns
 | 
				
			||||||
 | 
					                    ? Date.now()
 | 
				
			||||||
 | 
					                    : (Math.trunc(Date.now() / 86400_000) + 1) * 86400_000;
 | 
				
			||||||
 | 
					                dialogue.Chemistry += 20;
 | 
				
			||||||
 | 
					                dialogue.BountyChemExpiry = new Date(tomorrowAt0Utc);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                logger.debug(`Already got today's chemistry for ${buddy}`);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (isSteelPath) {
 | 
					        if (isSteelPath) {
 | 
				
			||||||
            await addItem(inventory, "/Lotus/Types/Items/MiscItems/SteelEssence", 1);
 | 
					            await addItem(inventory, "/Lotus/Types/Items/MiscItems/SteelEssence", 1);
 | 
				
			||||||
@ -1864,7 +1853,16 @@ const libraryPersonalTargetToAvatar: Record<string, string> = {
 | 
				
			|||||||
        "/Lotus/Types/Enemies/Corpus/Spaceman/AIWeek/NullifySpacemanAvatar"
 | 
					        "/Lotus/Types/Enemies/Corpus/Spaceman/AIWeek/NullifySpacemanAvatar"
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const node_excluded_buddies: Record<string, string> = {
 | 
					const chemistryBuddies: readonly string[] = [
 | 
				
			||||||
 | 
					    "/Lotus/Types/Gameplay/1999Wf/Dialogue/JabirDialogue_rom.dialogue",
 | 
				
			||||||
 | 
					    "/Lotus/Types/Gameplay/1999Wf/Dialogue/AoiDialogue_rom.dialogue",
 | 
				
			||||||
 | 
					    "/Lotus/Types/Gameplay/1999Wf/Dialogue/ArthurDialogue_rom.dialogue",
 | 
				
			||||||
 | 
					    "/Lotus/Types/Gameplay/1999Wf/Dialogue/EleanorDialogue_rom.dialogue",
 | 
				
			||||||
 | 
					    "/Lotus/Types/Gameplay/1999Wf/Dialogue/LettieDialogue_rom.dialogue",
 | 
				
			||||||
 | 
					    "/Lotus/Types/Gameplay/1999Wf/Dialogue/QuincyDialogue_rom.dialogue"
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*const node_excluded_buddies: Record<string, string> = {
 | 
				
			||||||
    SolNode856: "/Lotus/Types/Gameplay/1999Wf/Dialogue/ArthurDialogue_rom.dialogue",
 | 
					    SolNode856: "/Lotus/Types/Gameplay/1999Wf/Dialogue/ArthurDialogue_rom.dialogue",
 | 
				
			||||||
    SolNode852: "/Lotus/Types/Gameplay/1999Wf/Dialogue/LettieDialogue_rom.dialogue",
 | 
					    SolNode852: "/Lotus/Types/Gameplay/1999Wf/Dialogue/LettieDialogue_rom.dialogue",
 | 
				
			||||||
    SolNode851: "/Lotus/Types/Gameplay/1999Wf/Dialogue/JabirDialogue_rom.dialogue",
 | 
					    SolNode851: "/Lotus/Types/Gameplay/1999Wf/Dialogue/JabirDialogue_rom.dialogue",
 | 
				
			||||||
@ -1914,4 +1912,4 @@ const getHexBounties = (seed: number): { nodes: string[]; buddies: string[] } =>
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return { nodes, buddies };
 | 
					    return { nodes, buddies };
 | 
				
			||||||
};
 | 
					};*/
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ import { mixSeeds, SRng } from "@/src/services/rngService";
 | 
				
			|||||||
import { IMongoDate } from "@/src/types/commonTypes";
 | 
					import { IMongoDate } from "@/src/types/commonTypes";
 | 
				
			||||||
import { IItemManifest, IVendorInfo, IVendorManifest } from "@/src/types/vendorTypes";
 | 
					import { IItemManifest, IVendorInfo, IVendorManifest } from "@/src/types/vendorTypes";
 | 
				
			||||||
import { logger } from "@/src/utils/logger";
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
import { ExportVendors, IRange, IVendor } from "warframe-public-export-plus";
 | 
					import { ExportVendors, IRange, IVendor, IVendorOffer } from "warframe-public-export-plus";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ArchimedeanVendorManifest from "@/static/fixed_responses/getVendorInfo/ArchimedeanVendorManifest.json";
 | 
					import ArchimedeanVendorManifest from "@/static/fixed_responses/getVendorInfo/ArchimedeanVendorManifest.json";
 | 
				
			||||||
import DeimosEntratiFragmentVendorProductsManifest from "@/static/fixed_responses/getVendorInfo/DeimosEntratiFragmentVendorProductsManifest.json";
 | 
					import DeimosEntratiFragmentVendorProductsManifest from "@/static/fixed_responses/getVendorInfo/DeimosEntratiFragmentVendorProductsManifest.json";
 | 
				
			||||||
@ -17,18 +17,14 @@ import DeimosHivemindCommisionsManifestTokenVendor from "@/static/fixed_response
 | 
				
			|||||||
import DeimosHivemindCommisionsManifestWeaponsmith from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestWeaponsmith.json";
 | 
					import DeimosHivemindCommisionsManifestWeaponsmith from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestWeaponsmith.json";
 | 
				
			||||||
import DeimosHivemindTokenVendorManifest from "@/static/fixed_responses/getVendorInfo/DeimosHivemindTokenVendorManifest.json";
 | 
					import DeimosHivemindTokenVendorManifest from "@/static/fixed_responses/getVendorInfo/DeimosHivemindTokenVendorManifest.json";
 | 
				
			||||||
import DeimosPetVendorManifest from "@/static/fixed_responses/getVendorInfo/DeimosPetVendorManifest.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 DuviriAcrithisVendorManifest from "@/static/fixed_responses/getVendorInfo/DuviriAcrithisVendorManifest.json";
 | 
				
			||||||
import EntratiLabsEntratiLabsCommisionsManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabsCommisionsManifest.json";
 | 
					import EntratiLabsEntratiLabsCommisionsManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabsCommisionsManifest.json";
 | 
				
			||||||
import EntratiLabsEntratiLabVendorManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabVendorManifest.json";
 | 
					import EntratiLabsEntratiLabVendorManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabVendorManifest.json";
 | 
				
			||||||
import HubsIronwakeDondaVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsIronwakeDondaVendorManifest.json";
 | 
					 | 
				
			||||||
import HubsRailjackCrewMemberVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsRailjackCrewMemberVendorManifest.json";
 | 
					import HubsRailjackCrewMemberVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsRailjackCrewMemberVendorManifest.json";
 | 
				
			||||||
import MaskSalesmanManifest from "@/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json";
 | 
					import MaskSalesmanManifest from "@/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json";
 | 
				
			||||||
import Nova1999ConquestShopManifest from "@/static/fixed_responses/getVendorInfo/Nova1999ConquestShopManifest.json";
 | 
					import Nova1999ConquestShopManifest from "@/static/fixed_responses/getVendorInfo/Nova1999ConquestShopManifest.json";
 | 
				
			||||||
import OstronPetVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronPetVendorManifest.json";
 | 
					import OstronPetVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronPetVendorManifest.json";
 | 
				
			||||||
import OstronProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronProspectorVendorManifest.json";
 | 
					 | 
				
			||||||
import SolarisDebtTokenVendorRepossessionsManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorRepossessionsManifest.json";
 | 
					import SolarisDebtTokenVendorRepossessionsManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorRepossessionsManifest.json";
 | 
				
			||||||
import SolarisProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisProspectorVendorManifest.json";
 | 
					 | 
				
			||||||
import Temple1999VendorManifest from "@/static/fixed_responses/getVendorInfo/Temple1999VendorManifest.json";
 | 
					import Temple1999VendorManifest from "@/static/fixed_responses/getVendorInfo/Temple1999VendorManifest.json";
 | 
				
			||||||
import TeshinHardModeVendorManifest from "@/static/fixed_responses/getVendorInfo/TeshinHardModeVendorManifest.json";
 | 
					import TeshinHardModeVendorManifest from "@/static/fixed_responses/getVendorInfo/TeshinHardModeVendorManifest.json";
 | 
				
			||||||
import ZarimanCommisionsManifestArchimedean from "@/static/fixed_responses/getVendorInfo/ZarimanCommisionsManifestArchimedean.json";
 | 
					import ZarimanCommisionsManifestArchimedean from "@/static/fixed_responses/getVendorInfo/ZarimanCommisionsManifestArchimedean.json";
 | 
				
			||||||
@ -43,18 +39,14 @@ const rawVendorManifests: IVendorManifest[] = [
 | 
				
			|||||||
    DeimosHivemindCommisionsManifestWeaponsmith,
 | 
					    DeimosHivemindCommisionsManifestWeaponsmith,
 | 
				
			||||||
    DeimosHivemindTokenVendorManifest,
 | 
					    DeimosHivemindTokenVendorManifest,
 | 
				
			||||||
    DeimosPetVendorManifest,
 | 
					    DeimosPetVendorManifest,
 | 
				
			||||||
    DeimosProspectorVendorManifest,
 | 
					 | 
				
			||||||
    DuviriAcrithisVendorManifest,
 | 
					    DuviriAcrithisVendorManifest,
 | 
				
			||||||
    EntratiLabsEntratiLabsCommisionsManifest,
 | 
					    EntratiLabsEntratiLabsCommisionsManifest,
 | 
				
			||||||
    EntratiLabsEntratiLabVendorManifest,
 | 
					    EntratiLabsEntratiLabVendorManifest,
 | 
				
			||||||
    HubsIronwakeDondaVendorManifest, // uses preprocessing
 | 
					 | 
				
			||||||
    HubsRailjackCrewMemberVendorManifest,
 | 
					    HubsRailjackCrewMemberVendorManifest,
 | 
				
			||||||
    MaskSalesmanManifest,
 | 
					    MaskSalesmanManifest,
 | 
				
			||||||
    Nova1999ConquestShopManifest,
 | 
					    Nova1999ConquestShopManifest,
 | 
				
			||||||
    OstronPetVendorManifest,
 | 
					    OstronPetVendorManifest,
 | 
				
			||||||
    OstronProspectorVendorManifest,
 | 
					 | 
				
			||||||
    SolarisDebtTokenVendorRepossessionsManifest,
 | 
					    SolarisDebtTokenVendorRepossessionsManifest,
 | 
				
			||||||
    SolarisProspectorVendorManifest,
 | 
					 | 
				
			||||||
    Temple1999VendorManifest,
 | 
					    Temple1999VendorManifest,
 | 
				
			||||||
    TeshinHardModeVendorManifest, // uses preprocessing
 | 
					    TeshinHardModeVendorManifest, // uses preprocessing
 | 
				
			||||||
    ZarimanCommisionsManifestArchimedean
 | 
					    ZarimanCommisionsManifestArchimedean
 | 
				
			||||||
@ -83,10 +75,6 @@ const generatableVendors: IGeneratableVendorInfo[] = [
 | 
				
			|||||||
        cycleOffset: 1744934400_000,
 | 
					        cycleOffset: 1744934400_000,
 | 
				
			||||||
        cycleDuration: 4 * unixTimesInMs.day
 | 
					        cycleDuration: 4 * unixTimesInMs.day
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // {
 | 
					 | 
				
			||||||
    //     _id: { $oid: "5dbb4c41e966f7886c3ce939" },
 | 
					 | 
				
			||||||
    //     TypeName: "/Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest"
 | 
					 | 
				
			||||||
    // }
 | 
					 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getVendorOid = (typeName: string): string => {
 | 
					const getVendorOid = (typeName: string): string => {
 | 
				
			||||||
@ -228,6 +216,22 @@ const toRange = (value: IRange | number): IRange => {
 | 
				
			|||||||
    return value;
 | 
					    return value;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getCycleDurationRange = (manifest: IVendor): IRange | undefined => {
 | 
				
			||||||
 | 
					    const res: IRange = { minValue: Number.MAX_SAFE_INTEGER, maxValue: 0 };
 | 
				
			||||||
 | 
					    for (const offer of manifest.items) {
 | 
				
			||||||
 | 
					        if (offer.durationHours) {
 | 
				
			||||||
 | 
					            const range = toRange(offer.durationHours);
 | 
				
			||||||
 | 
					            if (res.minValue > range.minValue) {
 | 
				
			||||||
 | 
					                res.minValue = range.minValue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (res.maxValue < range.maxValue) {
 | 
				
			||||||
 | 
					                res.maxValue = range.maxValue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return res.maxValue != 0 ? res : undefined;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const vendorManifestCache: Record<string, IVendorManifest> = {};
 | 
					const vendorManifestCache: Record<string, IVendorManifest> = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorManifest => {
 | 
					const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorManifest => {
 | 
				
			||||||
@ -244,10 +248,16 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    const cacheEntry = vendorManifestCache[vendorInfo.TypeName];
 | 
					    const cacheEntry = vendorManifestCache[vendorInfo.TypeName];
 | 
				
			||||||
    const info = cacheEntry.VendorInfo;
 | 
					    const info = cacheEntry.VendorInfo;
 | 
				
			||||||
    if (Date.now() >= parseInt(info.Expiry.$date.$numberLong)) {
 | 
					    const manifest = ExportVendors[vendorInfo.TypeName];
 | 
				
			||||||
 | 
					    const cycleDurationRange = getCycleDurationRange(manifest);
 | 
				
			||||||
 | 
					    let now = Date.now();
 | 
				
			||||||
 | 
					    if (cycleDurationRange && cycleDurationRange.minValue != cycleDurationRange.maxValue) {
 | 
				
			||||||
 | 
					        now -= (cycleDurationRange.maxValue - 1) * unixTimesInMs.hour;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    while (Date.now() >= parseInt(info.Expiry.$date.$numberLong)) {
 | 
				
			||||||
        // Remove expired offers
 | 
					        // Remove expired offers
 | 
				
			||||||
        for (let i = 0; i != info.ItemManifest.length; ) {
 | 
					        for (let i = 0; i != info.ItemManifest.length; ) {
 | 
				
			||||||
            if (Date.now() >= parseInt(info.ItemManifest[i].Expiry.$date.$numberLong)) {
 | 
					            if (now >= parseInt(info.ItemManifest[i].Expiry.$date.$numberLong)) {
 | 
				
			||||||
                info.ItemManifest.splice(i, 1);
 | 
					                info.ItemManifest.splice(i, 1);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                ++i;
 | 
					                ++i;
 | 
				
			||||||
@ -258,16 +268,10 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
 | 
				
			|||||||
        const vendorSeed = parseInt(vendorInfo._id.$oid.substring(16), 16);
 | 
					        const vendorSeed = parseInt(vendorInfo._id.$oid.substring(16), 16);
 | 
				
			||||||
        const cycleOffset = vendorInfo.cycleOffset ?? 1734307200_000;
 | 
					        const cycleOffset = vendorInfo.cycleOffset ?? 1734307200_000;
 | 
				
			||||||
        const cycleDuration = vendorInfo.cycleDuration;
 | 
					        const cycleDuration = vendorInfo.cycleDuration;
 | 
				
			||||||
        const cycleIndex = Math.trunc((Date.now() - cycleOffset) / cycleDuration);
 | 
					        const cycleIndex = Math.trunc((now - cycleOffset) / cycleDuration);
 | 
				
			||||||
        const rng = new SRng(mixSeeds(vendorSeed, cycleIndex));
 | 
					        const rng = new SRng(mixSeeds(vendorSeed, cycleIndex));
 | 
				
			||||||
        const manifest = ExportVendors[vendorInfo.TypeName];
 | 
					        const offersToAdd: IVendorOffer[] = [];
 | 
				
			||||||
        const offersToAdd = [];
 | 
					        if (!manifest.isOneBinPerCycle) {
 | 
				
			||||||
        if (
 | 
					 | 
				
			||||||
            manifest.numItems &&
 | 
					 | 
				
			||||||
            (manifest.numItems.minValue != manifest.numItems.maxValue ||
 | 
					 | 
				
			||||||
                manifest.items.length != manifest.numItems.minValue) &&
 | 
					 | 
				
			||||||
            !manifest.isOneBinPerCycle
 | 
					 | 
				
			||||||
        ) {
 | 
					 | 
				
			||||||
            const remainingItemCapacity: Record<string, number> = {};
 | 
					            const remainingItemCapacity: Record<string, number> = {};
 | 
				
			||||||
            for (const item of manifest.items) {
 | 
					            for (const item of manifest.items) {
 | 
				
			||||||
                remainingItemCapacity[item.storeItem] = 1 + item.duplicates;
 | 
					                remainingItemCapacity[item.storeItem] = 1 + item.duplicates;
 | 
				
			||||||
@ -275,31 +279,48 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
 | 
				
			|||||||
            for (const offer of info.ItemManifest) {
 | 
					            for (const offer of info.ItemManifest) {
 | 
				
			||||||
                remainingItemCapacity[offer.StoreItem] -= 1;
 | 
					                remainingItemCapacity[offer.StoreItem] -= 1;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            const numItemsTarget = rng.randomInt(manifest.numItems.minValue, manifest.numItems.maxValue);
 | 
					            if (manifest.numItems && manifest.items.length != manifest.numItems.minValue) {
 | 
				
			||||||
            while (info.ItemManifest.length + offersToAdd.length < numItemsTarget) {
 | 
					                const numItemsTarget = rng.randomInt(manifest.numItems.minValue, manifest.numItems.maxValue);
 | 
				
			||||||
                // TODO: Consider per-bin item limits
 | 
					                while (info.ItemManifest.length + offersToAdd.length < numItemsTarget) {
 | 
				
			||||||
                // TODO: Consider item probability weightings
 | 
					                    // TODO: Consider per-bin item limits
 | 
				
			||||||
                const item = rng.randomElement(manifest.items)!;
 | 
					                    // TODO: Consider item probability weightings
 | 
				
			||||||
                if (remainingItemCapacity[item.storeItem] != 0) {
 | 
					                    const item = rng.randomElement(manifest.items)!;
 | 
				
			||||||
                    remainingItemCapacity[item.storeItem] -= 1;
 | 
					                    if (remainingItemCapacity[item.storeItem] != 0) {
 | 
				
			||||||
                    offersToAdd.push(item);
 | 
					                        remainingItemCapacity[item.storeItem] -= 1;
 | 
				
			||||||
 | 
					                        offersToAdd.push(item);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                for (const item of manifest.items) {
 | 
				
			||||||
 | 
					                    if (!item.alwaysOffered && remainingItemCapacity[item.storeItem] != 0) {
 | 
				
			||||||
 | 
					                        remainingItemCapacity[item.storeItem] -= 1;
 | 
				
			||||||
 | 
					                        offersToAdd.push(item);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                for (const e of Object.entries(remainingItemCapacity)) {
 | 
				
			||||||
 | 
					                    const item = manifest.items.find(x => x.storeItem == e[0])!;
 | 
				
			||||||
 | 
					                    if (!item.alwaysOffered) {
 | 
				
			||||||
 | 
					                        while (e[1] != 0) {
 | 
				
			||||||
 | 
					                            e[1] -= 1;
 | 
				
			||||||
 | 
					                            offersToAdd.push(item);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                for (const item of manifest.items) {
 | 
				
			||||||
 | 
					                    if (item.alwaysOffered && remainingItemCapacity[item.storeItem] != 0) {
 | 
				
			||||||
 | 
					                        remainingItemCapacity[item.storeItem] -= 1;
 | 
				
			||||||
 | 
					                        offersToAdd.push(item);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                offersToAdd.reverse();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            let binThisCycle;
 | 
					            const binThisCycle = cycleIndex % 2; // Note: May want to auto-compute the bin size, but this is only used for coda weapons right now.
 | 
				
			||||||
            if (manifest.isOneBinPerCycle) {
 | 
					 | 
				
			||||||
                binThisCycle = cycleIndex % 2; // Note: May want to auto-compute the bin size, but this is only used for coda weapons right now.
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            for (const rawItem of manifest.items) {
 | 
					            for (const rawItem of manifest.items) {
 | 
				
			||||||
                if (!manifest.isOneBinPerCycle || rawItem.bin == binThisCycle) {
 | 
					                if (rawItem.bin == binThisCycle) {
 | 
				
			||||||
                    offersToAdd.push(rawItem);
 | 
					                    offersToAdd.push(rawItem);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					 | 
				
			||||||
            // For most vendors, the offers seem to roughly be in reverse order from the manifest. Coda weapons are an odd exception.
 | 
					 | 
				
			||||||
            if (!manifest.isOneBinPerCycle) {
 | 
					 | 
				
			||||||
                offersToAdd.reverse();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const cycleStart = cycleOffset + cycleIndex * cycleDuration;
 | 
					        const cycleStart = cycleOffset + cycleIndex * cycleDuration;
 | 
				
			||||||
        for (const rawItem of offersToAdd) {
 | 
					        for (const rawItem of offersToAdd) {
 | 
				
			||||||
@ -311,7 +332,7 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
 | 
				
			|||||||
                StoreItem: rawItem.storeItem,
 | 
					                StoreItem: rawItem.storeItem,
 | 
				
			||||||
                ItemPrices: rawItem.itemPrices?.map(itemPrice => ({ ...itemPrice, ProductCategory: "MiscItems" })),
 | 
					                ItemPrices: rawItem.itemPrices?.map(itemPrice => ({ ...itemPrice, ProductCategory: "MiscItems" })),
 | 
				
			||||||
                Bin: "BIN_" + rawItem.bin,
 | 
					                Bin: "BIN_" + rawItem.bin,
 | 
				
			||||||
                QuantityMultiplier: 1,
 | 
					                QuantityMultiplier: rawItem.quantity,
 | 
				
			||||||
                Expiry: { $date: { $numberLong: expiry.toString() } },
 | 
					                Expiry: { $date: { $numberLong: expiry.toString() } },
 | 
				
			||||||
                AllowMultipurchase: false,
 | 
					                AllowMultipurchase: false,
 | 
				
			||||||
                Id: {
 | 
					                Id: {
 | 
				
			||||||
@ -371,6 +392,8 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        info.Expiry.$date.$numberLong = soonestOfferExpiry.toString();
 | 
					        info.Expiry.$date.$numberLong = soonestOfferExpiry.toString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        now += unixTimesInMs.hour;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return cacheEntry;
 | 
					    return cacheEntry;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -388,4 +411,17 @@ if (isDev) {
 | 
				
			|||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest`);
 | 
					        logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const pall = getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest")!
 | 
				
			||||||
 | 
					        .VendorInfo.ItemManifest;
 | 
				
			||||||
 | 
					    if (
 | 
				
			||||||
 | 
					        pall.length != 5 ||
 | 
				
			||||||
 | 
					        pall[0].StoreItem != "/Lotus/StoreItems/Types/Items/ShipDecos/HarrowQuestKeyOrnament" ||
 | 
				
			||||||
 | 
					        pall[1].StoreItem != "/Lotus/StoreItems/Types/BoosterPacks/RivenModPack" ||
 | 
				
			||||||
 | 
					        pall[2].StoreItem != "/Lotus/StoreItems/Types/StoreItems/CreditBundles/150000Credits" ||
 | 
				
			||||||
 | 
					        pall[3].StoreItem != "/Lotus/StoreItems/Types/Items/MiscItems/Kuva" ||
 | 
				
			||||||
 | 
					        pall[4].StoreItem != "/Lotus/StoreItems/Types/BoosterPacks/RivenModPack"
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,61 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "VendorInfo": {
 | 
					 | 
				
			||||||
    "_id": {
 | 
					 | 
				
			||||||
      "$oid": "5f456e00c96976e97d6b7fd7"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "TypeName": "/Lotus/Types/Game/VendorManifests/Deimos/ProspectorVendorManifest",
 | 
					 | 
				
			||||||
    "ItemManifest": [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Gems/Deimos/DeimosUncommonGemACutItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [13, 13],
 | 
					 | 
				
			||||||
        "Bin": "BIN_1",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 10,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e93a8"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Gems/Deimos/DeimosCommonGemBCutItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [7, 7],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e93a9"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Gems/Deimos/DeimosCommonGemACutItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [7, 7],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e93aa"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    "PropertyTextHash": "2BBC116116C757F6AF4FBC3B9BF754C8",
 | 
					 | 
				
			||||||
    "Expiry": {
 | 
					 | 
				
			||||||
      "$date": {
 | 
					 | 
				
			||||||
        "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,125 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "VendorInfo": {
 | 
					 | 
				
			||||||
    "_id": {
 | 
					 | 
				
			||||||
      "$oid": "5dbb4c41e966f7886c3ce939"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "TypeName": "/Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest",
 | 
					 | 
				
			||||||
    "ItemManifest": [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/HarrowQuestKeyOrnament",
 | 
					 | 
				
			||||||
        "ItemPrices": [
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            "ItemCount": 25,
 | 
					 | 
				
			||||||
            "ItemType": "/Lotus/Types/Items/MiscItems/PrimeBucks",
 | 
					 | 
				
			||||||
            "ProductCategory": "MiscItems"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "604800000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e945f"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/BoosterPacks/RivenModPack",
 | 
					 | 
				
			||||||
        "ItemPrices": [
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            "ItemCount": 10,
 | 
					 | 
				
			||||||
            "ItemType": "/Lotus/Types/Items/MiscItems/RivenFragment",
 | 
					 | 
				
			||||||
            "ProductCategory": "MiscItems"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "604800000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e9468"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/StoreItems/CreditBundles/150000Credits",
 | 
					 | 
				
			||||||
        "ItemPrices": [
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            "ItemCount": 5,
 | 
					 | 
				
			||||||
            "ItemType": "/Lotus/Types/Items/MiscItems/RivenFragment",
 | 
					 | 
				
			||||||
            "ProductCategory": "MiscItems"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "604800000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e9469"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/MiscItems/Kuva",
 | 
					 | 
				
			||||||
        "ItemPrices": [
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            "ItemCount": 10,
 | 
					 | 
				
			||||||
            "ItemType": "/Lotus/Types/Items/MiscItems/RivenFragment",
 | 
					 | 
				
			||||||
            "ProductCategory": "MiscItems"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 35000,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "604800000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e946a"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/BoosterPacks/RivenModPack",
 | 
					 | 
				
			||||||
        "ItemPrices": [
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            "ItemCount": 10,
 | 
					 | 
				
			||||||
            "ItemType": "/Lotus/Types/Items/MiscItems/RivenFragment",
 | 
					 | 
				
			||||||
            "ProductCategory": "MiscItems"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "604800000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e946b"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    "PropertyTextHash": "62B64A8065B7C0FA345895D4BC234621",
 | 
					 | 
				
			||||||
    "Expiry": {
 | 
					 | 
				
			||||||
      "$date": {
 | 
					 | 
				
			||||||
        "$numberLong": "604800000"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,62 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "VendorInfo": {
 | 
					 | 
				
			||||||
    "_id": {
 | 
					 | 
				
			||||||
      "$oid": "59dfe591314805ffe1d47c0a"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "TypeName": "/Lotus/Types/Game/VendorManifests/Ostron/ProspectorVendorManifest",
 | 
					 | 
				
			||||||
    "ItemManifest": [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Gems/Eidolon/RareGemACutAItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [19, 19],
 | 
					 | 
				
			||||||
        "Bin": "BIN_1",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 5,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e98f0"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Gems/Eidolon/CommonGemBCutAItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [8, 8],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e98f1"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Gems/Eidolon/CommonGemACutAItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [5, 5],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e98f2"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    "MaxDailyPurchases": 0,
 | 
					 | 
				
			||||||
    "PropertyTextHash": "773C6968D9A65506CD28DF28C768F0DA",
 | 
					 | 
				
			||||||
    "Expiry": {
 | 
					 | 
				
			||||||
      "$date": {
 | 
					 | 
				
			||||||
        "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,61 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "VendorInfo": {
 | 
					 | 
				
			||||||
    "_id": {
 | 
					 | 
				
			||||||
      "$oid": "5be4a159b144f3cdf1c22ebb"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "TypeName": "/Lotus/Types/Game/VendorManifests/Solaris/ProspectorVendorManifest",
 | 
					 | 
				
			||||||
    "ItemManifest": [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Gems/Solaris/SolarisRareGemACutItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [20, 20],
 | 
					 | 
				
			||||||
        "Bin": "BIN_1",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 5,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e9777"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Gems/Solaris/SolarisCommonGemBCutItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [10, 10],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e9778"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Gems/Solaris/SolarisCommonGemACutItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [8, 8],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e9779"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    "PropertyTextHash": "A5756A21991FF49CFA7D096B4026515B",
 | 
					 | 
				
			||||||
    "Expiry": {
 | 
					 | 
				
			||||||
      "$date": {
 | 
					 | 
				
			||||||
        "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user