forked from OpenWF/SpaceNinjaServer
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			main
			...
			inflich-we
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ab5543abde | |||
| 03c6f92016 | 
@ -1,5 +1,6 @@
 | 
				
			|||||||
import { version_compare } from "@/src/helpers/inventoryHelpers";
 | 
					import { version_compare } from "@/src/helpers/inventoryHelpers";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
 | 
					    antivirusMods,
 | 
				
			||||||
    consumeModCharge,
 | 
					    consumeModCharge,
 | 
				
			||||||
    decodeNemesisGuess,
 | 
					    decodeNemesisGuess,
 | 
				
			||||||
    encodeNemesisGuess,
 | 
					    encodeNemesisGuess,
 | 
				
			||||||
@ -134,34 +135,37 @@ export const nemesisController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
                for (const upgrade of body.knife!.AttachedUpgrades) {
 | 
					                for (const upgrade of body.knife!.AttachedUpgrades) {
 | 
				
			||||||
                    switch (upgrade.ItemType) {
 | 
					                    switch (upgrade.ItemType) {
 | 
				
			||||||
                        case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusAndSpeedOnUseMod":
 | 
					                        case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusAndSpeedOnUseMod":
 | 
				
			||||||
                            antivirusGain += 10;
 | 
					 | 
				
			||||||
                            consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
 | 
					 | 
				
			||||||
                            break;
 | 
					 | 
				
			||||||
                        case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusAndWeaponDamageOnUseMod":
 | 
					                        case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusAndWeaponDamageOnUseMod":
 | 
				
			||||||
 | 
					                        case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusSmallOnSingleUseMod":
 | 
				
			||||||
                            antivirusGain += 10;
 | 
					                            antivirusGain += 10;
 | 
				
			||||||
                            consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
 | 
					                            consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
                        case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusLargeOnSingleUseMod": // Instant Secure
 | 
					                        case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusLargeOnSingleUseMod": // Instant Secure
 | 
				
			||||||
                            antivirusGain += 15;
 | 
					 | 
				
			||||||
                            consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
 | 
					 | 
				
			||||||
                            break;
 | 
					 | 
				
			||||||
                        case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusOnUseMod": // Immuno Shield
 | 
					                        case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusOnUseMod": // Immuno Shield
 | 
				
			||||||
                            antivirusGain += 15;
 | 
					                            antivirusGain += 15;
 | 
				
			||||||
                            consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
 | 
					                            consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
                        case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusSmallOnSingleUseMod":
 | 
					 | 
				
			||||||
                            antivirusGain += 10;
 | 
					 | 
				
			||||||
                            consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
 | 
					 | 
				
			||||||
                            break;
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                inventory.Nemesis!.HenchmenKilled += antivirusGain;
 | 
					                inventory.Nemesis!.HenchmenKilled += antivirusGain;
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (inventory.Nemesis!.HenchmenKilled >= 100) {
 | 
					                if (inventory.Nemesis!.HenchmenKilled >= 100) {
 | 
				
			||||||
                    inventory.Nemesis!.HenchmenKilled = 100;
 | 
					                    inventory.Nemesis!.HenchmenKilled = 100;
 | 
				
			||||||
 | 
					                    // Client doesn't seem to request mode=w for infested liches, so weakening it here.
 | 
				
			||||||
 | 
					                    inventory.Nemesis!.InfNodes = [
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            Node: getNemesisManifest(inventory.Nemesis!.manifest).showdownNode,
 | 
				
			||||||
 | 
					                            Influence: 1
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					                    ];
 | 
				
			||||||
 | 
					                    inventory.Nemesis!.Weakened = true;
 | 
				
			||||||
 | 
					                    const upgrade = getKnifeUpgrade(inventory, dataknifeUpgrades, antivirusMods[passcode]);
 | 
				
			||||||
 | 
					                    consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (inventory.Nemesis!.HenchmenKilled < 100) {
 | 
				
			||||||
                inventory.Nemesis!.InfNodes = getInfNodes(getNemesisManifest(inventory.Nemesis!.manifest), 0);
 | 
					                inventory.Nemesis!.InfNodes = getInfNodes(getNemesisManifest(inventory.Nemesis!.manifest), 0);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await inventory.save();
 | 
					            await inventory.save();
 | 
				
			||||||
            res.json(response);
 | 
					            res.json(response);
 | 
				
			||||||
@ -283,6 +287,10 @@ export const nemesisController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
        //const body = getJSONfromString<INemesisWeakenRequest>(String(req.body));
 | 
					        //const body = getJSONfromString<INemesisWeakenRequest>(String(req.body));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (inventory.Nemesis!.Weakened) {
 | 
				
			||||||
 | 
					            logger.warn(`client is weakening an already-weakened nemesis?!`);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inventory.Nemesis!.InfNodes = [
 | 
					        inventory.Nemesis!.InfNodes = [
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Node: getNemesisManifest(inventory.Nemesis!.manifest).showdownNode,
 | 
					                Node: getNemesisManifest(inventory.Nemesis!.manifest).showdownNode,
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,6 @@ export const popArchonCrystalUpgradeController: RequestHandler = async (req, res
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
        await inventory.save();
 | 
					        await inventory.save();
 | 
				
			||||||
        res.end();
 | 
					        res.end();
 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    res.status(400).end();
 | 
					    res.status(400).end();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,6 @@ export const pushArchonCrystalUpgradeController: RequestHandler = async (req, re
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            await inventory.save();
 | 
					            await inventory.save();
 | 
				
			||||||
            res.end();
 | 
					            res.end();
 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    res.status(400).end();
 | 
					    res.status(400).end();
 | 
				
			||||||
 | 
				
			|||||||
@ -248,7 +248,7 @@ const requiemMods: readonly string[] = [
 | 
				
			|||||||
    "/Lotus/Upgrades/Mods/Immortal/ImmortalEightMod"
 | 
					    "/Lotus/Upgrades/Mods/Immortal/ImmortalEightMod"
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const antivirusMods: readonly string[] = [
 | 
					export const antivirusMods: readonly string[] = [
 | 
				
			||||||
    "/Lotus/Upgrades/Mods/Immortal/AntivirusOneMod",
 | 
					    "/Lotus/Upgrades/Mods/Immortal/AntivirusOneMod",
 | 
				
			||||||
    "/Lotus/Upgrades/Mods/Immortal/AntivirusTwoMod",
 | 
					    "/Lotus/Upgrades/Mods/Immortal/AntivirusTwoMod",
 | 
				
			||||||
    "/Lotus/Upgrades/Mods/Immortal/AntivirusThreeMod",
 | 
					    "/Lotus/Upgrades/Mods/Immortal/AntivirusThreeMod",
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,7 @@ import DeimosPetVendorManifest from "@/static/fixed_responses/getVendorInfo/Deim
 | 
				
			|||||||
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 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";
 | 
				
			||||||
@ -41,6 +42,7 @@ const rawVendorManifests: IVendorManifest[] = [
 | 
				
			|||||||
    DuviriAcrithisVendorManifest,
 | 
					    DuviriAcrithisVendorManifest,
 | 
				
			||||||
    EntratiLabsEntratiLabsCommisionsManifest,
 | 
					    EntratiLabsEntratiLabsCommisionsManifest,
 | 
				
			||||||
    EntratiLabsEntratiLabVendorManifest,
 | 
					    EntratiLabsEntratiLabVendorManifest,
 | 
				
			||||||
 | 
					    HubsRailjackCrewMemberVendorManifest,
 | 
				
			||||||
    MaskSalesmanManifest,
 | 
					    MaskSalesmanManifest,
 | 
				
			||||||
    Nova1999ConquestShopManifest,
 | 
					    Nova1999ConquestShopManifest,
 | 
				
			||||||
    OstronPetVendorManifest,
 | 
					    OstronPetVendorManifest,
 | 
				
			||||||
@ -271,39 +273,20 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
 | 
				
			|||||||
        const offersToAdd: IVendorOffer[] = [];
 | 
					        const offersToAdd: IVendorOffer[] = [];
 | 
				
			||||||
        if (!manifest.isOneBinPerCycle) {
 | 
					        if (!manifest.isOneBinPerCycle) {
 | 
				
			||||||
            const remainingItemCapacity: Record<string, number> = {};
 | 
					            const remainingItemCapacity: Record<string, number> = {};
 | 
				
			||||||
            const missingItemsPerBin: Record<number, number> = {};
 | 
					 | 
				
			||||||
            let numOffersThatNeedToMatchABin = 0;
 | 
					 | 
				
			||||||
            if (manifest.numItemsPerBin) {
 | 
					 | 
				
			||||||
                for (let bin = 0; bin != manifest.numItemsPerBin.length; ++bin) {
 | 
					 | 
				
			||||||
                    missingItemsPerBin[bin] = manifest.numItemsPerBin[bin];
 | 
					 | 
				
			||||||
                    numOffersThatNeedToMatchABin += manifest.numItemsPerBin[bin];
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            for (const item of manifest.items) {
 | 
					            for (const item of manifest.items) {
 | 
				
			||||||
                remainingItemCapacity[item.storeItem] = 1 + item.duplicates;
 | 
					                remainingItemCapacity[item.storeItem] = 1 + item.duplicates;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            for (const offer of info.ItemManifest) {
 | 
					            for (const offer of info.ItemManifest) {
 | 
				
			||||||
                remainingItemCapacity[offer.StoreItem] -= 1;
 | 
					                remainingItemCapacity[offer.StoreItem] -= 1;
 | 
				
			||||||
                const bin = parseInt(offer.Bin.substring(4));
 | 
					 | 
				
			||||||
                if (missingItemsPerBin[bin]) {
 | 
					 | 
				
			||||||
                    missingItemsPerBin[bin] -= 1;
 | 
					 | 
				
			||||||
                    numOffersThatNeedToMatchABin -= 1;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (manifest.numItems && manifest.items.length != manifest.numItems.minValue) {
 | 
					            if (manifest.numItems && manifest.items.length != manifest.numItems.minValue) {
 | 
				
			||||||
                const numItemsTarget = rng.randomInt(manifest.numItems.minValue, manifest.numItems.maxValue);
 | 
					                const numItemsTarget = rng.randomInt(manifest.numItems.minValue, manifest.numItems.maxValue);
 | 
				
			||||||
                while (info.ItemManifest.length + offersToAdd.length < numItemsTarget) {
 | 
					                while (info.ItemManifest.length + offersToAdd.length < numItemsTarget) {
 | 
				
			||||||
 | 
					                    // TODO: Consider per-bin item limits
 | 
				
			||||||
                    // TODO: Consider item probability weightings
 | 
					                    // TODO: Consider item probability weightings
 | 
				
			||||||
                    const item = rng.randomElement(manifest.items)!;
 | 
					                    const item = rng.randomElement(manifest.items)!;
 | 
				
			||||||
                    if (
 | 
					                    if (remainingItemCapacity[item.storeItem] != 0) {
 | 
				
			||||||
                        remainingItemCapacity[item.storeItem] != 0 &&
 | 
					 | 
				
			||||||
                        (numOffersThatNeedToMatchABin == 0 || missingItemsPerBin[item.bin])
 | 
					 | 
				
			||||||
                    ) {
 | 
					 | 
				
			||||||
                        remainingItemCapacity[item.storeItem] -= 1;
 | 
					                        remainingItemCapacity[item.storeItem] -= 1;
 | 
				
			||||||
                        if (missingItemsPerBin[item.bin]) {
 | 
					 | 
				
			||||||
                            missingItemsPerBin[item.bin] -= 1;
 | 
					 | 
				
			||||||
                            numOffersThatNeedToMatchABin -= 1;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        offersToAdd.push(item);
 | 
					                        offersToAdd.push(item);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -400,12 +383,6 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
 | 
				
			|||||||
            info.ItemManifest.push(item);
 | 
					            info.ItemManifest.push(item);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        info.ItemManifest.sort((a, b) => {
 | 
					 | 
				
			||||||
            const aBin = parseInt(a.Bin.substring(4));
 | 
					 | 
				
			||||||
            const bBin = parseInt(b.Bin.substring(4));
 | 
					 | 
				
			||||||
            return aBin == bBin ? 0 : aBin < bBin ? +1 : -1;
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Update vendor expiry
 | 
					        // Update vendor expiry
 | 
				
			||||||
        let soonestOfferExpiry: number = Number.MAX_SAFE_INTEGER;
 | 
					        let soonestOfferExpiry: number = Number.MAX_SAFE_INTEGER;
 | 
				
			||||||
        for (const offer of info.ItemManifest) {
 | 
					        for (const offer of info.ItemManifest) {
 | 
				
			||||||
@ -447,17 +424,4 @@ if (isDev) {
 | 
				
			|||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest`);
 | 
					        logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    const cms = getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/Hubs/RailjackCrewMemberVendorManifest")!
 | 
					 | 
				
			||||||
        .VendorInfo.ItemManifest;
 | 
					 | 
				
			||||||
    if (
 | 
					 | 
				
			||||||
        cms.length != 9 ||
 | 
					 | 
				
			||||||
        cms[0].Bin != "BIN_2" ||
 | 
					 | 
				
			||||||
        cms[8].Bin != "BIN_0" ||
 | 
					 | 
				
			||||||
        cms.reduce((a, x) => a + (x.Bin == "BIN_2" ? 1 : 0), 0) < 2 ||
 | 
					 | 
				
			||||||
        cms.reduce((a, x) => a + (x.Bin == "BIN_1" ? 1 : 0), 0) < 2 ||
 | 
					 | 
				
			||||||
        cms.reduce((a, x) => a + (x.Bin == "BIN_0" ? 1 : 0), 0) < 4
 | 
					 | 
				
			||||||
    ) {
 | 
					 | 
				
			||||||
        logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/RailjackCrewMemberVendorManifest`);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@ import {
 | 
				
			|||||||
    ISortie,
 | 
					    ISortie,
 | 
				
			||||||
    ISortieMission,
 | 
					    ISortieMission,
 | 
				
			||||||
    ISyndicateMissionInfo,
 | 
					    ISyndicateMissionInfo,
 | 
				
			||||||
    IVoidStorm,
 | 
					 | 
				
			||||||
    IWorldState
 | 
					    IWorldState
 | 
				
			||||||
} from "../types/worldStateTypes";
 | 
					} from "../types/worldStateTypes";
 | 
				
			||||||
import { version_compare } from "../helpers/inventoryHelpers";
 | 
					import { version_compare } from "../helpers/inventoryHelpers";
 | 
				
			||||||
@ -964,61 +963,6 @@ const getCalendarSeason = (week: number): ICalendarSeason => {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Not very faithful, but to avoid the same node coming up back-to-back (which is not valid), I've split these into 2 arrays which we're alternating between.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const voidStormMissionsA = {
 | 
					 | 
				
			||||||
    VoidT1: ["CrewBattleNode519", "CrewBattleNode518", "CrewBattleNode515", "CrewBattleNode503"],
 | 
					 | 
				
			||||||
    VoidT2: ["CrewBattleNode501", "CrewBattleNode534", "CrewBattleNode530"],
 | 
					 | 
				
			||||||
    VoidT3: ["CrewBattleNode521", "CrewBattleNode516"],
 | 
					 | 
				
			||||||
    VoidT4: [
 | 
					 | 
				
			||||||
        "CrewBattleNode555",
 | 
					 | 
				
			||||||
        "CrewBattleNode553",
 | 
					 | 
				
			||||||
        "CrewBattleNode554",
 | 
					 | 
				
			||||||
        "CrewBattleNode539",
 | 
					 | 
				
			||||||
        "CrewBattleNode531",
 | 
					 | 
				
			||||||
        "CrewBattleNode527"
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const voidStormMissionsB = {
 | 
					 | 
				
			||||||
    VoidT1: ["CrewBattleNode509", "CrewBattleNode522", "CrewBattleNode511", "CrewBattleNode512"],
 | 
					 | 
				
			||||||
    VoidT2: ["CrewBattleNode535", "CrewBattleNode533"],
 | 
					 | 
				
			||||||
    VoidT3: ["CrewBattleNode524", "CrewBattleNode525"],
 | 
					 | 
				
			||||||
    VoidT4: [
 | 
					 | 
				
			||||||
        "CrewBattleNode542",
 | 
					 | 
				
			||||||
        "CrewBattleNode538",
 | 
					 | 
				
			||||||
        "CrewBattleNode543",
 | 
					 | 
				
			||||||
        "CrewBattleNode536",
 | 
					 | 
				
			||||||
        "CrewBattleNode550",
 | 
					 | 
				
			||||||
        "CrewBattleNode529"
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const pushVoidStorms = (arr: IVoidStorm[], hour: number): void => {
 | 
					 | 
				
			||||||
    const activation = hour * unixTimesInMs.hour + 40 * unixTimesInMs.minute;
 | 
					 | 
				
			||||||
    const expiry = activation + 90 * unixTimesInMs.minute;
 | 
					 | 
				
			||||||
    let accum = 0;
 | 
					 | 
				
			||||||
    const rng = new SRng(new SRng(hour).randomInt(0, 100_000));
 | 
					 | 
				
			||||||
    const voidStormMissions = structuredClone(hour & 1 ? voidStormMissionsA : voidStormMissionsB);
 | 
					 | 
				
			||||||
    for (const tier of ["VoidT1", "VoidT1", "VoidT2", "VoidT3", "VoidT4", "VoidT4"] as const) {
 | 
					 | 
				
			||||||
        const idx = rng.randomInt(0, voidStormMissions[tier].length - 1);
 | 
					 | 
				
			||||||
        const node = voidStormMissions[tier][idx];
 | 
					 | 
				
			||||||
        voidStormMissions[tier].splice(idx, 1);
 | 
					 | 
				
			||||||
        arr.push({
 | 
					 | 
				
			||||||
            _id: {
 | 
					 | 
				
			||||||
                $oid:
 | 
					 | 
				
			||||||
                    ((activation / 1000) & 0xffffffff).toString(16).padStart(8, "0") +
 | 
					 | 
				
			||||||
                    "0321e89b" +
 | 
					 | 
				
			||||||
                    (accum++).toString().padStart(8, "0")
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            Node: node,
 | 
					 | 
				
			||||||
            Activation: { $date: { $numberLong: activation.toString() } },
 | 
					 | 
				
			||||||
            Expiry: { $date: { $numberLong: expiry.toString() } },
 | 
					 | 
				
			||||||
            ActiveMissionTier: tier
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const doesTimeSatsifyConstraints = (timeSecs: number): boolean => {
 | 
					const doesTimeSatsifyConstraints = (timeSecs: number): boolean => {
 | 
				
			||||||
    if (config.worldState?.eidolonOverride) {
 | 
					    if (config.worldState?.eidolonOverride) {
 | 
				
			||||||
        const eidolonEpoch = 1391992660;
 | 
					        const eidolonEpoch = 1391992660;
 | 
				
			||||||
@ -1088,7 +1032,6 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
 | 
				
			|||||||
        Sorties: [],
 | 
					        Sorties: [],
 | 
				
			||||||
        LiteSorties: [],
 | 
					        LiteSorties: [],
 | 
				
			||||||
        GlobalUpgrades: [],
 | 
					        GlobalUpgrades: [],
 | 
				
			||||||
        VoidStorms: [],
 | 
					 | 
				
			||||||
        EndlessXpChoices: [],
 | 
					        EndlessXpChoices: [],
 | 
				
			||||||
        KnownCalendarSeasons: [],
 | 
					        KnownCalendarSeasons: [],
 | 
				
			||||||
        ...staticWorldState,
 | 
					        ...staticWorldState,
 | 
				
			||||||
@ -1285,18 +1228,6 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
 | 
				
			|||||||
        worldState.KnownCalendarSeasons.push(getCalendarSeason(week + 1));
 | 
					        worldState.KnownCalendarSeasons.push(getCalendarSeason(week + 1));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Void Storms
 | 
					 | 
				
			||||||
    const hour = Math.trunc(timeMs / unixTimesInMs.hour);
 | 
					 | 
				
			||||||
    const overLastHourStormExpiry = hour * unixTimesInMs.hour + 10 * unixTimesInMs.minute;
 | 
					 | 
				
			||||||
    const thisHourStormActivation = hour * unixTimesInMs.hour + 40 * unixTimesInMs.minute;
 | 
					 | 
				
			||||||
    if (overLastHourStormExpiry > timeMs) {
 | 
					 | 
				
			||||||
        pushVoidStorms(worldState.VoidStorms, hour - 2);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    pushVoidStorms(worldState.VoidStorms, hour - 1);
 | 
					 | 
				
			||||||
    if (isBeforeNextExpectedWorldStateRefresh(timeMs, thisHourStormActivation)) {
 | 
					 | 
				
			||||||
        pushVoidStorms(worldState.VoidStorms, hour);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Sentient Anomaly cycling every 30 minutes
 | 
					    // Sentient Anomaly cycling every 30 minutes
 | 
				
			||||||
    const halfHour = Math.trunc(timeMs / (unixTimesInMs.hour / 2));
 | 
					    const halfHour = Math.trunc(timeMs / (unixTimesInMs.hour / 2));
 | 
				
			||||||
    const tmp = {
 | 
					    const tmp = {
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,6 @@ export interface IWorldState {
 | 
				
			|||||||
    GlobalUpgrades: IGlobalUpgrade[];
 | 
					    GlobalUpgrades: IGlobalUpgrade[];
 | 
				
			||||||
    ActiveMissions: IFissure[];
 | 
					    ActiveMissions: IFissure[];
 | 
				
			||||||
    NodeOverrides: INodeOverride[];
 | 
					    NodeOverrides: INodeOverride[];
 | 
				
			||||||
    VoidStorms: IVoidStorm[];
 | 
					 | 
				
			||||||
    PVPChallengeInstances: IPVPChallengeInstance[];
 | 
					    PVPChallengeInstances: IPVPChallengeInstance[];
 | 
				
			||||||
    EndlessXpChoices: IEndlessXpChoice[];
 | 
					    EndlessXpChoices: IEndlessXpChoice[];
 | 
				
			||||||
    SeasonInfo?: {
 | 
					    SeasonInfo?: {
 | 
				
			||||||
@ -132,14 +131,6 @@ export interface ILiteSortie {
 | 
				
			|||||||
    }[];
 | 
					    }[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IVoidStorm {
 | 
					 | 
				
			||||||
    _id: IOid;
 | 
					 | 
				
			||||||
    Node: string;
 | 
					 | 
				
			||||||
    Activation: IMongoDate;
 | 
					 | 
				
			||||||
    Expiry: IMongoDate;
 | 
					 | 
				
			||||||
    ActiveMissionTier: string;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface IPVPChallengeInstance {
 | 
					export interface IPVPChallengeInstance {
 | 
				
			||||||
    _id: IOid;
 | 
					    _id: IOid;
 | 
				
			||||||
    challengeTypeRefID: string;
 | 
					    challengeTypeRefID: string;
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,244 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "VendorInfo": {
 | 
				
			||||||
 | 
					    "_id": {
 | 
				
			||||||
 | 
					      "$oid": "5fb70313c96976e97d6be787"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "TypeName": "/Lotus/Types/Game/VendorManifests/Hubs/RailjackCrewMemberVendorManifest",
 | 
				
			||||||
 | 
					    "ItemManifest": [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Game/CrewShip/CrewMember/SteelMeridianCrewMemberGeneratorStrong",
 | 
				
			||||||
 | 
					        "ItemPrices": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "ItemType": "/Lotus/Types/Items/RailjackMiscItems/IsosRailjackItem",
 | 
				
			||||||
 | 
					            "ItemCount": 2220,
 | 
				
			||||||
 | 
					            "ProductCategory": "MiscItems"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "RegularPrice": [2180000, 2180000],
 | 
				
			||||||
 | 
					        "Bin": "BIN_2",
 | 
				
			||||||
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
 | 
					        "Expiry": {
 | 
				
			||||||
 | 
					          "$date": {
 | 
				
			||||||
 | 
					            "$numberLong": "9999999000000"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
 | 
					        "Affiliation": "SteelMeridianSyndicate",
 | 
				
			||||||
 | 
					        "MinAffiliationRank": 0,
 | 
				
			||||||
 | 
					        "ReductionPerPositiveRank": 0.1,
 | 
				
			||||||
 | 
					        "IncreasePerNegativeRank": 0.5,
 | 
				
			||||||
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
 | 
					        "LocTagRandSeed": 4185144421,
 | 
				
			||||||
 | 
					        "Id": {
 | 
				
			||||||
 | 
					          "$oid": "670daf92d21f34757a5e73da"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Game/CrewShip/CrewMember/NewLokaCrewMemberGeneratorStrong",
 | 
				
			||||||
 | 
					        "ItemPrices": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "ItemType": "/Lotus/Types/Items/RailjackMiscItems/IsosRailjackItem",
 | 
				
			||||||
 | 
					            "ItemCount": 2130,
 | 
				
			||||||
 | 
					            "ProductCategory": "MiscItems"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "RegularPrice": [1890000, 1890000],
 | 
				
			||||||
 | 
					        "Bin": "BIN_2",
 | 
				
			||||||
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
 | 
					        "Expiry": {
 | 
				
			||||||
 | 
					          "$date": {
 | 
				
			||||||
 | 
					            "$numberLong": "9999999000000"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
 | 
					        "Affiliation": "NewLokaSyndicate",
 | 
				
			||||||
 | 
					        "MinAffiliationRank": 0,
 | 
				
			||||||
 | 
					        "ReductionPerPositiveRank": 0.1,
 | 
				
			||||||
 | 
					        "IncreasePerNegativeRank": 0.5,
 | 
				
			||||||
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
 | 
					        "LocTagRandSeed": 496053258,
 | 
				
			||||||
 | 
					        "Id": {
 | 
				
			||||||
 | 
					          "$oid": "670daf92d21f34757a5e73db"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Game/CrewShip/CrewMember/SteelMeridianCrewMemberGeneratorMediumVersionTwo",
 | 
				
			||||||
 | 
					        "ItemPrices": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "ItemType": "/Lotus/Types/Items/RailjackMiscItems/IsosRailjackItem",
 | 
				
			||||||
 | 
					            "ItemCount": 440,
 | 
				
			||||||
 | 
					            "ProductCategory": "MiscItems"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "Bin": "BIN_1",
 | 
				
			||||||
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
 | 
					        "Expiry": {
 | 
				
			||||||
 | 
					          "$date": {
 | 
				
			||||||
 | 
					            "$numberLong": "9999999000000"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
 | 
					        "Affiliation": "SteelMeridianSyndicate",
 | 
				
			||||||
 | 
					        "MinAffiliationRank": 0,
 | 
				
			||||||
 | 
					        "ReductionPerPositiveRank": 0.1,
 | 
				
			||||||
 | 
					        "IncreasePerNegativeRank": 0.5,
 | 
				
			||||||
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
 | 
					        "LocTagRandSeed": 2078883475,
 | 
				
			||||||
 | 
					        "Id": {
 | 
				
			||||||
 | 
					          "$oid": "670daf92d21f34757a5e73dc"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Game/CrewShip/CrewMember/NewLokaCrewMemberGeneratorMediumVersionTwo",
 | 
				
			||||||
 | 
					        "ItemPrices": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "ItemType": "/Lotus/Types/Items/RailjackMiscItems/AsteriteRailjackItem",
 | 
				
			||||||
 | 
					            "ItemCount": 730,
 | 
				
			||||||
 | 
					            "ProductCategory": "MiscItems"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "Bin": "BIN_1",
 | 
				
			||||||
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
 | 
					        "Expiry": {
 | 
				
			||||||
 | 
					          "$date": {
 | 
				
			||||||
 | 
					            "$numberLong": "9999999000000"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
 | 
					        "Affiliation": "NewLokaSyndicate",
 | 
				
			||||||
 | 
					        "MinAffiliationRank": 0,
 | 
				
			||||||
 | 
					        "ReductionPerPositiveRank": 0.1,
 | 
				
			||||||
 | 
					        "IncreasePerNegativeRank": 0.5,
 | 
				
			||||||
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
 | 
					        "LocTagRandSeed": 3890380934,
 | 
				
			||||||
 | 
					        "Id": {
 | 
				
			||||||
 | 
					          "$oid": "670daf92d21f34757a5e73dd"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Game/CrewShip/CrewMember/CephalonSudaCrewMemberGeneratorMediumVersionTwo",
 | 
				
			||||||
 | 
					        "ItemPrices": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "ItemType": "/Lotus/Types/Items/RailjackMiscItems/AsteriteRailjackItem",
 | 
				
			||||||
 | 
					            "ItemCount": 720,
 | 
				
			||||||
 | 
					            "ProductCategory": "MiscItems"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "Bin": "BIN_1",
 | 
				
			||||||
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
 | 
					        "Expiry": {
 | 
				
			||||||
 | 
					          "$date": {
 | 
				
			||||||
 | 
					            "$numberLong": "9999999000000"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
 | 
					        "Affiliation": "CephalonSudaSyndicate",
 | 
				
			||||||
 | 
					        "MinAffiliationRank": 0,
 | 
				
			||||||
 | 
					        "ReductionPerPositiveRank": 0.1,
 | 
				
			||||||
 | 
					        "IncreasePerNegativeRank": 0.5,
 | 
				
			||||||
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
 | 
					        "LocTagRandSeed": 3425148044,
 | 
				
			||||||
 | 
					        "Id": {
 | 
				
			||||||
 | 
					          "$oid": "670daf92d21f34757a5e73de"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Game/CrewShip/CrewMember/ArbitersCrewMemberGeneratorMediumVersionTwo",
 | 
				
			||||||
 | 
					        "ItemPrices": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "ItemType": "/Lotus/Types/Items/RailjackMiscItems/CubicsRailjackItem",
 | 
				
			||||||
 | 
					            "ItemCount": 6500,
 | 
				
			||||||
 | 
					            "ProductCategory": "MiscItems"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "Bin": "BIN_1",
 | 
				
			||||||
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
 | 
					        "Expiry": {
 | 
				
			||||||
 | 
					          "$date": {
 | 
				
			||||||
 | 
					            "$numberLong": "9999999000000"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
 | 
					        "Affiliation": "ArbitersSyndicate",
 | 
				
			||||||
 | 
					        "MinAffiliationRank": 0,
 | 
				
			||||||
 | 
					        "ReductionPerPositiveRank": 0.1,
 | 
				
			||||||
 | 
					        "IncreasePerNegativeRank": 0.5,
 | 
				
			||||||
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
 | 
					        "LocTagRandSeed": 2472754512,
 | 
				
			||||||
 | 
					        "Id": {
 | 
				
			||||||
 | 
					          "$oid": "670daf92d21f34757a5e73df"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Game/CrewShip/CrewMember/PerrinCrewMemberGeneratorVersionTwo",
 | 
				
			||||||
 | 
					        "RegularPrice": [105000, 105000],
 | 
				
			||||||
 | 
					        "Bin": "BIN_0",
 | 
				
			||||||
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
 | 
					        "Expiry": {
 | 
				
			||||||
 | 
					          "$date": {
 | 
				
			||||||
 | 
					            "$numberLong": "9999999000000"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
 | 
					        "Affiliation": "PerrinSyndicate",
 | 
				
			||||||
 | 
					        "MinAffiliationRank": 0,
 | 
				
			||||||
 | 
					        "ReductionPerPositiveRank": 0.1,
 | 
				
			||||||
 | 
					        "IncreasePerNegativeRank": 0.5,
 | 
				
			||||||
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
 | 
					        "LocTagRandSeed": 966238763,
 | 
				
			||||||
 | 
					        "Id": {
 | 
				
			||||||
 | 
					          "$oid": "670daf92d21f34757a5e73e0"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Game/CrewShip/CrewMember/NewLokaCrewMemberGeneratorVersionTwo",
 | 
				
			||||||
 | 
					        "RegularPrice": [120000, 120000],
 | 
				
			||||||
 | 
					        "Bin": "BIN_0",
 | 
				
			||||||
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
 | 
					        "Expiry": {
 | 
				
			||||||
 | 
					          "$date": {
 | 
				
			||||||
 | 
					            "$numberLong": "9999999000000"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
 | 
					        "Affiliation": "NewLokaSyndicate",
 | 
				
			||||||
 | 
					        "MinAffiliationRank": 0,
 | 
				
			||||||
 | 
					        "ReductionPerPositiveRank": 0.1,
 | 
				
			||||||
 | 
					        "IncreasePerNegativeRank": 0.5,
 | 
				
			||||||
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
 | 
					        "LocTagRandSeed": 356717213,
 | 
				
			||||||
 | 
					        "Id": {
 | 
				
			||||||
 | 
					          "$oid": "670daf92d21f34757a5e73e1"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Game/CrewShip/CrewMember/ArbitersCrewMemberGeneratorVersionTwo",
 | 
				
			||||||
 | 
					        "RegularPrice": [120000, 120000],
 | 
				
			||||||
 | 
					        "Bin": "BIN_0",
 | 
				
			||||||
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
 | 
					        "Expiry": {
 | 
				
			||||||
 | 
					          "$date": {
 | 
				
			||||||
 | 
					            "$numberLong": "9999999000000"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
 | 
					        "Affiliation": "ArbitersSyndicate",
 | 
				
			||||||
 | 
					        "MinAffiliationRank": 0,
 | 
				
			||||||
 | 
					        "ReductionPerPositiveRank": 0.1,
 | 
				
			||||||
 | 
					        "IncreasePerNegativeRank": 0.5,
 | 
				
			||||||
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
 | 
					        "LocTagRandSeed": 1969797050,
 | 
				
			||||||
 | 
					        "Id": {
 | 
				
			||||||
 | 
					          "$oid": "670daf92d21f34757a5e73e2"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "PropertyTextHash": "BE543CCC0A4F50A1D80CD2B523796EAE",
 | 
				
			||||||
 | 
					    "RandomSeedType": "VRST_FLAVOUR_TEXT",
 | 
				
			||||||
 | 
					    "Expiry": {
 | 
				
			||||||
 | 
					      "$date": {
 | 
				
			||||||
 | 
					        "$numberLong": "9999999000000"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -2562,6 +2562,50 @@
 | 
				
			|||||||
      ]
 | 
					      ]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
 | 
					  "VoidStorms": [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "_id": { "$oid": "663a7581ced28e18f694b550" },
 | 
				
			||||||
 | 
					      "Node": "CrewBattleNode519",
 | 
				
			||||||
 | 
					      "Activation": { "$date": { "$numberLong": "1715109601821" } },
 | 
				
			||||||
 | 
					      "Expiry": { "$date": { "$numberLong": "2000000000000" } },
 | 
				
			||||||
 | 
					      "ActiveMissionTier": "VoidT1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "_id": { "$oid": "663a7581ced28e18f694b551" },
 | 
				
			||||||
 | 
					      "Node": "CrewBattleNode515",
 | 
				
			||||||
 | 
					      "Activation": { "$date": { "$numberLong": "1715109601825" } },
 | 
				
			||||||
 | 
					      "Expiry": { "$date": { "$numberLong": "2000000000000" } },
 | 
				
			||||||
 | 
					      "ActiveMissionTier": "VoidT1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "_id": { "$oid": "663a7581ced28e18f694b554" },
 | 
				
			||||||
 | 
					      "Node": "CrewBattleNode536",
 | 
				
			||||||
 | 
					      "Activation": { "$date": { "$numberLong": "1715109601832" } },
 | 
				
			||||||
 | 
					      "Expiry": { "$date": { "$numberLong": "2000000000000" } },
 | 
				
			||||||
 | 
					      "ActiveMissionTier": "VoidT4"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "_id": { "$oid": "663a7581ced28e18f694b555" },
 | 
				
			||||||
 | 
					      "Node": "CrewBattleNode539",
 | 
				
			||||||
 | 
					      "Activation": { "$date": { "$numberLong": "1715109601834" } },
 | 
				
			||||||
 | 
					      "Expiry": { "$date": { "$numberLong": "2000000000000" } },
 | 
				
			||||||
 | 
					      "ActiveMissionTier": "VoidT4"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "_id": { "$oid": "663a7581ced28e18f694b553" },
 | 
				
			||||||
 | 
					      "Node": "CrewBattleNode521",
 | 
				
			||||||
 | 
					      "Activation": { "$date": { "$numberLong": "1715109601829" } },
 | 
				
			||||||
 | 
					      "Expiry": { "$date": { "$numberLong": "2000000000000" } },
 | 
				
			||||||
 | 
					      "ActiveMissionTier": "VoidT3"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "_id": { "$oid": "663a7581ced28e18f694b552" },
 | 
				
			||||||
 | 
					      "Node": "CrewBattleNode535",
 | 
				
			||||||
 | 
					      "Activation": { "$date": { "$numberLong": "1715109601827" } },
 | 
				
			||||||
 | 
					      "Expiry": { "$date": { "$numberLong": "2000000000000" } },
 | 
				
			||||||
 | 
					      "ActiveMissionTier": "VoidT2"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
  "PrimeAccessAvailability": { "State": "PRIME1" },
 | 
					  "PrimeAccessAvailability": { "State": "PRIME1" },
 | 
				
			||||||
  "PrimeVaultAvailabilities": [false, false, false, false, false],
 | 
					  "PrimeVaultAvailabilities": [false, false, false, false, false],
 | 
				
			||||||
  "PrimeTokenAvailability": true,
 | 
					  "PrimeTokenAvailability": true,
 | 
				
			||||||
 | 
				
			|||||||
@ -29,7 +29,7 @@ function loginFromLocalStorage() {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        () => {
 | 
					        () => {
 | 
				
			||||||
            logout();
 | 
					            logout();
 | 
				
			||||||
            alert(loc(isRegister ? "code_regFail" : "code_loginFail"));
 | 
					            alert(isRegister ? "Registration failed. Account already exists?" : "Login failed");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,8 +3,6 @@ dict = {
 | 
				
			|||||||
    general_inventoryUpdateNote: `Hinweis: Änderungen, die hier vorgenommen werden, werden erst im Spiel angewendet, sobald das Inventar synchronisiert wird. Die Sternenkarte zu besuchen, sollte der einfachste Weg sein, dies auszulösen.`,
 | 
					    general_inventoryUpdateNote: `Hinweis: Änderungen, die hier vorgenommen werden, werden erst im Spiel angewendet, sobald das Inventar synchronisiert wird. Die Sternenkarte zu besuchen, sollte der einfachste Weg sein, dies auszulösen.`,
 | 
				
			||||||
    general_addButton: `Hinzufügen`,
 | 
					    general_addButton: `Hinzufügen`,
 | 
				
			||||||
    general_bulkActions: `Massenaktionen`,
 | 
					    general_bulkActions: `Massenaktionen`,
 | 
				
			||||||
    code_loginFail: `[UNTRANSLATED] Login failed. Double-check the email and password.`,
 | 
					 | 
				
			||||||
    code_regFail: `[UNTRANSLATED] Registration failed. Account already exists?`,
 | 
					 | 
				
			||||||
    code_nonValidAuthz: `Deine Anmeldedaten sind nicht mehr gültig.`,
 | 
					    code_nonValidAuthz: `Deine Anmeldedaten sind nicht mehr gültig.`,
 | 
				
			||||||
    code_changeNameConfirm: `In welchen Namen möchtest du deinen Account umbenennen?`,
 | 
					    code_changeNameConfirm: `In welchen Namen möchtest du deinen Account umbenennen?`,
 | 
				
			||||||
    code_deleteAccountConfirm: `Bist du sicher, dass du deinen Account |DISPLAYNAME| (|EMAIL|) löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.`,
 | 
					    code_deleteAccountConfirm: `Bist du sicher, dass du deinen Account |DISPLAYNAME| (|EMAIL|) löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.`,
 | 
				
			||||||
 | 
				
			|||||||
@ -2,8 +2,6 @@ dict = {
 | 
				
			|||||||
    general_inventoryUpdateNote: `Note: Changes made here will only be applied in-game when the game syncs the inventory. Visiting the navigation should be the easiest way to trigger that.`,
 | 
					    general_inventoryUpdateNote: `Note: Changes made here will only be applied in-game when the game syncs the inventory. Visiting the navigation should be the easiest way to trigger that.`,
 | 
				
			||||||
    general_addButton: `Add`,
 | 
					    general_addButton: `Add`,
 | 
				
			||||||
    general_bulkActions: `Bulk Actions`,
 | 
					    general_bulkActions: `Bulk Actions`,
 | 
				
			||||||
    code_loginFail: `Login failed. Double-check the email and password.`,
 | 
					 | 
				
			||||||
    code_regFail: `Registration failed. Account already exists?`,
 | 
					 | 
				
			||||||
    code_nonValidAuthz: `Your credentials are no longer valid.`,
 | 
					    code_nonValidAuthz: `Your credentials are no longer valid.`,
 | 
				
			||||||
    code_changeNameConfirm: `What would you like to change your account name to?`,
 | 
					    code_changeNameConfirm: `What would you like to change your account name to?`,
 | 
				
			||||||
    code_deleteAccountConfirm: `Are you sure you want to delete your account |DISPLAYNAME| (|EMAIL|)? This action cannot be undone.`,
 | 
					    code_deleteAccountConfirm: `Are you sure you want to delete your account |DISPLAYNAME| (|EMAIL|)? This action cannot be undone.`,
 | 
				
			||||||
 | 
				
			|||||||
@ -3,8 +3,6 @@ dict = {
 | 
				
			|||||||
    general_inventoryUpdateNote: `Nota: Los cambios realizados aquí se reflejarán en el juego cuando este sincronice el inventario. Usar la navegación debería ser la forma más sencilla de activar esto.`,
 | 
					    general_inventoryUpdateNote: `Nota: Los cambios realizados aquí se reflejarán en el juego cuando este sincronice el inventario. Usar la navegación debería ser la forma más sencilla de activar esto.`,
 | 
				
			||||||
    general_addButton: `Agregar`,
 | 
					    general_addButton: `Agregar`,
 | 
				
			||||||
    general_bulkActions: `Acciones masivas`,
 | 
					    general_bulkActions: `Acciones masivas`,
 | 
				
			||||||
    code_loginFail: `[UNTRANSLATED] Login failed. Double-check the email and password.`,
 | 
					 | 
				
			||||||
    code_regFail: `[UNTRANSLATED] Registration failed. Account already exists?`,
 | 
					 | 
				
			||||||
    code_nonValidAuthz: `Tus credenciales no son válidas.`,
 | 
					    code_nonValidAuthz: `Tus credenciales no son válidas.`,
 | 
				
			||||||
    code_changeNameConfirm: `¿Qué nombre te gustaría ponerle a tu cuenta?`,
 | 
					    code_changeNameConfirm: `¿Qué nombre te gustaría ponerle a tu cuenta?`,
 | 
				
			||||||
    code_deleteAccountConfirm: `¿Estás seguro de que deseas eliminar tu cuenta |DISPLAYNAME| (|EMAIL|)? Esta acción es permanente.`,
 | 
					    code_deleteAccountConfirm: `¿Estás seguro de que deseas eliminar tu cuenta |DISPLAYNAME| (|EMAIL|)? Esta acción es permanente.`,
 | 
				
			||||||
 | 
				
			|||||||
@ -3,8 +3,6 @@ dict = {
 | 
				
			|||||||
    general_inventoryUpdateNote: `Note : Les changements effectués ici seront appliqués lors de la syncrhonisation. Visiter la navigation appliquera les changements apportés à l'inventaire.`,
 | 
					    general_inventoryUpdateNote: `Note : Les changements effectués ici seront appliqués lors de la syncrhonisation. Visiter la navigation appliquera les changements apportés à l'inventaire.`,
 | 
				
			||||||
    general_addButton: `Ajouter`,
 | 
					    general_addButton: `Ajouter`,
 | 
				
			||||||
    general_bulkActions: `Action groupée`,
 | 
					    general_bulkActions: `Action groupée`,
 | 
				
			||||||
    code_loginFail: `[UNTRANSLATED] Login failed. Double-check the email and password.`,
 | 
					 | 
				
			||||||
    code_regFail: `[UNTRANSLATED] Registration failed. Account already exists?`,
 | 
					 | 
				
			||||||
    code_nonValidAuthz: `Informations de connexion invalides`,
 | 
					    code_nonValidAuthz: `Informations de connexion invalides`,
 | 
				
			||||||
    code_changeNameConfirm: `Nouveau nom du compte :`,
 | 
					    code_changeNameConfirm: `Nouveau nom du compte :`,
 | 
				
			||||||
    code_deleteAccountConfirm: `Supprimer |DISPLAYNAME| (|EMAIL|) ? Cette action est irreversible.`,
 | 
					    code_deleteAccountConfirm: `Supprimer |DISPLAYNAME| (|EMAIL|) ? Cette action est irreversible.`,
 | 
				
			||||||
 | 
				
			|||||||
@ -3,8 +3,6 @@ dict = {
 | 
				
			|||||||
    general_inventoryUpdateNote: `Примечание: изменения, внесенные здесь, отобразятся в игре только после повторной загрузки вашего инвентаря. Посещение навигации — самый простой способ этого добиться.`,
 | 
					    general_inventoryUpdateNote: `Примечание: изменения, внесенные здесь, отобразятся в игре только после повторной загрузки вашего инвентаря. Посещение навигации — самый простой способ этого добиться.`,
 | 
				
			||||||
    general_addButton: `Добавить`,
 | 
					    general_addButton: `Добавить`,
 | 
				
			||||||
    general_bulkActions: `Массовые действия`,
 | 
					    general_bulkActions: `Массовые действия`,
 | 
				
			||||||
    code_loginFail: `[UNTRANSLATED] Login failed. Double-check the email and password.`,
 | 
					 | 
				
			||||||
    code_regFail: `[UNTRANSLATED] Registration failed. Account already exists?`,
 | 
					 | 
				
			||||||
    code_nonValidAuthz: `Ваши данные больше не действительны.`,
 | 
					    code_nonValidAuthz: `Ваши данные больше не действительны.`,
 | 
				
			||||||
    code_changeNameConfirm: `Какое имя вы хотите установить для своей учетной записи?`,
 | 
					    code_changeNameConfirm: `Какое имя вы хотите установить для своей учетной записи?`,
 | 
				
			||||||
    code_deleteAccountConfirm: `Вы уверены, что хотите удалить аккаунт |DISPLAYNAME| (|EMAIL|)? Это действие нельзя отменить.`,
 | 
					    code_deleteAccountConfirm: `Вы уверены, что хотите удалить аккаунт |DISPLAYNAME| (|EMAIL|)? Это действие нельзя отменить.`,
 | 
				
			||||||
 | 
				
			|||||||
@ -3,8 +3,6 @@ dict = {
 | 
				
			|||||||
    general_inventoryUpdateNote: `注意:此处所做的更改只有在游戏同步仓库后才会生效。您可以通过访问星图来触发仓库更新。`,
 | 
					    general_inventoryUpdateNote: `注意:此处所做的更改只有在游戏同步仓库后才会生效。您可以通过访问星图来触发仓库更新。`,
 | 
				
			||||||
    general_addButton: `添加`,
 | 
					    general_addButton: `添加`,
 | 
				
			||||||
    general_bulkActions: `批量操作`,
 | 
					    general_bulkActions: `批量操作`,
 | 
				
			||||||
    code_loginFail: `[UNTRANSLATED] Login failed. Double-check the email and password.`,
 | 
					 | 
				
			||||||
    code_regFail: `[UNTRANSLATED] Registration failed. Account already exists?`,
 | 
					 | 
				
			||||||
    code_nonValidAuthz: `您的登录凭证已失效。`,
 | 
					    code_nonValidAuthz: `您的登录凭证已失效。`,
 | 
				
			||||||
    code_changeNameConfirm: `您想将账户名称更改为什么?`,
 | 
					    code_changeNameConfirm: `您想将账户名称更改为什么?`,
 | 
				
			||||||
    code_deleteAccountConfirm: `确定要删除账户 |DISPLAYNAME| (|EMAIL|) 吗?此操作不可撤销。`,
 | 
					    code_deleteAccountConfirm: `确定要删除账户 |DISPLAYNAME| (|EMAIL|) 吗?此操作不可撤销。`,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user