chore: update docker stuff #1961
							
								
								
									
										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.58",
 | 
					        "warframe-public-export-plus": "^0.5.59",
 | 
				
			||||||
        "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"
 | 
				
			||||||
@ -3789,9 +3789,9 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/warframe-public-export-plus": {
 | 
					    "node_modules/warframe-public-export-plus": {
 | 
				
			||||||
      "version": "0.5.58",
 | 
					      "version": "0.5.59",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.58.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.59.tgz",
 | 
				
			||||||
      "integrity": "sha512-2G3tKcoblUl7S3Rkk5k/qH+VGZBUmU2QjtIrEO/Bt6UlgO83s648elkNdDKOLBKXnxIsa194nVwz+ci1K86sXg=="
 | 
					      "integrity": "sha512-/SUCVjngVDBz6gahz7CdVLywtHLODL6O5nmNtQcxFDUwrUGnF1lETcG8/UO+WLeGxBVAy4BDPbq+9ZWlYZM4uQ=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "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.58",
 | 
					    "warframe-public-export-plus": "^0.5.59",
 | 
				
			||||||
    "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"
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,7 @@ import { addItems, combineInventoryChanges, getInventory } from "@/src/services/
 | 
				
			|||||||
import { logger } from "@/src/utils/logger";
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
import { ExportFlavour, ExportGear } from "warframe-public-export-plus";
 | 
					import { ExportFlavour, ExportGear } from "warframe-public-export-plus";
 | 
				
			||||||
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
 | 
					import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
 | 
				
			||||||
 | 
					import { fromStoreItem, isStoreItem } from "@/src/services/itemDataService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const inboxController: RequestHandler = async (req, res) => {
 | 
					export const inboxController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const { deleteId, lastMessage: latestClientMessageId, messageId } = req.query;
 | 
					    const { deleteId, lastMessage: latestClientMessageId, messageId } = req.query;
 | 
				
			||||||
@ -48,7 +49,7 @@ export const inboxController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
            await addItems(
 | 
					            await addItems(
 | 
				
			||||||
                inventory,
 | 
					                inventory,
 | 
				
			||||||
                attachmentItems.map(attItem => ({
 | 
					                attachmentItems.map(attItem => ({
 | 
				
			||||||
                    ItemType: attItem,
 | 
					                    ItemType: isStoreItem(attItem) ? fromStoreItem(attItem) : attItem,
 | 
				
			||||||
                    ItemCount: attItem in ExportGear ? (ExportGear[attItem].purchaseQuantity ?? 1) : 1
 | 
					                    ItemCount: attItem in ExportGear ? (ExportGear[attItem].purchaseQuantity ?? 1) : 1
 | 
				
			||||||
                })),
 | 
					                })),
 | 
				
			||||||
                inventoryChanges
 | 
					                inventoryChanges
 | 
				
			||||||
 | 
				
			|||||||
@ -18,10 +18,12 @@ import {
 | 
				
			|||||||
    addMiscItems,
 | 
					    addMiscItems,
 | 
				
			||||||
    allDailyAffiliationKeys,
 | 
					    allDailyAffiliationKeys,
 | 
				
			||||||
    cleanupInventory,
 | 
					    cleanupInventory,
 | 
				
			||||||
    createLibraryDailyTask
 | 
					    createLibraryDailyTask,
 | 
				
			||||||
 | 
					    generateRewardSeed
 | 
				
			||||||
} from "@/src/services/inventoryService";
 | 
					} from "@/src/services/inventoryService";
 | 
				
			||||||
import { logger } from "@/src/utils/logger";
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
import { catBreadHash } from "@/src/helpers/stringHelpers";
 | 
					import { catBreadHash } from "@/src/helpers/stringHelpers";
 | 
				
			||||||
 | 
					import { Types } from "mongoose";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const inventoryController: RequestHandler = async (request, response) => {
 | 
					export const inventoryController: RequestHandler = async (request, response) => {
 | 
				
			||||||
    const accountId = await getAccountIdForRequest(request);
 | 
					    const accountId = await getAccountIdForRequest(request);
 | 
				
			||||||
@ -87,7 +89,7 @@ export const inventoryController: RequestHandler = async (request, response) =>
 | 
				
			|||||||
        cleanupInventory(inventory);
 | 
					        cleanupInventory(inventory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inventory.NextRefill = new Date((Math.trunc(Date.now() / 86400000) + 1) * 86400000);
 | 
					        inventory.NextRefill = new Date((Math.trunc(Date.now() / 86400000) + 1) * 86400000);
 | 
				
			||||||
        await inventory.save();
 | 
					        //await inventory.save();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (
 | 
					    if (
 | 
				
			||||||
@ -96,9 +98,20 @@ export const inventoryController: RequestHandler = async (request, response) =>
 | 
				
			|||||||
        new Date() >= inventory.InfestedFoundry.AbilityOverrideUnlockCooldown
 | 
					        new Date() >= inventory.InfestedFoundry.AbilityOverrideUnlockCooldown
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        handleSubsumeCompletion(inventory);
 | 
					        handleSubsumeCompletion(inventory);
 | 
				
			||||||
        await inventory.save();
 | 
					        //await inventory.save();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (inventory.LastInventorySync) {
 | 
				
			||||||
 | 
					        const lastSyncDuviriMood = Math.trunc(inventory.LastInventorySync.getTimestamp().getTime() / 7200000);
 | 
				
			||||||
 | 
					        const currentDuviriMood = Math.trunc(Date.now() / 7200000);
 | 
				
			||||||
 | 
					        if (lastSyncDuviriMood != currentDuviriMood) {
 | 
				
			||||||
 | 
					            logger.debug(`refreshing duviri seed`);
 | 
				
			||||||
 | 
					            inventory.DuviriInfo.Seed = generateRewardSeed();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    inventory.LastInventorySync = new Types.ObjectId();
 | 
				
			||||||
 | 
					    await inventory.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    response.json(await getInventoryResponse(inventory, "xpBasedLevelCapDisabled" in request.query));
 | 
					    response.json(await getInventoryResponse(inventory, "xpBasedLevelCapDisabled" in request.query));
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -274,7 +287,7 @@ export const getInventoryResponse = async (
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Omitting this field so opening the navigation resyncs the inventory which is more desirable for typical usage.
 | 
					    // Omitting this field so opening the navigation resyncs the inventory which is more desirable for typical usage.
 | 
				
			||||||
    //inventoryResponse.LastInventorySync = toOid(new Types.ObjectId());
 | 
					    inventoryResponse.LastInventorySync = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Set 2FA enabled so trading post can be used
 | 
					    // Set 2FA enabled so trading post can be used
 | 
				
			||||||
    inventoryResponse.HWIDProtectEnabled = true;
 | 
					    inventoryResponse.HWIDProtectEnabled = true;
 | 
				
			||||||
 | 
				
			|||||||
@ -2,9 +2,12 @@ import {
 | 
				
			|||||||
    consumeModCharge,
 | 
					    consumeModCharge,
 | 
				
			||||||
    encodeNemesisGuess,
 | 
					    encodeNemesisGuess,
 | 
				
			||||||
    getInfNodes,
 | 
					    getInfNodes,
 | 
				
			||||||
 | 
					    getKnifeUpgrade,
 | 
				
			||||||
    getNemesisPasscode,
 | 
					    getNemesisPasscode,
 | 
				
			||||||
 | 
					    getNemesisPasscodeModTypes,
 | 
				
			||||||
    getWeaponsForManifest,
 | 
					    getWeaponsForManifest,
 | 
				
			||||||
    IKnifeResponse
 | 
					    IKnifeResponse,
 | 
				
			||||||
 | 
					    showdownNodes
 | 
				
			||||||
} from "@/src/helpers/nemesisHelpers";
 | 
					} from "@/src/helpers/nemesisHelpers";
 | 
				
			||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
					import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
				
			||||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
 | 
					import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
 | 
				
			||||||
@ -15,6 +18,8 @@ import { IMongoDate, IOid } from "@/src/types/commonTypes";
 | 
				
			|||||||
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
					import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
    IInnateDamageFingerprint,
 | 
					    IInnateDamageFingerprint,
 | 
				
			||||||
 | 
					    IInventoryClient,
 | 
				
			||||||
 | 
					    INemesisClient,
 | 
				
			||||||
    InventorySlot,
 | 
					    InventorySlot,
 | 
				
			||||||
    IUpgradeClient,
 | 
					    IUpgradeClient,
 | 
				
			||||||
    IWeaponSkinClient,
 | 
					    IWeaponSkinClient,
 | 
				
			||||||
@ -100,13 +105,14 @@ export const nemesisController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
                encodeNemesisGuess(guess[0], result1, guess[1], result2, guess[2], result3)
 | 
					                encodeNemesisGuess(guess[0], result1, guess[1], result2, guess[2], result3)
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Increase antivirus
 | 
					            // Increase antivirus if correct antivirus mod is installed
 | 
				
			||||||
 | 
					            const response: IKnifeResponse = {};
 | 
				
			||||||
 | 
					            if (result1 == 0 || result2 == 0 || result3 == 0) {
 | 
				
			||||||
                let antivirusGain = 5;
 | 
					                let antivirusGain = 5;
 | 
				
			||||||
                const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
 | 
					                const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
 | 
				
			||||||
                const dataknifeLoadout = loadout.DATAKNIFE.id(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid);
 | 
					                const dataknifeLoadout = loadout.DATAKNIFE.id(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid);
 | 
				
			||||||
                const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
 | 
					                const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
 | 
				
			||||||
                const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
 | 
					                const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
 | 
				
			||||||
            const response: IKnifeResponse = {};
 | 
					 | 
				
			||||||
                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":
 | 
				
			||||||
@ -132,18 +138,12 @@ export const nemesisController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                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;
 | 
				
			||||||
                inventory.Nemesis!.InfNodes = [
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        Node: "CrewBattleNode559",
 | 
					 | 
				
			||||||
                        Influence: 1
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
                ];
 | 
					 | 
				
			||||||
                inventory.Nemesis!.Weakened = true;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
            inventory.Nemesis!.InfNodes = getInfNodes("FC_INFESTATION", 0);
 | 
					            inventory.Nemesis!.InfNodes = getInfNodes("FC_INFESTATION", 0);
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await inventory.save();
 | 
					            await inventory.save();
 | 
				
			||||||
            res.json(response);
 | 
					            res.json(response);
 | 
				
			||||||
@ -213,6 +213,38 @@ export const nemesisController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
        res.json({
 | 
					        res.json({
 | 
				
			||||||
            target: inventory.toJSON().Nemesis
 | 
					            target: inventory.toJSON().Nemesis
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					    } else if ((req.query.mode as string) == "w") {
 | 
				
			||||||
 | 
					        const inventory = await getInventory(
 | 
				
			||||||
 | 
					            accountId,
 | 
				
			||||||
 | 
					            "Nemesis LoadOutPresets CurrentLoadOutIds DataKnives Upgrades RawUpgrades"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        //const body = getJSONfromString<INemesisWeakenRequest>(String(req.body));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inventory.Nemesis!.InfNodes = [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Node: showdownNodes[inventory.Nemesis!.Faction],
 | 
				
			||||||
 | 
					                Influence: 1
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					        inventory.Nemesis!.Weakened = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const response: IKnifeResponse & { target: INemesisClient } = {
 | 
				
			||||||
 | 
					            target: inventory.toJSON<IInventoryClient>().Nemesis!
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Consume charge of the correct requiem mod(s)
 | 
				
			||||||
 | 
					        const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
 | 
				
			||||||
 | 
					        const dataknifeLoadout = loadout.DATAKNIFE.id(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid);
 | 
				
			||||||
 | 
					        const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
 | 
				
			||||||
 | 
					        const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
 | 
				
			||||||
 | 
					        const modTypes = getNemesisPasscodeModTypes(inventory.Nemesis!);
 | 
				
			||||||
 | 
					        for (const modType of modTypes) {
 | 
				
			||||||
 | 
					            const upgrade = getKnifeUpgrade(inventory, dataknifeUpgrades, modType);
 | 
				
			||||||
 | 
					            consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await inventory.save();
 | 
				
			||||||
 | 
					        res.json(response);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
 | 
					        logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
 | 
				
			||||||
        throw new Error(`unknown nemesis mode: ${String(req.query.mode)}`);
 | 
					        throw new Error(`unknown nemesis mode: ${String(req.query.mode)}`);
 | 
				
			||||||
@ -264,12 +296,19 @@ interface INemesisRequiemRequest {
 | 
				
			|||||||
    guess: number; // grn/crp: 4 bits | coda: 3x 4 bits
 | 
					    guess: number; // grn/crp: 4 bits | coda: 3x 4 bits
 | 
				
			||||||
    position: number; // grn/crp: 0-2 | coda: 0
 | 
					    position: number; // grn/crp: 0-2 | coda: 0
 | 
				
			||||||
    // knife field provided for coda only
 | 
					    // knife field provided for coda only
 | 
				
			||||||
    knife?: {
 | 
					    knife?: IKnife;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// interface INemesisWeakenRequest {
 | 
				
			||||||
 | 
					//     target: INemesisClient;
 | 
				
			||||||
 | 
					//     knife: IKnife;
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IKnife {
 | 
				
			||||||
    Item: IEquipmentClient;
 | 
					    Item: IEquipmentClient;
 | 
				
			||||||
    Skins: IWeaponSkinClient[];
 | 
					    Skins: IWeaponSkinClient[];
 | 
				
			||||||
    ModSlot: number;
 | 
					    ModSlot: number;
 | 
				
			||||||
    CustSlot: number;
 | 
					    CustSlot: number;
 | 
				
			||||||
    AttachedUpgrades: IUpgradeClient[];
 | 
					    AttachedUpgrades: IUpgradeClient[];
 | 
				
			||||||
    HiddenWhenHolstered: boolean;
 | 
					    HiddenWhenHolstered: boolean;
 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,14 @@
 | 
				
			|||||||
import { ExportRegions, ExportWarframes } from "warframe-public-export-plus";
 | 
					import { ExportRegions, ExportWarframes } from "warframe-public-export-plus";
 | 
				
			||||||
import { IInfNode } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
					import { IInfNode, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
				
			||||||
import { SRng } from "@/src/services/rngService";
 | 
					import { getRewardAtPercentage, SRng } from "@/src/services/rngService";
 | 
				
			||||||
import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel";
 | 
					import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel";
 | 
				
			||||||
import { logger } from "../utils/logger";
 | 
					import { logger } from "../utils/logger";
 | 
				
			||||||
import { IOid } from "../types/commonTypes";
 | 
					import { IOid } from "../types/commonTypes";
 | 
				
			||||||
import { Types } from "mongoose";
 | 
					import { Types } from "mongoose";
 | 
				
			||||||
import { addMods } from "../services/inventoryService";
 | 
					import { addMods, generateRewardSeed } from "../services/inventoryService";
 | 
				
			||||||
import { isArchwingMission } from "../services/worldStateService";
 | 
					import { isArchwingMission } from "../services/worldStateService";
 | 
				
			||||||
 | 
					import { fromStoreItem, toStoreItem } from "../services/itemDataService";
 | 
				
			||||||
 | 
					import { createMessage } from "../services/inboxService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getInfNodes = (faction: string, rank: number): IInfNode[] => {
 | 
					export const getInfNodes = (faction: string, rank: number): IInfNode[] => {
 | 
				
			||||||
    const infNodes = [];
 | 
					    const infNodes = [];
 | 
				
			||||||
@ -38,17 +40,59 @@ const systemIndexes: Record<string, number[]> = {
 | 
				
			|||||||
    FC_INFESTATION: [23]
 | 
					    FC_INFESTATION: [23]
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const showdownNodes: Record<string, string> = {
 | 
				
			||||||
 | 
					    FC_GRINEER: "CrewBattleNode557",
 | 
				
			||||||
 | 
					    FC_CORPUS: "CrewBattleNode558",
 | 
				
			||||||
 | 
					    FC_INFESTATION: "CrewBattleNode559"
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get a parazon 'passcode' based on the nemesis fingerprint so it's always the same for the same nemesis.
 | 
					// Get a parazon 'passcode' based on the nemesis fingerprint so it's always the same for the same nemesis.
 | 
				
			||||||
export const getNemesisPasscode = (nemesis: { fp: bigint; Faction: string }): number[] => {
 | 
					export const getNemesisPasscode = (nemesis: { fp: bigint; Faction: string }): number[] => {
 | 
				
			||||||
    const rng = new SRng(nemesis.fp);
 | 
					    const rng = new SRng(nemesis.fp);
 | 
				
			||||||
    const passcode = [rng.randomInt(0, 7)];
 | 
					    const choices = [0, 1, 2, 3, 5, 6, 7];
 | 
				
			||||||
 | 
					    let choiceIndex = rng.randomInt(0, choices.length - 1);
 | 
				
			||||||
 | 
					    const passcode = [choices[choiceIndex]];
 | 
				
			||||||
    if (nemesis.Faction != "FC_INFESTATION") {
 | 
					    if (nemesis.Faction != "FC_INFESTATION") {
 | 
				
			||||||
        passcode.push(rng.randomInt(0, 7));
 | 
					        choices.splice(choiceIndex, 1);
 | 
				
			||||||
        passcode.push(rng.randomInt(0, 7));
 | 
					        choiceIndex = rng.randomInt(0, choices.length - 1);
 | 
				
			||||||
 | 
					        passcode.push(choices[choiceIndex]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        choices.splice(choiceIndex, 1);
 | 
				
			||||||
 | 
					        choiceIndex = rng.randomInt(0, choices.length - 1);
 | 
				
			||||||
 | 
					        passcode.push(choices[choiceIndex]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return passcode;
 | 
					    return passcode;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const reqiuemMods: readonly string[] = [
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/ImmortalOneMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/ImmortalTwoMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/ImmortalThreeMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/ImmortalFourMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/ImmortalFiveMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/ImmortalSixMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/ImmortalSevenMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/ImmortalEightMod"
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const antivirusMods: readonly string[] = [
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/AntivirusOneMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/AntivirusTwoMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/AntivirusThreeMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/AntivirusFourMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/AntivirusFiveMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/AntivirusSixMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/AntivirusSevenMod",
 | 
				
			||||||
 | 
					    "/Lotus/Upgrades/Mods/Immortal/AntivirusEightMod"
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getNemesisPasscodeModTypes = (nemesis: { fp: bigint; Faction: string }): string[] => {
 | 
				
			||||||
 | 
					    const passcode = getNemesisPasscode(nemesis);
 | 
				
			||||||
 | 
					    return nemesis.Faction == "FC_INFESTATION"
 | 
				
			||||||
 | 
					        ? passcode.map(i => antivirusMods[i])
 | 
				
			||||||
 | 
					        : passcode.map(i => reqiuemMods[i]);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const encodeNemesisGuess = (
 | 
					export const encodeNemesisGuess = (
 | 
				
			||||||
    symbol1: number,
 | 
					    symbol1: number,
 | 
				
			||||||
    result1: number,
 | 
					    result1: number,
 | 
				
			||||||
@ -79,6 +123,31 @@ export interface IKnifeResponse {
 | 
				
			|||||||
    HasKnife?: boolean;
 | 
					    HasKnife?: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getKnifeUpgrade = (
 | 
				
			||||||
 | 
					    inventory: TInventoryDatabaseDocument,
 | 
				
			||||||
 | 
					    dataknifeUpgrades: string[],
 | 
				
			||||||
 | 
					    type: string
 | 
				
			||||||
 | 
					): { ItemId: IOid; ItemType: string } => {
 | 
				
			||||||
 | 
					    if (dataknifeUpgrades.indexOf(type) != -1) {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            ItemId: { $oid: "000000000000000000000000" },
 | 
				
			||||||
 | 
					            ItemType: type
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    for (const upgradeId of dataknifeUpgrades) {
 | 
				
			||||||
 | 
					        if (upgradeId.length == 24) {
 | 
				
			||||||
 | 
					            const upgrade = inventory.Upgrades.id(upgradeId);
 | 
				
			||||||
 | 
					            if (upgrade && upgrade.ItemType == type) {
 | 
				
			||||||
 | 
					                return {
 | 
				
			||||||
 | 
					                    ItemId: { $oid: upgradeId },
 | 
				
			||||||
 | 
					                    ItemType: type
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    throw new Error(`${type} does not seem to be installed on parazon?!`);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const consumeModCharge = (
 | 
					export const consumeModCharge = (
 | 
				
			||||||
    response: IKnifeResponse,
 | 
					    response: IKnifeResponse,
 | 
				
			||||||
    inventory: TInventoryDatabaseDocument,
 | 
					    inventory: TInventoryDatabaseDocument,
 | 
				
			||||||
@ -177,7 +246,6 @@ export const getWeaponsForManifest = (manifest: string): readonly string[] => {
 | 
				
			|||||||
    throw new Error(`unknown nemesis manifest: ${manifest}`);
 | 
					    throw new Error(`unknown nemesis manifest: ${manifest}`);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: This sucks.
 | 
					 | 
				
			||||||
export const getInnateDamageTag = (
 | 
					export const getInnateDamageTag = (
 | 
				
			||||||
    KillingSuit: string
 | 
					    KillingSuit: string
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
@ -188,78 +256,7 @@ export const getInnateDamageTag = (
 | 
				
			|||||||
    | "InnateMagDamage"
 | 
					    | "InnateMagDamage"
 | 
				
			||||||
    | "InnateRadDamage"
 | 
					    | "InnateRadDamage"
 | 
				
			||||||
    | "InnateToxinDamage" => {
 | 
					    | "InnateToxinDamage" => {
 | 
				
			||||||
    const baseSuitType = ExportWarframes[KillingSuit].parentName;
 | 
					    return ExportWarframes[KillingSuit].nemesisUpgradeTag!;
 | 
				
			||||||
    switch (baseSuitType) {
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Volt/VoltBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Excalibur/ExcaliburBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/AntiMatter/NovaBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Banshee/BansheeBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Berserker/BerserkerBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Magician/MagicianBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Sentient/SentientBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Gyre/GyreBaseSuit":
 | 
					 | 
				
			||||||
            return "InnateElectricityDamage";
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Ember/EmberBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Dragon/DragonBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Nezha/NezhaBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Sandman/SandmanBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Trapper/TrapperBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Wisp/WispBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Odalisk/OdaliskBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/PaxDuviricus/PaxDuviricusBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Choir/ChoirBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Temple/TempleBaseSuit":
 | 
					 | 
				
			||||||
            return "InnateHeatDamage";
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Frost/FrostBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Glass/GlassBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Fairy/FairyBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/IronFrame/IronFrameBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Revenant/RevenantBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Trinity/TrinityBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Hoplite/HopliteBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Koumei/KoumeiBaseSuit":
 | 
					 | 
				
			||||||
            return "InnateFreezeDamage";
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Saryn/SarynBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Paladin/PaladinBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Brawler/BrawlerBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Infestation/InfestationBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Necro/NecroBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Khora/KhoraBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Ranger/RangerBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Dagath/DagathBaseSuit":
 | 
					 | 
				
			||||||
            return "InnateToxinDamage";
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Mag/MagBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Pirate/PirateBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Cowgirl/CowgirlBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Priest/PriestBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/BrokenFrame/BrokenFrameBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Alchemist/AlchemistBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Yareli/YareliBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Geode/GeodeBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Frumentarius/FrumentariusBaseSuit":
 | 
					 | 
				
			||||||
            return "InnateMagDamage";
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Loki/LokiBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Ninja/NinjaBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Jade/JadeBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Bard/BardBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Harlequin/HarlequinBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Garuda/GarudaBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/YinYang/YinYangBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Werewolf/WerewolfBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/ConcreteFrame/ConcreteFrameBaseSuit":
 | 
					 | 
				
			||||||
            return "InnateRadDamage";
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Rhino/RhinoBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Tengu/TenguBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/MonkeyKing/MonkeyKingBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Runner/RunnerBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Pacifist/PacifistBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Devourer/DevourerBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Wraith/WraithBaseSuit":
 | 
					 | 
				
			||||||
        case "/Lotus/Powersuits/Pagemaster/PagemasterBaseSuit":
 | 
					 | 
				
			||||||
            return "InnateImpactDamage";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    logger.warn(`unknown innate damage type for ${KillingSuit}, using heat as a fallback`);
 | 
					 | 
				
			||||||
    return "InnateHeatDamage";
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: For -1399275245665749231n, the value should be 75306944, but we're off by 59 with 75307003.
 | 
					// TODO: For -1399275245665749231n, the value should be 75306944, but we're off by 59 with 75307003.
 | 
				
			||||||
@ -273,3 +270,109 @@ export const getInnateDamageValue = (fp: bigint): number => {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    return Math.trunc(value * 0x40000000);
 | 
					    return Math.trunc(value * 0x40000000);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getKillTokenRewardCount = (fp: bigint): number => {
 | 
				
			||||||
 | 
					    const rng = new SRng(fp);
 | 
				
			||||||
 | 
					    return rng.randomInt(10, 15);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// /Lotus/Types/Enemies/InfestedLich/InfestedLichRewardManifest
 | 
				
			||||||
 | 
					const infestedLichRotA = [
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyDJRomHuman", probability: 0.046 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyDJRomInfested", probability: 0.045 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyDrillbitHuman", probability: 0.046 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyDrillbitInfested", probability: 0.045 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyHarddriveHuman", probability: 0.046 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyHarddriveInfested", probability: 0.045 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyPacketHuman", probability: 0.046 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyPacketInfested", probability: 0.045 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyZekeHuman", probability: 0.046 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyZekeInfested", probability: 0.045 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/BoybandPosters/BoybandBillboardPosterA", probability: 0.045 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/BoybandPosters/BoybandBillboardPosterB", probability: 0.046 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/BoybandPosters/BoybandDespairPoster", probability: 0.045 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/BoybandPosters/BoybandGridPoster", probability: 0.046 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/BoybandPosters/BoybandHuddlePoster", probability: 0.045 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/BoybandPosters/BoybandJumpPoster", probability: 0.046 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/BoybandPosters/BoybandLimoPoster", probability: 0.045 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/BoybandPosters/BoybandLookingDownPosterDay", probability: 0.046 },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        type: "/Lotus/StoreItems/Types/Items/ShipDecos/BoybandPosters/BoybandLookingDownPosterNight",
 | 
				
			||||||
 | 
					        probability: 0.045
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/BoybandPosters/BoybandSillyPoster", probability: 0.046 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/BoybandPosters/BoybandWhiteBluePoster", probability: 0.045 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/ShipDecos/BoybandPosters/BoybandWhitePinkPoster", probability: 0.045 }
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					const infestedLichRotB = [
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Upgrades/Skins/Effects/InfestedLichEphemeraA", probability: 0.072 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Upgrades/Skins/Effects/InfestedLichEphemeraB", probability: 0.071 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Upgrades/Skins/Effects/InfestedLichEphemeraC", probability: 0.072 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Upgrades/Skins/Effects/InfestedLichEphemeraD", probability: 0.071 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Upgrades/Skins/Effects/InfestedLichEphemeraE", probability: 0.072 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Upgrades/Skins/Effects/InfestedLichEphemeraF", probability: 0.071 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Upgrades/Skins/Effects/InfestedLichEphemeraG", probability: 0.071 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Upgrades/Skins/Effects/InfestedLichEphemeraH", probability: 0.072 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/Emotes/DanceDJRomHype", probability: 0.071 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/Emotes/DancePacketWindmillShuffle", probability: 0.072 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/Emotes/DanceHarddrivePony", probability: 0.071 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/Emotes/DanceDrillbitCrisscross", probability: 0.072 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/Emotes/DanceZekeCanthavethis", probability: 0.071 },
 | 
				
			||||||
 | 
					    { type: "/Lotus/StoreItems/Types/Items/PhotoBooth/PhotoboothTileRJLasXStadiumBossArena", probability: 0.071 }
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					export const getInfestedLichItemRewards = (fp: bigint): string[] => {
 | 
				
			||||||
 | 
					    const rng = new SRng(fp);
 | 
				
			||||||
 | 
					    const rotAReward = getRewardAtPercentage(infestedLichRotA, rng.randomFloat())!.type;
 | 
				
			||||||
 | 
					    rng.randomFloat(); // unused afaict
 | 
				
			||||||
 | 
					    const rotBReward = getRewardAtPercentage(infestedLichRotB, rng.randomFloat())!.type;
 | 
				
			||||||
 | 
					    return [rotAReward, rotBReward];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const sendCodaFinishedMessage = async (
 | 
				
			||||||
 | 
					    inventory: TInventoryDatabaseDocument,
 | 
				
			||||||
 | 
					    fp: bigint = generateRewardSeed(),
 | 
				
			||||||
 | 
					    name: string = "ZEKE_BEATWOMAN_TM.1999",
 | 
				
			||||||
 | 
					    killed: boolean = true
 | 
				
			||||||
 | 
					): Promise<void> => {
 | 
				
			||||||
 | 
					    const att: string[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // First vanquish/convert gives a sigil
 | 
				
			||||||
 | 
					    const sigil = killed
 | 
				
			||||||
 | 
					        ? "/Lotus/Upgrades/Skins/Sigils/InfLichVanquishedSigil"
 | 
				
			||||||
 | 
					        : "/Lotus/Upgrades/Skins/Sigils/InfLichConvertedSigil";
 | 
				
			||||||
 | 
					    if (!inventory.WeaponSkins.find(x => x.ItemType == sigil)) {
 | 
				
			||||||
 | 
					        att.push(toStoreItem(sigil));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const [rotAReward, rotBReward] = getInfestedLichItemRewards(fp);
 | 
				
			||||||
 | 
					    att.push(fromStoreItem(rotAReward));
 | 
				
			||||||
 | 
					    att.push(fromStoreItem(rotBReward));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let countedAtt: ITypeCount[] | undefined;
 | 
				
			||||||
 | 
					    if (killed) {
 | 
				
			||||||
 | 
					        countedAtt = [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ItemType: "/Lotus/Types/Items/MiscItems/CodaWeaponBucks",
 | 
				
			||||||
 | 
					                ItemCount: getKillTokenRewardCount(fp)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await createMessage(inventory.accountOwnerId, [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            sndr: "/Lotus/Language/Bosses/Ordis",
 | 
				
			||||||
 | 
					            msg: "/Lotus/Language/Inbox/VanquishBandMsgBody",
 | 
				
			||||||
 | 
					            arg: [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Key: "LICH_NAME",
 | 
				
			||||||
 | 
					                    Tag: name
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            att: att,
 | 
				
			||||||
 | 
					            countedAtt: countedAtt,
 | 
				
			||||||
 | 
					            sub: "/Lotus/Language/Inbox/VanquishBandMsgTitle",
 | 
				
			||||||
 | 
					            icon: "/Lotus/Interface/Icons/Npcs/Ordis.png",
 | 
				
			||||||
 | 
					            highPriority: true
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -1399,7 +1399,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
				
			|||||||
        //How many Gift do you have left*(gift spends the trade)
 | 
					        //How many Gift do you have left*(gift spends the trade)
 | 
				
			||||||
        GiftsRemaining: { type: Number, default: 8 },
 | 
					        GiftsRemaining: { type: Number, default: 8 },
 | 
				
			||||||
        //Curent trade info Giving or Getting items
 | 
					        //Curent trade info Giving or Getting items
 | 
				
			||||||
        PendingTrades: [Schema.Types.Mixed],
 | 
					        //PendingTrades: [Schema.Types.Mixed],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //Syndicate currently being pledged to.
 | 
					        //Syndicate currently being pledged to.
 | 
				
			||||||
        SupportedSyndicate: String,
 | 
					        SupportedSyndicate: String,
 | 
				
			||||||
@ -1449,7 +1449,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        KubrowPetEggs: [kubrowPetEggSchema],
 | 
					        KubrowPetEggs: [kubrowPetEggSchema],
 | 
				
			||||||
        //Prints   Cat(3 Prints)\Kubrow(2 Prints) Pets
 | 
					        //Prints   Cat(3 Prints)\Kubrow(2 Prints) Pets
 | 
				
			||||||
        KubrowPetPrints: [Schema.Types.Mixed],
 | 
					        //KubrowPetPrints: [Schema.Types.Mixed],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //Item for EquippedGear example:Scaner,LoadoutTechSummon etc
 | 
					        //Item for EquippedGear example:Scaner,LoadoutTechSummon etc
 | 
				
			||||||
        Consumables: [typeCountSchema],
 | 
					        Consumables: [typeCountSchema],
 | 
				
			||||||
@ -1495,7 +1495,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
				
			|||||||
        //item like DojoKey or Boss missions key
 | 
					        //item like DojoKey or Boss missions key
 | 
				
			||||||
        LevelKeys: [typeCountSchema],
 | 
					        LevelKeys: [typeCountSchema],
 | 
				
			||||||
        //Active quests
 | 
					        //Active quests
 | 
				
			||||||
        Quests: [Schema.Types.Mixed],
 | 
					        //Quests: [Schema.Types.Mixed],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //Cosmetics like profile glyphs\Kavasa Prime Kubrow Collar\Game Theme etc
 | 
					        //Cosmetics like profile glyphs\Kavasa Prime Kubrow Collar\Game Theme etc
 | 
				
			||||||
        FlavourItems: [FlavourItemSchema],
 | 
					        FlavourItems: [FlavourItemSchema],
 | 
				
			||||||
@ -1534,7 +1534,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
				
			|||||||
        TauntHistory: { type: [tauntSchema], default: undefined },
 | 
					        TauntHistory: { type: [tauntSchema], default: undefined },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //noShow2FA,VisitPrimeVault etc
 | 
					        //noShow2FA,VisitPrimeVault etc
 | 
				
			||||||
        WebFlags: Schema.Types.Mixed,
 | 
					        //WebFlags: Schema.Types.Mixed,
 | 
				
			||||||
        //Id CompletedAlerts
 | 
					        //Id CompletedAlerts
 | 
				
			||||||
        CompletedAlerts: [String],
 | 
					        CompletedAlerts: [String],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1554,7 +1554,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
				
			|||||||
        //the color your clan requests like Items/Research/DojoColors/DojoColorPlainsB
 | 
					        //the color your clan requests like Items/Research/DojoColors/DojoColorPlainsB
 | 
				
			||||||
        ActiveDojoColorResearch: String,
 | 
					        ActiveDojoColorResearch: String,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SentientSpawnChanceBoosters: Schema.Types.Mixed,
 | 
					        //SentientSpawnChanceBoosters: Schema.Types.Mixed,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        QualifyingInvasions: [invasionProgressSchema],
 | 
					        QualifyingInvasions: [invasionProgressSchema],
 | 
				
			||||||
        FactionScores: [Number],
 | 
					        FactionScores: [Number],
 | 
				
			||||||
@ -1589,10 +1589,10 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
				
			|||||||
        // open location store like EidolonPlainsDiscoverable or OrbVallisCaveDiscoverable
 | 
					        // open location store like EidolonPlainsDiscoverable or OrbVallisCaveDiscoverable
 | 
				
			||||||
        DiscoveredMarkers: [discoveredMarkerSchema],
 | 
					        DiscoveredMarkers: [discoveredMarkerSchema],
 | 
				
			||||||
        //Open location mission like "JobId" + "StageCompletions"
 | 
					        //Open location mission like "JobId" + "StageCompletions"
 | 
				
			||||||
        CompletedJobs: [Schema.Types.Mixed],
 | 
					        //CompletedJobs: [Schema.Types.Mixed],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //Game mission\ivent score example  "Tag": "WaterFight", "Best": 170, "Count": 1258,
 | 
					        //Game mission\ivent score example  "Tag": "WaterFight", "Best": 170, "Count": 1258,
 | 
				
			||||||
        PersonalGoalProgress: [Schema.Types.Mixed],
 | 
					        //PersonalGoalProgress: [Schema.Types.Mixed],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //Setting interface Style
 | 
					        //Setting interface Style
 | 
				
			||||||
        ThemeStyle: String,
 | 
					        ThemeStyle: String,
 | 
				
			||||||
@ -1622,13 +1622,13 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
				
			|||||||
        LibraryActiveDailyTaskInfo: libraryDailyTaskInfoSchema,
 | 
					        LibraryActiveDailyTaskInfo: libraryDailyTaskInfoSchema,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //https://warframe.fandom.com/wiki/Invasion
 | 
					        //https://warframe.fandom.com/wiki/Invasion
 | 
				
			||||||
        InvasionChainProgress: [Schema.Types.Mixed],
 | 
					        //InvasionChainProgress: [Schema.Types.Mixed],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //CorpusLich or GrineerLich
 | 
					        //CorpusLich or GrineerLich
 | 
				
			||||||
        NemesisAbandonedRewards: { type: [String], default: [] },
 | 
					        NemesisAbandonedRewards: { type: [String], default: [] },
 | 
				
			||||||
        Nemesis: nemesisSchema,
 | 
					        Nemesis: nemesisSchema,
 | 
				
			||||||
        NemesisHistory: { type: [nemesisSchema], default: undefined },
 | 
					        NemesisHistory: { type: [nemesisSchema], default: undefined },
 | 
				
			||||||
        LastNemesisAllySpawnTime: Schema.Types.Mixed,
 | 
					        //LastNemesisAllySpawnTime: Schema.Types.Mixed,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //TradingRulesConfirmed,ShowFriendInvNotifications(Option->Social)
 | 
					        //TradingRulesConfirmed,ShowFriendInvNotifications(Option->Social)
 | 
				
			||||||
        Settings: settingsSchema,
 | 
					        Settings: settingsSchema,
 | 
				
			||||||
@ -1642,7 +1642,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
				
			|||||||
        PlayerSkills: { type: playerSkillsSchema, default: {} },
 | 
					        PlayerSkills: { type: playerSkillsSchema, default: {} },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //TradeBannedUntil data
 | 
					        //TradeBannedUntil data
 | 
				
			||||||
        TradeBannedUntil: Schema.Types.Mixed,
 | 
					        //TradeBannedUntil: Schema.Types.Mixed,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //https://warframe.fandom.com/wiki/Helminth
 | 
					        //https://warframe.fandom.com/wiki/Helminth
 | 
				
			||||||
        InfestedFoundry: infestedFoundrySchema,
 | 
					        InfestedFoundry: infestedFoundrySchema,
 | 
				
			||||||
@ -1662,23 +1662,24 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        //Unknown and system
 | 
					        //Unknown and system
 | 
				
			||||||
        DuviriInfo: DuviriInfoSchema,
 | 
					        DuviriInfo: DuviriInfoSchema,
 | 
				
			||||||
 | 
					        LastInventorySync: Schema.Types.ObjectId,
 | 
				
			||||||
        Mailbox: MailboxSchema,
 | 
					        Mailbox: MailboxSchema,
 | 
				
			||||||
        HandlerPoints: Number,
 | 
					        HandlerPoints: Number,
 | 
				
			||||||
        ChallengesFixVersion: { type: Number, default: 6 },
 | 
					        ChallengesFixVersion: { type: Number, default: 6 },
 | 
				
			||||||
        PlayedParkourTutorial: Boolean,
 | 
					        PlayedParkourTutorial: Boolean,
 | 
				
			||||||
        ActiveLandscapeTraps: [Schema.Types.Mixed],
 | 
					        //ActiveLandscapeTraps: [Schema.Types.Mixed],
 | 
				
			||||||
        RepVotes: [Schema.Types.Mixed],
 | 
					        //RepVotes: [Schema.Types.Mixed],
 | 
				
			||||||
        LeagueTickets: [Schema.Types.Mixed],
 | 
					        //LeagueTickets: [Schema.Types.Mixed],
 | 
				
			||||||
        HasContributedToDojo: Boolean,
 | 
					        HasContributedToDojo: Boolean,
 | 
				
			||||||
        HWIDProtectEnabled: Boolean,
 | 
					        HWIDProtectEnabled: Boolean,
 | 
				
			||||||
        LoadOutPresets: { type: Schema.Types.ObjectId, ref: "Loadout" },
 | 
					        LoadOutPresets: { type: Schema.Types.ObjectId, ref: "Loadout" },
 | 
				
			||||||
        CurrentLoadOutIds: [oidSchema],
 | 
					        CurrentLoadOutIds: [oidSchema],
 | 
				
			||||||
        RandomUpgradesIdentified: Number,
 | 
					        RandomUpgradesIdentified: Number,
 | 
				
			||||||
        BountyScore: Number,
 | 
					        BountyScore: Number,
 | 
				
			||||||
        ChallengeInstanceStates: [Schema.Types.Mixed],
 | 
					        //ChallengeInstanceStates: [Schema.Types.Mixed],
 | 
				
			||||||
        RecentVendorPurchases: { type: [recentVendorPurchaseSchema], default: undefined },
 | 
					        RecentVendorPurchases: { type: [recentVendorPurchaseSchema], default: undefined },
 | 
				
			||||||
        Robotics: [Schema.Types.Mixed],
 | 
					        //Robotics: [Schema.Types.Mixed],
 | 
				
			||||||
        UsedDailyDeals: [Schema.Types.Mixed],
 | 
					        //UsedDailyDeals: [Schema.Types.Mixed],
 | 
				
			||||||
        CollectibleSeries: { type: [collectibleEntrySchema], default: undefined },
 | 
					        CollectibleSeries: { type: [collectibleEntrySchema], default: undefined },
 | 
				
			||||||
        HasResetAccount: { type: Boolean, default: false },
 | 
					        HasResetAccount: { type: Boolean, default: false },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1759,6 +1760,9 @@ inventorySchema.set("toJSON", {
 | 
				
			|||||||
                sn: inventoryDatabase.LockedWeaponGroup.sn ? toOid(inventoryDatabase.LockedWeaponGroup.sn) : undefined
 | 
					                sn: inventoryDatabase.LockedWeaponGroup.sn ? toOid(inventoryDatabase.LockedWeaponGroup.sn) : undefined
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (inventoryDatabase.LastInventorySync) {
 | 
				
			||||||
 | 
					            inventoryResponse.LastInventorySync = toOid(inventoryDatabase.LastInventorySync);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,7 @@ import {
 | 
				
			|||||||
    dict_uk,
 | 
					    dict_uk,
 | 
				
			||||||
    dict_zh,
 | 
					    dict_zh,
 | 
				
			||||||
    ExportArcanes,
 | 
					    ExportArcanes,
 | 
				
			||||||
 | 
					    ExportBoosters,
 | 
				
			||||||
    ExportCustoms,
 | 
					    ExportCustoms,
 | 
				
			||||||
    ExportDrones,
 | 
					    ExportDrones,
 | 
				
			||||||
    ExportGear,
 | 
					    ExportGear,
 | 
				
			||||||
@ -217,15 +218,30 @@ export const convertInboxMessage = (message: IInboxMessage): IMessage => {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const isStoreItem = (type: string): boolean => {
 | 
					export const isStoreItem = (type: string): boolean => {
 | 
				
			||||||
    return type.startsWith("/Lotus/StoreItems/");
 | 
					    return type.startsWith("/Lotus/StoreItems/") || type in ExportBoosters;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const toStoreItem = (type: string): string => {
 | 
					export const toStoreItem = (type: string): string => {
 | 
				
			||||||
 | 
					    if (type.startsWith("/Lotus/Types/StoreItems/Boosters/")) {
 | 
				
			||||||
 | 
					        const boosterEntry = Object.entries(ExportBoosters).find(arr => arr[1].typeName == type);
 | 
				
			||||||
 | 
					        if (boosterEntry) {
 | 
				
			||||||
 | 
					            return boosterEntry[0];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        throw new Error(`could not convert ${type} to a store item`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return "/Lotus/StoreItems/" + type.substring("/Lotus/".length);
 | 
					    return "/Lotus/StoreItems/" + type.substring("/Lotus/".length);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const fromStoreItem = (type: string): string => {
 | 
					export const fromStoreItem = (type: string): string => {
 | 
				
			||||||
 | 
					    if (type.startsWith("/Lotus/StoreItems/")) {
 | 
				
			||||||
        return "/Lotus/" + type.substring("/Lotus/StoreItems/".length);
 | 
					        return "/Lotus/" + type.substring("/Lotus/StoreItems/".length);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (type in ExportBoosters) {
 | 
				
			||||||
 | 
					        return ExportBoosters[type].typeName;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    throw new Error(`${type} is not a store item`);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getDefaultUpgrades = (parts: string[]): IDefaultUpgrade[] | undefined => {
 | 
					export const getDefaultUpgrades = (parts: string[]): IDefaultUpgrade[] | undefined => {
 | 
				
			||||||
 | 
				
			|||||||
@ -77,7 +77,6 @@ const getRandomLoginReward = (rng: CRng, day: number, inventory: TInventoryDatab
 | 
				
			|||||||
    const reward = rng.randomReward(randomRewards)!;
 | 
					    const reward = rng.randomReward(randomRewards)!;
 | 
				
			||||||
    //const reward = randomRewards.find(x => x.RewardType == "RT_BOOSTER")!;
 | 
					    //const reward = randomRewards.find(x => x.RewardType == "RT_BOOSTER")!;
 | 
				
			||||||
    if (reward.RewardType == "RT_RANDOM_RECIPE") {
 | 
					    if (reward.RewardType == "RT_RANDOM_RECIPE") {
 | 
				
			||||||
        // Not very faithful implementation but roughly the same idea
 | 
					 | 
				
			||||||
        const masteredItems = new Set();
 | 
					        const masteredItems = new Set();
 | 
				
			||||||
        for (const entry of inventory.XPInfo) {
 | 
					        for (const entry of inventory.XPInfo) {
 | 
				
			||||||
            masteredItems.add(entry.ItemType);
 | 
					            masteredItems.add(entry.ItemType);
 | 
				
			||||||
@ -95,12 +94,12 @@ const getRandomLoginReward = (rng: CRng, day: number, inventory: TInventoryDatab
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        const eligibleRecipes: string[] = [];
 | 
					        const eligibleRecipes: string[] = [];
 | 
				
			||||||
        for (const [uniqueName, recipe] of Object.entries(ExportRecipes)) {
 | 
					        for (const [uniqueName, recipe] of Object.entries(ExportRecipes)) {
 | 
				
			||||||
            if (unmasteredItems.has(recipe.resultType)) {
 | 
					            if (!recipe.excludeFromMarket && unmasteredItems.has(recipe.resultType)) {
 | 
				
			||||||
                eligibleRecipes.push(uniqueName);
 | 
					                eligibleRecipes.push(uniqueName);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (eligibleRecipes.length == 0) {
 | 
					        if (eligibleRecipes.length == 0) {
 | 
				
			||||||
            // This account has all warframes and weapons already mastered (filthy cheater), need a different reward.
 | 
					            // This account has all applicable warframes and weapons already mastered (filthy cheater), need a different reward.
 | 
				
			||||||
            return getRandomLoginReward(rng, day, inventory);
 | 
					            return getRandomLoginReward(rng, day, inventory);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        reward.StoreItemType = toStoreItem(rng.randomElement(eligibleRecipes));
 | 
					        reward.StoreItemType = toStoreItem(rng.randomElement(eligibleRecipes));
 | 
				
			||||||
 | 
				
			|||||||
@ -55,7 +55,7 @@ import kuriaMessage50 from "@/static/fixed_responses/kuriaMessages/fiftyPercent.
 | 
				
			|||||||
import kuriaMessage75 from "@/static/fixed_responses/kuriaMessages/seventyFivePercent.json";
 | 
					import kuriaMessage75 from "@/static/fixed_responses/kuriaMessages/seventyFivePercent.json";
 | 
				
			||||||
import kuriaMessage100 from "@/static/fixed_responses/kuriaMessages/oneHundredPercent.json";
 | 
					import kuriaMessage100 from "@/static/fixed_responses/kuriaMessages/oneHundredPercent.json";
 | 
				
			||||||
import conservationAnimals from "@/static/fixed_responses/conservationAnimals.json";
 | 
					import conservationAnimals from "@/static/fixed_responses/conservationAnimals.json";
 | 
				
			||||||
import { getInfNodes, getWeaponsForManifest } from "@/src/helpers/nemesisHelpers";
 | 
					import { getInfNodes, getWeaponsForManifest, sendCodaFinishedMessage } 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 { getLiteSortie, getWorldState, idToWeek } from "./worldStateService";
 | 
					import { getLiteSortie, getWorldState, idToWeek } from "./worldStateService";
 | 
				
			||||||
@ -639,7 +639,10 @@ export const addMissionInventoryUpdates = async (
 | 
				
			|||||||
                    });
 | 
					                    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (value.killed) {
 | 
					                    if (value.killed) {
 | 
				
			||||||
                        if (value.weaponLoc) {
 | 
					                        if (
 | 
				
			||||||
 | 
					                            value.weaponLoc &&
 | 
				
			||||||
 | 
					                            inventory.Nemesis.Faction != "FC_INFESTATION" // weaponLoc is "/Lotus/Language/Weapons/DerelictCernosName" for these for some reason
 | 
				
			||||||
 | 
					                        ) {
 | 
				
			||||||
                            const weaponType = getWeaponsForManifest(inventory.Nemesis.manifest)[
 | 
					                            const weaponType = getWeaponsForManifest(inventory.Nemesis.manifest)[
 | 
				
			||||||
                                inventory.Nemesis.WeaponIdx
 | 
					                                inventory.Nemesis.WeaponIdx
 | 
				
			||||||
                            ];
 | 
					                            ];
 | 
				
			||||||
@ -657,6 +660,11 @@ export const addMissionInventoryUpdates = async (
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // TOVERIFY: Is the inbox message also sent when converting a lich? If not, how are the rewards given?
 | 
				
			||||||
 | 
					                    if (inventory.Nemesis.Faction == "FC_INFESTATION") {
 | 
				
			||||||
 | 
					                        await sendCodaFinishedMessage(inventory, inventory.Nemesis.fp, value.nemesisName, value.killed);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    inventory.Nemesis = undefined;
 | 
					                    inventory.Nemesis = undefined;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,10 @@ export const getRandomInt = (min: number, max: number): number => {
 | 
				
			|||||||
    return Math.floor(Math.random() * (max - min + 1)) + min;
 | 
					    return Math.floor(Math.random() * (max - min + 1)) + min;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getRewardAtPercentage = <T extends { probability: number }>(pool: T[], percentage: number): T | undefined => {
 | 
					export const getRewardAtPercentage = <T extends { probability: number }>(
 | 
				
			||||||
 | 
					    pool: T[],
 | 
				
			||||||
 | 
					    percentage: number
 | 
				
			||||||
 | 
					): T | undefined => {
 | 
				
			||||||
    if (pool.length == 0) return;
 | 
					    if (pool.length == 0) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const totalChance = pool.reduce((accum, item) => accum + item.probability, 0);
 | 
					    const totalChance = pool.reduce((accum, item) => accum + item.probability, 0);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
import { unixTimesInMs } from "@/src/constants/timeConstants";
 | 
					import { unixTimesInMs } from "@/src/constants/timeConstants";
 | 
				
			||||||
 | 
					import { catBreadHash } from "@/src/helpers/stringHelpers";
 | 
				
			||||||
import { CRng, mixSeeds } from "@/src/services/rngService";
 | 
					import { CRng, mixSeeds } from "@/src/services/rngService";
 | 
				
			||||||
import { IMongoDate } from "@/src/types/commonTypes";
 | 
					import { IMongoDate } from "@/src/types/commonTypes";
 | 
				
			||||||
import { IItemManifest, IVendorInfo, IVendorManifest } from "@/src/types/vendorTypes";
 | 
					import { IItemManifest, IVendorInfo, IVendorManifest } from "@/src/types/vendorTypes";
 | 
				
			||||||
@ -6,7 +7,6 @@ import { ExportVendors, IRange } 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";
 | 
				
			||||||
import DeimosFishmongerVendorManifest from "@/static/fixed_responses/getVendorInfo/DeimosFishmongerVendorManifest.json";
 | 
					 | 
				
			||||||
import DeimosHivemindCommisionsManifestFishmonger from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestFishmonger.json";
 | 
					import DeimosHivemindCommisionsManifestFishmonger from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestFishmonger.json";
 | 
				
			||||||
import DeimosHivemindCommisionsManifestPetVendor from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestPetVendor.json";
 | 
					import DeimosHivemindCommisionsManifestPetVendor from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestPetVendor.json";
 | 
				
			||||||
import DeimosHivemindCommisionsManifestProspector from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestProspector.json";
 | 
					import DeimosHivemindCommisionsManifestProspector from "@/static/fixed_responses/getVendorInfo/DeimosHivemindCommisionsManifestProspector.json";
 | 
				
			||||||
@ -22,12 +22,10 @@ import HubsIronwakeDondaVendorManifest from "@/static/fixed_responses/getVendorI
 | 
				
			|||||||
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 OstronFishmongerVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronFishmongerVendorManifest.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 OstronProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronProspectorVendorManifest.json";
 | 
				
			||||||
import RadioLegionIntermission12VendorManifest from "@/static/fixed_responses/getVendorInfo/RadioLegionIntermission12VendorManifest.json";
 | 
					import RadioLegionIntermission12VendorManifest from "@/static/fixed_responses/getVendorInfo/RadioLegionIntermission12VendorManifest.json";
 | 
				
			||||||
import SolarisDebtTokenVendorRepossessionsManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorRepossessionsManifest.json";
 | 
					import SolarisDebtTokenVendorRepossessionsManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorRepossessionsManifest.json";
 | 
				
			||||||
import SolarisFishmongerVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisFishmongerVendorManifest.json";
 | 
					 | 
				
			||||||
import SolarisProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/SolarisProspectorVendorManifest.json";
 | 
					import 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";
 | 
				
			||||||
@ -36,7 +34,6 @@ import ZarimanCommisionsManifestArchimedean from "@/static/fixed_responses/getVe
 | 
				
			|||||||
const rawVendorManifests: IVendorManifest[] = [
 | 
					const rawVendorManifests: IVendorManifest[] = [
 | 
				
			||||||
    ArchimedeanVendorManifest,
 | 
					    ArchimedeanVendorManifest,
 | 
				
			||||||
    DeimosEntratiFragmentVendorProductsManifest,
 | 
					    DeimosEntratiFragmentVendorProductsManifest,
 | 
				
			||||||
    DeimosFishmongerVendorManifest,
 | 
					 | 
				
			||||||
    DeimosHivemindCommisionsManifestFishmonger,
 | 
					    DeimosHivemindCommisionsManifestFishmonger,
 | 
				
			||||||
    DeimosHivemindCommisionsManifestPetVendor,
 | 
					    DeimosHivemindCommisionsManifestPetVendor,
 | 
				
			||||||
    DeimosHivemindCommisionsManifestProspector,
 | 
					    DeimosHivemindCommisionsManifestProspector,
 | 
				
			||||||
@ -52,12 +49,10 @@ const rawVendorManifests: IVendorManifest[] = [
 | 
				
			|||||||
    HubsRailjackCrewMemberVendorManifest,
 | 
					    HubsRailjackCrewMemberVendorManifest,
 | 
				
			||||||
    MaskSalesmanManifest,
 | 
					    MaskSalesmanManifest,
 | 
				
			||||||
    Nova1999ConquestShopManifest,
 | 
					    Nova1999ConquestShopManifest,
 | 
				
			||||||
    OstronFishmongerVendorManifest,
 | 
					 | 
				
			||||||
    OstronPetVendorManifest,
 | 
					    OstronPetVendorManifest,
 | 
				
			||||||
    OstronProspectorVendorManifest,
 | 
					    OstronProspectorVendorManifest,
 | 
				
			||||||
    RadioLegionIntermission12VendorManifest,
 | 
					    RadioLegionIntermission12VendorManifest,
 | 
				
			||||||
    SolarisDebtTokenVendorRepossessionsManifest,
 | 
					    SolarisDebtTokenVendorRepossessionsManifest,
 | 
				
			||||||
    SolarisFishmongerVendorManifest,
 | 
					 | 
				
			||||||
    SolarisProspectorVendorManifest,
 | 
					    SolarisProspectorVendorManifest,
 | 
				
			||||||
    Temple1999VendorManifest,
 | 
					    Temple1999VendorManifest,
 | 
				
			||||||
    TeshinHardModeVendorManifest, // uses preprocessing
 | 
					    TeshinHardModeVendorManifest, // uses preprocessing
 | 
				
			||||||
@ -87,17 +82,11 @@ const generatableVendors: IGeneratableVendorInfo[] = [
 | 
				
			|||||||
        cycleOffset: 1744934400_000,
 | 
					        cycleOffset: 1744934400_000,
 | 
				
			||||||
        cycleDuration: 4 * unixTimesInMs.day
 | 
					        cycleDuration: 4 * unixTimesInMs.day
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        _id: { $oid: "5be4a159b144f3cdf1c22efa" },
 | 
					 | 
				
			||||||
        TypeName: "/Lotus/Types/Game/VendorManifests/Solaris/DebtTokenVendorManifest",
 | 
					 | 
				
			||||||
        RandomSeedType: "VRST_FLAVOUR_TEXT",
 | 
					 | 
				
			||||||
        cycleDuration: unixTimesInMs.hour
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        _id: { $oid: "61ba123467e5d37975aeeb03" },
 | 
					        _id: { $oid: "61ba123467e5d37975aeeb03" },
 | 
				
			||||||
        TypeName: "/Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest",
 | 
					        TypeName: "/Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest",
 | 
				
			||||||
        RandomSeedType: "VRST_FLAVOUR_TEXT",
 | 
					        RandomSeedType: "VRST_FLAVOUR_TEXT",
 | 
				
			||||||
        cycleDuration: unixTimesInMs.week
 | 
					        cycleDuration: unixTimesInMs.week // TODO: Auto-detect this based on the items, so we don't need to specify it explicitly.
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // {
 | 
					    // {
 | 
				
			||||||
    //     _id: { $oid: "5dbb4c41e966f7886c3ce939" },
 | 
					    //     _id: { $oid: "5dbb4c41e966f7886c3ce939" },
 | 
				
			||||||
@ -105,6 +94,10 @@ const generatableVendors: IGeneratableVendorInfo[] = [
 | 
				
			|||||||
    // }
 | 
					    // }
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getVendorOid = (typeName: string): string => {
 | 
				
			||||||
 | 
					    return "5be4a159b144f3cd" + catBreadHash(typeName).toString(16).padStart(8, "0");
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getVendorManifestByTypeName = (typeName: string): IVendorManifest | undefined => {
 | 
					export const getVendorManifestByTypeName = (typeName: string): IVendorManifest | undefined => {
 | 
				
			||||||
    for (const vendorManifest of rawVendorManifests) {
 | 
					    for (const vendorManifest of rawVendorManifests) {
 | 
				
			||||||
        if (vendorManifest.VendorInfo.TypeName == typeName) {
 | 
					        if (vendorManifest.VendorInfo.TypeName == typeName) {
 | 
				
			||||||
@ -116,6 +109,14 @@ export const getVendorManifestByTypeName = (typeName: string): IVendorManifest |
 | 
				
			|||||||
            return generateVendorManifest(vendorInfo);
 | 
					            return generateVendorManifest(vendorInfo);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (typeName in ExportVendors) {
 | 
				
			||||||
 | 
					        return generateVendorManifest({
 | 
				
			||||||
 | 
					            _id: { $oid: getVendorOid(typeName) },
 | 
				
			||||||
 | 
					            TypeName: typeName,
 | 
				
			||||||
 | 
					            RandomSeedType: ExportVendors[typeName].randomSeedType,
 | 
				
			||||||
 | 
					            cycleDuration: unixTimesInMs.hour
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return undefined;
 | 
					    return undefined;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -130,6 +131,17 @@ export const getVendorManifestByOid = (oid: string): IVendorManifest | undefined
 | 
				
			|||||||
            return generateVendorManifest(vendorInfo);
 | 
					            return generateVendorManifest(vendorInfo);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    for (const [typeName, manifest] of Object.entries(ExportVendors)) {
 | 
				
			||||||
 | 
					        const typeNameOid = getVendorOid(typeName);
 | 
				
			||||||
 | 
					        if (typeNameOid == oid) {
 | 
				
			||||||
 | 
					            return generateVendorManifest({
 | 
				
			||||||
 | 
					                _id: { $oid: typeNameOid },
 | 
				
			||||||
 | 
					                TypeName: typeName,
 | 
				
			||||||
 | 
					                RandomSeedType: manifest.randomSeedType,
 | 
				
			||||||
 | 
					                cycleDuration: unixTimesInMs.hour
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return undefined;
 | 
					    return undefined;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -195,7 +207,7 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
 | 
				
			|||||||
        const rng = new CRng(mixSeeds(vendorSeed, cycleIndex));
 | 
					        const rng = new CRng(mixSeeds(vendorSeed, cycleIndex));
 | 
				
			||||||
        const manifest = ExportVendors[vendorInfo.TypeName];
 | 
					        const manifest = ExportVendors[vendorInfo.TypeName];
 | 
				
			||||||
        const offersToAdd = [];
 | 
					        const offersToAdd = [];
 | 
				
			||||||
        if (manifest.numItems && manifest.numItems.minValue != manifest.numItems.maxValue) {
 | 
					        if (manifest.numItems && !manifest.isOneBinPerCycle) {
 | 
				
			||||||
            const numItemsTarget = rng.randomInt(manifest.numItems.minValue, manifest.numItems.maxValue);
 | 
					            const numItemsTarget = rng.randomInt(manifest.numItems.minValue, manifest.numItems.maxValue);
 | 
				
			||||||
            while (processed.ItemManifest.length + offersToAdd.length < numItemsTarget) {
 | 
					            while (processed.ItemManifest.length + offersToAdd.length < numItemsTarget) {
 | 
				
			||||||
                // TODO: Consider per-bin item limits
 | 
					                // TODO: Consider per-bin item limits
 | 
				
			||||||
@ -263,6 +275,13 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
 | 
				
			|||||||
                          ) * rawItem.credits.step;
 | 
					                          ) * rawItem.credits.step;
 | 
				
			||||||
                item.RegularPrice = [value, value];
 | 
					                item.RegularPrice = [value, value];
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            if (rawItem.platinum) {
 | 
				
			||||||
 | 
					                const value =
 | 
				
			||||||
 | 
					                    typeof rawItem.platinum == "number"
 | 
				
			||||||
 | 
					                        ? rawItem.platinum
 | 
				
			||||||
 | 
					                        : rng.randomInt(rawItem.platinum.minValue, rawItem.platinum.maxValue);
 | 
				
			||||||
 | 
					                item.PremiumPrice = [value, value];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            if (vendorInfo.RandomSeedType) {
 | 
					            if (vendorInfo.RandomSeedType) {
 | 
				
			||||||
                item.LocTagRandSeed = (rng.randomInt(0, 0xffff) << 16) | rng.randomInt(0, 0xffff);
 | 
					                item.LocTagRandSeed = (rng.randomInt(0, 0xffff) << 16) | rng.randomInt(0, 0xffff);
 | 
				
			||||||
                if (vendorInfo.RandomSeedType == "VRST_WEAPON") {
 | 
					                if (vendorInfo.RandomSeedType == "VRST_WEAPON") {
 | 
				
			||||||
 | 
				
			|||||||
@ -52,6 +52,7 @@ export interface IInventoryDatabase
 | 
				
			|||||||
            | "LastLiteSortieReward"
 | 
					            | "LastLiteSortieReward"
 | 
				
			||||||
            | "CrewMembers"
 | 
					            | "CrewMembers"
 | 
				
			||||||
            | "QualifyingInvasions"
 | 
					            | "QualifyingInvasions"
 | 
				
			||||||
 | 
					            | "LastInventorySync"
 | 
				
			||||||
            | TEquipmentKey
 | 
					            | TEquipmentKey
 | 
				
			||||||
        >,
 | 
					        >,
 | 
				
			||||||
        InventoryDatabaseEquipment {
 | 
					        InventoryDatabaseEquipment {
 | 
				
			||||||
@ -89,6 +90,7 @@ export interface IInventoryDatabase
 | 
				
			|||||||
    LastLiteSortieReward?: ILastSortieRewardDatabase[];
 | 
					    LastLiteSortieReward?: ILastSortieRewardDatabase[];
 | 
				
			||||||
    CrewMembers: ICrewMemberDatabase[];
 | 
					    CrewMembers: ICrewMemberDatabase[];
 | 
				
			||||||
    QualifyingInvasions: IInvasionProgressDatabase[];
 | 
					    QualifyingInvasions: IInvasionProgressDatabase[];
 | 
				
			||||||
 | 
					    LastInventorySync?: Types.ObjectId;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IQuestKeyDatabase {
 | 
					export interface IQuestKeyDatabase {
 | 
				
			||||||
@ -258,7 +260,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
 | 
				
			|||||||
    EquippedGear: string[];
 | 
					    EquippedGear: string[];
 | 
				
			||||||
    DeathMarks: string[];
 | 
					    DeathMarks: string[];
 | 
				
			||||||
    FusionTreasures: IFusionTreasure[];
 | 
					    FusionTreasures: IFusionTreasure[];
 | 
				
			||||||
    WebFlags: IWebFlags;
 | 
					    //WebFlags: IWebFlags;
 | 
				
			||||||
    CompletedAlerts: string[];
 | 
					    CompletedAlerts: string[];
 | 
				
			||||||
    Consumables: ITypeCount[];
 | 
					    Consumables: ITypeCount[];
 | 
				
			||||||
    LevelKeys: ITypeCount[];
 | 
					    LevelKeys: ITypeCount[];
 | 
				
			||||||
@ -268,10 +270,10 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
 | 
				
			|||||||
    KubrowPetEggs?: IKubrowPetEggClient[];
 | 
					    KubrowPetEggs?: IKubrowPetEggClient[];
 | 
				
			||||||
    LoreFragmentScans: ILoreFragmentScan[];
 | 
					    LoreFragmentScans: ILoreFragmentScan[];
 | 
				
			||||||
    EquippedEmotes: string[];
 | 
					    EquippedEmotes: string[];
 | 
				
			||||||
    PendingTrades: IPendingTrade[];
 | 
					    //PendingTrades: IPendingTrade[];
 | 
				
			||||||
    Boosters: IBooster[];
 | 
					    Boosters: IBooster[];
 | 
				
			||||||
    ActiveDojoColorResearch: string;
 | 
					    ActiveDojoColorResearch: string;
 | 
				
			||||||
    SentientSpawnChanceBoosters: ISentientSpawnChanceBoosters;
 | 
					    //SentientSpawnChanceBoosters: ISentientSpawnChanceBoosters;
 | 
				
			||||||
    SupportedSyndicate?: string;
 | 
					    SupportedSyndicate?: string;
 | 
				
			||||||
    Affiliations: IAffiliation[];
 | 
					    Affiliations: IAffiliation[];
 | 
				
			||||||
    QualifyingInvasions: IInvasionProgressClient[];
 | 
					    QualifyingInvasions: IInvasionProgressClient[];
 | 
				
			||||||
@ -293,19 +295,19 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
 | 
				
			|||||||
    ActiveAvatarImageType: string;
 | 
					    ActiveAvatarImageType: string;
 | 
				
			||||||
    ShipDecorations: ITypeCount[];
 | 
					    ShipDecorations: ITypeCount[];
 | 
				
			||||||
    DiscoveredMarkers: IDiscoveredMarker[];
 | 
					    DiscoveredMarkers: IDiscoveredMarker[];
 | 
				
			||||||
    CompletedJobs: ICompletedJob[];
 | 
					    //CompletedJobs: ICompletedJob[];
 | 
				
			||||||
    FocusAbility?: string;
 | 
					    FocusAbility?: string;
 | 
				
			||||||
    FocusUpgrades: IFocusUpgrade[];
 | 
					    FocusUpgrades: IFocusUpgrade[];
 | 
				
			||||||
    HasContributedToDojo?: boolean;
 | 
					    HasContributedToDojo?: boolean;
 | 
				
			||||||
    HWIDProtectEnabled?: boolean;
 | 
					    HWIDProtectEnabled?: boolean;
 | 
				
			||||||
    KubrowPetPrints: IKubrowPetPrint[];
 | 
					    //KubrowPetPrints: IKubrowPetPrint[];
 | 
				
			||||||
    AlignmentReplay?: IAlignment;
 | 
					    AlignmentReplay?: IAlignment;
 | 
				
			||||||
    PersonalGoalProgress: IPersonalGoalProgress[];
 | 
					    //PersonalGoalProgress: IPersonalGoalProgress[];
 | 
				
			||||||
    ThemeStyle: string;
 | 
					    ThemeStyle: string;
 | 
				
			||||||
    ThemeBackground: string;
 | 
					    ThemeBackground: string;
 | 
				
			||||||
    ThemeSounds: string;
 | 
					    ThemeSounds: string;
 | 
				
			||||||
    BountyScore: number;
 | 
					    BountyScore: number;
 | 
				
			||||||
    ChallengeInstanceStates: IChallengeInstanceState[];
 | 
					    //ChallengeInstanceStates: IChallengeInstanceState[];
 | 
				
			||||||
    LoginMilestoneRewards: string[];
 | 
					    LoginMilestoneRewards: string[];
 | 
				
			||||||
    RecentVendorPurchases?: IRecentVendorPurchaseClient[];
 | 
					    RecentVendorPurchases?: IRecentVendorPurchaseClient[];
 | 
				
			||||||
    NodeIntrosCompleted: string[];
 | 
					    NodeIntrosCompleted: string[];
 | 
				
			||||||
@ -313,17 +315,17 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
 | 
				
			|||||||
    CompletedJobChains?: ICompletedJobChain[];
 | 
					    CompletedJobChains?: ICompletedJobChain[];
 | 
				
			||||||
    SeasonChallengeHistory: ISeasonChallenge[];
 | 
					    SeasonChallengeHistory: ISeasonChallenge[];
 | 
				
			||||||
    EquippedInstrument?: string;
 | 
					    EquippedInstrument?: string;
 | 
				
			||||||
    InvasionChainProgress: IInvasionChainProgress[];
 | 
					    //InvasionChainProgress: IInvasionChainProgress[];
 | 
				
			||||||
    Nemesis?: INemesisClient;
 | 
					    Nemesis?: INemesisClient;
 | 
				
			||||||
    NemesisHistory?: INemesisBaseClient[];
 | 
					    NemesisHistory?: INemesisBaseClient[];
 | 
				
			||||||
    LastNemesisAllySpawnTime?: IMongoDate;
 | 
					    //LastNemesisAllySpawnTime?: IMongoDate;
 | 
				
			||||||
    Settings?: ISettings;
 | 
					    Settings?: ISettings;
 | 
				
			||||||
    PersonalTechProjects: IPersonalTechProjectClient[];
 | 
					    PersonalTechProjects: IPersonalTechProjectClient[];
 | 
				
			||||||
    PlayerSkills: IPlayerSkills;
 | 
					    PlayerSkills: IPlayerSkills;
 | 
				
			||||||
    CrewShipAmmo: ITypeCount[];
 | 
					    CrewShipAmmo: ITypeCount[];
 | 
				
			||||||
    CrewShipWeaponSkins: IUpgradeClient[];
 | 
					    CrewShipWeaponSkins: IUpgradeClient[];
 | 
				
			||||||
    CrewShipSalvagedWeaponSkins: IUpgradeClient[];
 | 
					    CrewShipSalvagedWeaponSkins: IUpgradeClient[];
 | 
				
			||||||
    TradeBannedUntil?: IMongoDate;
 | 
					    //TradeBannedUntil?: IMongoDate;
 | 
				
			||||||
    PlayedParkourTutorial: boolean;
 | 
					    PlayedParkourTutorial: boolean;
 | 
				
			||||||
    SubscribedToEmailsPersonalized: number;
 | 
					    SubscribedToEmailsPersonalized: number;
 | 
				
			||||||
    InfestedFoundry?: IInfestedFoundryClient;
 | 
					    InfestedFoundry?: IInfestedFoundryClient;
 | 
				
			||||||
@ -333,17 +335,17 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
 | 
				
			|||||||
    LotusCustomization?: ILotusCustomization;
 | 
					    LotusCustomization?: ILotusCustomization;
 | 
				
			||||||
    UseAdultOperatorLoadout?: boolean;
 | 
					    UseAdultOperatorLoadout?: boolean;
 | 
				
			||||||
    NemesisAbandonedRewards: string[];
 | 
					    NemesisAbandonedRewards: string[];
 | 
				
			||||||
    LastInventorySync: IOid;
 | 
					    LastInventorySync?: IOid;
 | 
				
			||||||
    NextRefill?: IMongoDate;
 | 
					    NextRefill?: IMongoDate;
 | 
				
			||||||
    FoundToday?: IMiscItem[]; // for Argon Crystals
 | 
					    FoundToday?: IMiscItem[]; // for Argon Crystals
 | 
				
			||||||
    CustomMarkers?: ICustomMarkers[];
 | 
					    CustomMarkers?: ICustomMarkers[];
 | 
				
			||||||
    ActiveLandscapeTraps: any[];
 | 
					    //ActiveLandscapeTraps: any[];
 | 
				
			||||||
    EvolutionProgress?: IEvolutionProgress[];
 | 
					    EvolutionProgress?: IEvolutionProgress[];
 | 
				
			||||||
    RepVotes: any[];
 | 
					    //RepVotes: any[];
 | 
				
			||||||
    LeagueTickets: any[];
 | 
					    //LeagueTickets: any[];
 | 
				
			||||||
    Quests: any[];
 | 
					    //Quests: any[];
 | 
				
			||||||
    Robotics: any[];
 | 
					    //Robotics: any[];
 | 
				
			||||||
    UsedDailyDeals: any[];
 | 
					    //UsedDailyDeals: any[];
 | 
				
			||||||
    LibraryPersonalTarget?: string;
 | 
					    LibraryPersonalTarget?: string;
 | 
				
			||||||
    LibraryPersonalProgress: ILibraryPersonalProgress[];
 | 
					    LibraryPersonalProgress: ILibraryPersonalProgress[];
 | 
				
			||||||
    CollectibleSeries?: ICollectibleEntry[];
 | 
					    CollectibleSeries?: ICollectibleEntry[];
 | 
				
			||||||
 | 
				
			|||||||
@ -1,106 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "VendorInfo": {
 | 
					 | 
				
			||||||
    "_id": {
 | 
					 | 
				
			||||||
      "$oid": "5f456e01c96976e97d6b8016"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "TypeName": "/Lotus/Types/Game/VendorManifests/Deimos/FishmongerVendorManifest",
 | 
					 | 
				
			||||||
    "ItemManifest": [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Deimos/FishParts/DeimosOrokinFishAPartItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [9, 9],
 | 
					 | 
				
			||||||
        "Bin": "BIN_1",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 10,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e91b9"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Deimos/FishParts/DeimosInfestedFishDPartItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [17, 17],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e91ba"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Deimos/FishParts/DeimosInfestedFishCPartItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [10, 10],
 | 
					 | 
				
			||||||
        "Bin": "BIN_1",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e91bb"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Deimos/FishParts/DeimosInfestedFishBPartItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [6, 6],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e91bc"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Deimos/FishParts/DeimosInfestedFishAPartItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [5, 5],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e91bd"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Deimos/FishParts/DeimosGenericSharedFishPartItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [7, 7],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e91be"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    "PropertyTextHash": "6DF13A7FB573C25B4B4F989CBEFFC615",
 | 
					 | 
				
			||||||
    "Expiry": {
 | 
					 | 
				
			||||||
      "$date": {
 | 
					 | 
				
			||||||
        "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,106 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "VendorInfo": {
 | 
					 | 
				
			||||||
    "_id": {
 | 
					 | 
				
			||||||
      "$oid": "59d6e27ebcc718474eb17115"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "TypeName": "/Lotus/Types/Game/VendorManifests/Ostron/FishmongerVendorManifest",
 | 
					 | 
				
			||||||
    "ItemManifest": [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Eidolon/FishParts/DayUncommonFishAPartItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [14, 14],
 | 
					 | 
				
			||||||
        "Bin": "BIN_1",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 10,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e9808"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishBPartItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [12, 12],
 | 
					 | 
				
			||||||
        "Bin": "BIN_1",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 10,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e9809"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Eidolon/FishParts/DayCommonFishCPartItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [8, 8],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e980a"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Eidolon/FishParts/DayCommonFishBPartItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [7, 7],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e980b"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Eidolon/FishParts/DayCommonFishAPartItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [10, 10],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e980c"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Eidolon/FishParts/BothCommonFishBPartItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [8, 8],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e980d"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    "PropertyTextHash": "CC3B9DAFB38F412998E90A41421A8986",
 | 
					 | 
				
			||||||
    "Expiry": {
 | 
					 | 
				
			||||||
      "$date": {
 | 
					 | 
				
			||||||
        "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,106 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "VendorInfo": {
 | 
					 | 
				
			||||||
    "_id": {
 | 
					 | 
				
			||||||
      "$oid": "5b0de8556df82a56ea9bae82"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "TypeName": "/Lotus/Types/Game/VendorManifests/Solaris/FishmongerVendorManifest",
 | 
					 | 
				
			||||||
    "ItemManifest": [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Solaris/FishParts/CorpusFishThermalLaserItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [15, 15],
 | 
					 | 
				
			||||||
        "Bin": "BIN_1",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 10,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e9515"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Solaris/FishParts/CorpusFishVenedoCaseItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [8, 8],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e9516"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Solaris/FishParts/SolarisFishDissipatorCoilItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [18, 18],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e9517"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Solaris/FishParts/CorpusFishExaBrainItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [5, 5],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e9518"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Solaris/FishParts/CorpusFishAnoscopicSensorItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [5, 5],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e9519"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Fish/Solaris/FishParts/GenericFishScrapItem",
 | 
					 | 
				
			||||||
        "PremiumPrice": [5, 5],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 20,
 | 
					 | 
				
			||||||
        "Expiry": {
 | 
					 | 
				
			||||||
          "$date": {
 | 
					 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					 | 
				
			||||||
        "Id": {
 | 
					 | 
				
			||||||
          "$oid": "66fd60b20ba592c4c95e951a"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    "PropertyTextHash": "946131D0CF5CDF7C2C03BB967DE0DF49",
 | 
					 | 
				
			||||||
    "Expiry": {
 | 
					 | 
				
			||||||
      "$date": {
 | 
					 | 
				
			||||||
        "$numberLong": "9999999000000"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -34,8 +34,8 @@ dict = {
 | 
				
			|||||||
    code_rerollsNumber: `Anzahl der Umrollversuche`,
 | 
					    code_rerollsNumber: `Anzahl der Umrollversuche`,
 | 
				
			||||||
    code_viewStats: `Statistiken anzeigen`,
 | 
					    code_viewStats: `Statistiken anzeigen`,
 | 
				
			||||||
    code_rank: `Rang`,
 | 
					    code_rank: `Rang`,
 | 
				
			||||||
    code_rankUp: `[UNTRANSLATED] Rank up`,
 | 
					    code_rankUp: `Rang erhöhen`,
 | 
				
			||||||
    code_rankDown: `[UNTRANSLATED] Rank down`,
 | 
					    code_rankDown: `Rang verringern`,
 | 
				
			||||||
    code_count: `Anzahl`,
 | 
					    code_count: `Anzahl`,
 | 
				
			||||||
    code_focusAllUnlocked: `Alle Fokus-Schulen sind bereits freigeschaltet.`,
 | 
					    code_focusAllUnlocked: `Alle Fokus-Schulen sind bereits freigeschaltet.`,
 | 
				
			||||||
    code_focusUnlocked: `|COUNT| neue Fokus-Schulen freigeschaltet! Ein Inventar-Update wird benötigt, damit die Änderungen im Spiel sichtbar werden. Die Sternenkarte zu besuchen, sollte der einfachste Weg sein, dies auszulösen.`,
 | 
					    code_focusUnlocked: `|COUNT| neue Fokus-Schulen freigeschaltet! Ein Inventar-Update wird benötigt, damit die Änderungen im Spiel sichtbar werden. Die Sternenkarte zu besuchen, sollte der einfachste Weg sein, dies auszulösen.`,
 | 
				
			||||||
@ -86,21 +86,21 @@ dict = {
 | 
				
			|||||||
    inventory_hoverboards: `K-Drives`,
 | 
					    inventory_hoverboards: `K-Drives`,
 | 
				
			||||||
    inventory_moaPets: `Moas`,
 | 
					    inventory_moaPets: `Moas`,
 | 
				
			||||||
    inventory_kubrowPets: `Bestien`,
 | 
					    inventory_kubrowPets: `Bestien`,
 | 
				
			||||||
    inventory_evolutionProgress: `[UNTRANSLATED] Incarnon Evolution Progress`,
 | 
					    inventory_evolutionProgress: `Incarnon-Entwicklungsfortschritte`,
 | 
				
			||||||
    inventory_bulkAddSuits: `Fehlende Warframes hinzufügen`,
 | 
					    inventory_bulkAddSuits: `Fehlende Warframes hinzufügen`,
 | 
				
			||||||
    inventory_bulkAddWeapons: `Fehlende Waffen hinzufügen`,
 | 
					    inventory_bulkAddWeapons: `Fehlende Waffen hinzufügen`,
 | 
				
			||||||
    inventory_bulkAddSpaceSuits: `Fehlende Archwings hinzufügen`,
 | 
					    inventory_bulkAddSpaceSuits: `Fehlende Archwings hinzufügen`,
 | 
				
			||||||
    inventory_bulkAddSpaceWeapons: `Fehlende Archwing-Waffen hinzufügen`,
 | 
					    inventory_bulkAddSpaceWeapons: `Fehlende Archwing-Waffen hinzufügen`,
 | 
				
			||||||
    inventory_bulkAddSentinels: `Fehlende Wächter hinzufügen`,
 | 
					    inventory_bulkAddSentinels: `Fehlende Wächter hinzufügen`,
 | 
				
			||||||
    inventory_bulkAddSentinelWeapons: `Fehlende Wächter-Waffen hinzufügen`,
 | 
					    inventory_bulkAddSentinelWeapons: `Fehlende Wächter-Waffen hinzufügen`,
 | 
				
			||||||
    inventory_bulkAddEvolutionProgress: `[UNTRANSLATED] Add Missing Incarnon Evolution Progress`,
 | 
					    inventory_bulkAddEvolutionProgress: `Fehlende Incarnon-Entwicklungsfortschritte hinzufügen`,
 | 
				
			||||||
    inventory_bulkRankUpSuits: `Alle Warframes auf Max. Rang`,
 | 
					    inventory_bulkRankUpSuits: `Alle Warframes auf Max. Rang`,
 | 
				
			||||||
    inventory_bulkRankUpWeapons: `Alle Waffen auf Max. Rang`,
 | 
					    inventory_bulkRankUpWeapons: `Alle Waffen auf Max. Rang`,
 | 
				
			||||||
    inventory_bulkRankUpSpaceSuits: `Alle Archwings auf Max. Rang`,
 | 
					    inventory_bulkRankUpSpaceSuits: `Alle Archwings auf Max. Rang`,
 | 
				
			||||||
    inventory_bulkRankUpSpaceWeapons: `Alle Archwing-Waffen auf Max. Rang`,
 | 
					    inventory_bulkRankUpSpaceWeapons: `Alle Archwing-Waffen auf Max. Rang`,
 | 
				
			||||||
    inventory_bulkRankUpSentinels: `Alle Wächter auf Max. Rang`,
 | 
					    inventory_bulkRankUpSentinels: `Alle Wächter auf Max. Rang`,
 | 
				
			||||||
    inventory_bulkRankUpSentinelWeapons: `Alle Wächter-Waffen auf Max. Rang`,
 | 
					    inventory_bulkRankUpSentinelWeapons: `Alle Wächter-Waffen auf Max. Rang`,
 | 
				
			||||||
    inventory_bulkRankUpEvolutionProgress: `[UNTRANSLATED] Max Rank All Incarnon Evolution Progress`,
 | 
					    inventory_bulkRankUpEvolutionProgress: `Alle Incarnon-Entwicklungsfortschritte auf Max. Rang`,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    quests_list: `Quests`,
 | 
					    quests_list: `Quests`,
 | 
				
			||||||
    quests_completeAll: `Alle Quests abschließen`,
 | 
					    quests_completeAll: `Alle Quests abschließen`,
 | 
				
			||||||
@ -120,9 +120,9 @@ dict = {
 | 
				
			|||||||
    mods_fingerprintHelp: `Benötigst du Hilfe mit dem Fingerabdruck?`,
 | 
					    mods_fingerprintHelp: `Benötigst du Hilfe mit dem Fingerabdruck?`,
 | 
				
			||||||
    mods_rivens: `Rivens`,
 | 
					    mods_rivens: `Rivens`,
 | 
				
			||||||
    mods_mods: `Mods`,
 | 
					    mods_mods: `Mods`,
 | 
				
			||||||
    mods_addMissingUnrankedMods: `[UNTRANSLATED] Add Missing Unranked Mods`,
 | 
					    mods_addMissingUnrankedMods: `Fehlende Mods ohne Rang hinzufügen`,
 | 
				
			||||||
    mods_removeUnranked: `Mods ohne Rang entfernen`,
 | 
					    mods_removeUnranked: `Mods ohne Rang entfernen`,
 | 
				
			||||||
    mods_addMissingMaxRankMods: `[UNTRANSLATED] Add Missing Max Rank Mods`,
 | 
					    mods_addMissingMaxRankMods: `Fehlende Mods mit Max. Rang hinzufügen`,
 | 
				
			||||||
    cheats_administratorRequirement: `Du musst Administrator sein, um diese Funktion nutzen zu können. Um Administrator zu werden, füge <code>|DISPLAYNAME|</code> zu <code>administratorNames</code> in der config.json hinzu.`,
 | 
					    cheats_administratorRequirement: `Du musst Administrator sein, um diese Funktion nutzen zu können. Um Administrator zu werden, füge <code>|DISPLAYNAME|</code> zu <code>administratorNames</code> in der config.json hinzu.`,
 | 
				
			||||||
    cheats_server: `Server`,
 | 
					    cheats_server: `Server`,
 | 
				
			||||||
    cheats_skipTutorial: `Tutorial überspringen`,
 | 
					    cheats_skipTutorial: `Tutorial überspringen`,
 | 
				
			||||||
@ -134,7 +134,7 @@ dict = {
 | 
				
			|||||||
    cheats_infiniteEndo: `Unendlich Endo`,
 | 
					    cheats_infiniteEndo: `Unendlich Endo`,
 | 
				
			||||||
    cheats_infiniteRegalAya: `Unendlich Reines Aya`,
 | 
					    cheats_infiniteRegalAya: `Unendlich Reines Aya`,
 | 
				
			||||||
    cheats_infiniteHelminthMaterials: `Unendlich Helminth-Materialien`,
 | 
					    cheats_infiniteHelminthMaterials: `Unendlich Helminth-Materialien`,
 | 
				
			||||||
    cheats_dontSubtractConsumables: `[UNTRANSLATED] Don't Subtract Consumables`,
 | 
					    cheats_dontSubtractConsumables: `Verbrauchsgegenstände (Ausrüstung) nicht verbrauchen`,
 | 
				
			||||||
    cheats_unlockAllShipFeatures: `Alle Schiffs-Funktionen freischalten`,
 | 
					    cheats_unlockAllShipFeatures: `Alle Schiffs-Funktionen freischalten`,
 | 
				
			||||||
    cheats_unlockAllShipDecorations: `Alle Schiffsdekorationen freischalten`,
 | 
					    cheats_unlockAllShipDecorations: `Alle Schiffsdekorationen freischalten`,
 | 
				
			||||||
    cheats_unlockAllFlavourItems: `Alle <abbr title=\"Animationssets, Glyphen, Farbpaletten usw.\">Sammlerstücke</abbr> freischalten`,
 | 
					    cheats_unlockAllFlavourItems: `Alle <abbr title=\"Animationssets, Glyphen, Farbpaletten usw.\">Sammlerstücke</abbr> freischalten`,
 | 
				
			||||||
@ -154,7 +154,7 @@ dict = {
 | 
				
			|||||||
    cheats_noKimCooldowns: `Keine Wartezeit bei KIM`,
 | 
					    cheats_noKimCooldowns: `Keine Wartezeit bei KIM`,
 | 
				
			||||||
    cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`,
 | 
					    cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`,
 | 
				
			||||||
    cheats_noResourceExtractorDronesDamage: `Kein Schaden für Ressourcen-Extraktor-Drohnen`,
 | 
					    cheats_noResourceExtractorDronesDamage: `Kein Schaden für Ressourcen-Extraktor-Drohnen`,
 | 
				
			||||||
    cheats_skipClanKeyCrafting: `[UNTRANSLATED] Skip Clan Key Crafting`,
 | 
					    cheats_skipClanKeyCrafting: `Clan-Schlüsselherstellung überspringen`,
 | 
				
			||||||
    cheats_noDojoRoomBuildStage: `Kein Dojo-Raum-Bauvorgang`,
 | 
					    cheats_noDojoRoomBuildStage: `Kein Dojo-Raum-Bauvorgang`,
 | 
				
			||||||
    cheats_noDojoDecoBuildStage: `Kein Dojo-Deko-Bauvorgang`,
 | 
					    cheats_noDojoDecoBuildStage: `Kein Dojo-Deko-Bauvorgang`,
 | 
				
			||||||
    cheats_fastDojoRoomDestruction: `Schnelle Dojo-Raum-Zerstörung`,
 | 
					    cheats_fastDojoRoomDestruction: `Schnelle Dojo-Raum-Zerstörung`,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user