chore: update docker stuff #1961
@ -1,5 +1,5 @@
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
			
		||||
import { getAccountForRequest } from "@/src/services/loginService";
 | 
			
		||||
import { Inventory, TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
 | 
			
		||||
import { config } from "@/src/services/configService";
 | 
			
		||||
import allDialogue from "@/static/fixed_responses/allDialogue.json";
 | 
			
		||||
@ -24,11 +24,12 @@ import {
 | 
			
		||||
import { logger } from "@/src/utils/logger";
 | 
			
		||||
import { catBreadHash } from "@/src/helpers/stringHelpers";
 | 
			
		||||
import { Types } from "mongoose";
 | 
			
		||||
import { isNemesisCompatibleWithVersion } from "@/src/helpers/nemesisHelpers";
 | 
			
		||||
 | 
			
		||||
export const inventoryController: RequestHandler = async (request, response) => {
 | 
			
		||||
    const accountId = await getAccountIdForRequest(request);
 | 
			
		||||
    const account = await getAccountForRequest(request);
 | 
			
		||||
 | 
			
		||||
    const inventory = await Inventory.findOne({ accountOwnerId: accountId });
 | 
			
		||||
    const inventory = await Inventory.findOne({ accountOwnerId: account._id });
 | 
			
		||||
 | 
			
		||||
    if (!inventory) {
 | 
			
		||||
        response.status(400).json({ error: "inventory was undefined" });
 | 
			
		||||
@ -119,12 +120,15 @@ export const inventoryController: RequestHandler = async (request, response) =>
 | 
			
		||||
    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, account.BuildLabel)
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const getInventoryResponse = async (
 | 
			
		||||
    inventory: TInventoryDatabaseDocument,
 | 
			
		||||
    xpBasedLevelCapDisabled: boolean
 | 
			
		||||
    xpBasedLevelCapDisabled: boolean,
 | 
			
		||||
    buildLabel: string | undefined
 | 
			
		||||
): Promise<IInventoryClient> => {
 | 
			
		||||
    const inventoryWithLoadOutPresets = await inventory.populate<{ LoadOutPresets: ILoadoutDatabase }>(
 | 
			
		||||
        "LoadOutPresets"
 | 
			
		||||
@ -299,6 +303,15 @@ export const getInventoryResponse = async (
 | 
			
		||||
    // Set 2FA enabled so trading post can be used
 | 
			
		||||
    inventoryResponse.HWIDProtectEnabled = true;
 | 
			
		||||
 | 
			
		||||
    // Fix nemesis for older versions
 | 
			
		||||
    if (
 | 
			
		||||
        inventoryResponse.Nemesis &&
 | 
			
		||||
        buildLabel &&
 | 
			
		||||
        !isNemesisCompatibleWithVersion(inventoryResponse.Nemesis, buildLabel)
 | 
			
		||||
    ) {
 | 
			
		||||
        inventoryResponse.Nemesis = undefined;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return inventoryResponse;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -47,7 +47,8 @@ export const loginController: RequestHandler = async (request, response) => {
 | 
			
		||||
                ForceLogoutVersion: 0,
 | 
			
		||||
                ConsentNeeded: false,
 | 
			
		||||
                TrackedSettings: [],
 | 
			
		||||
                Nonce: nonce
 | 
			
		||||
                Nonce: nonce,
 | 
			
		||||
                BuildLabel: buildLabel
 | 
			
		||||
            });
 | 
			
		||||
            logger.debug("created new account");
 | 
			
		||||
            response.json(createLoginResponse(myAddress, newAccount, buildLabel));
 | 
			
		||||
@ -88,6 +89,7 @@ export const loginController: RequestHandler = async (request, response) => {
 | 
			
		||||
        account.ClientType = loginRequest.ClientType;
 | 
			
		||||
        account.Nonce = nonce;
 | 
			
		||||
        account.CountryCode = loginRequest.lang.toUpperCase();
 | 
			
		||||
        account.BuildLabel = buildLabel;
 | 
			
		||||
    }
 | 
			
		||||
    await account.save();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
			
		||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
			
		||||
import { getAccountForRequest } from "@/src/services/loginService";
 | 
			
		||||
import { IMissionInventoryUpdateRequest } from "@/src/types/requestTypes";
 | 
			
		||||
import { addMissionInventoryUpdates, addMissionRewards } from "@/src/services/missionInventoryUpdateService";
 | 
			
		||||
import { generateRewardSeed, getInventory } from "@/src/services/inventoryService";
 | 
			
		||||
@ -49,11 +49,11 @@ import { IMissionInventoryUpdateResponse } from "@/src/types/missionTypes";
 | 
			
		||||
*/
 | 
			
		||||
//move credit calc in here, return MissionRewards: [] if no reward info
 | 
			
		||||
export const missionInventoryUpdateController: RequestHandler = async (req, res): Promise<void> => {
 | 
			
		||||
    const accountId = await getAccountIdForRequest(req);
 | 
			
		||||
    const account = await getAccountForRequest(req);
 | 
			
		||||
    const missionReport = getJSONfromString<IMissionInventoryUpdateRequest>((req.body as string).toString());
 | 
			
		||||
    logger.debug("mission report:", missionReport);
 | 
			
		||||
 | 
			
		||||
    const inventory = await getInventory(accountId);
 | 
			
		||||
    const inventory = await getInventory(account._id.toString());
 | 
			
		||||
    const firstCompletion = missionReport.SortieId
 | 
			
		||||
        ? inventory.CompletedSorties.indexOf(missionReport.SortieId) == -1
 | 
			
		||||
        : false;
 | 
			
		||||
@ -65,7 +65,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
 | 
			
		||||
    ) {
 | 
			
		||||
        inventory.RewardSeed = generateRewardSeed();
 | 
			
		||||
        await inventory.save();
 | 
			
		||||
        const inventoryResponse = await getInventoryResponse(inventory, true);
 | 
			
		||||
        const inventoryResponse = await getInventoryResponse(inventory, true, account.BuildLabel);
 | 
			
		||||
        res.json({
 | 
			
		||||
            InventoryJson: JSON.stringify(inventoryResponse),
 | 
			
		||||
            MissionRewards: []
 | 
			
		||||
@ -84,7 +84,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
 | 
			
		||||
 | 
			
		||||
    inventory.RewardSeed = generateRewardSeed();
 | 
			
		||||
    await inventory.save();
 | 
			
		||||
    const inventoryResponse = await getInventoryResponse(inventory, true);
 | 
			
		||||
    const inventoryResponse = await getInventoryResponse(inventory, true, account.BuildLabel);
 | 
			
		||||
 | 
			
		||||
    //TODO: figure out when to send inventory. it is needed for many cases.
 | 
			
		||||
    res.json({
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@ export const addItemsController: RequestHandler = async (req, res) => {
 | 
			
		||||
    const requests = req.body as IAddItemRequest[];
 | 
			
		||||
    const inventory = await getInventory(accountId);
 | 
			
		||||
    for (const request of requests) {
 | 
			
		||||
        await addItem(inventory, request.ItemType, request.ItemCount, true);
 | 
			
		||||
        await addItem(inventory, request.ItemType, request.ItemCount, true, undefined, undefined, true);
 | 
			
		||||
    }
 | 
			
		||||
    await inventory.save();
 | 
			
		||||
    res.end();
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@ import { logger } from "../utils/logger";
 | 
			
		||||
import { IOid } from "../types/commonTypes";
 | 
			
		||||
import { Types } from "mongoose";
 | 
			
		||||
import { addMods, generateRewardSeed } from "../services/inventoryService";
 | 
			
		||||
import { isArchwingMission } from "../services/worldStateService";
 | 
			
		||||
import { isArchwingMission, version_compare } from "../services/worldStateService";
 | 
			
		||||
import { fromStoreItem, toStoreItem } from "../services/itemDataService";
 | 
			
		||||
import { createMessage } from "../services/inboxService";
 | 
			
		||||
 | 
			
		||||
@ -237,15 +237,39 @@ const corpusVersionThreeWeapons = [
 | 
			
		||||
 | 
			
		||||
export const getWeaponsForManifest = (manifest: string): readonly string[] => {
 | 
			
		||||
    switch (manifest) {
 | 
			
		||||
        case "/Lotus/Types/Game/Nemesis/KuvaLich/KuvaLichManifestVersionSix":
 | 
			
		||||
        case "/Lotus/Types/Game/Nemesis/KuvaLich/KuvaLichManifestVersionSix": // >= 35.6.0
 | 
			
		||||
            return kuvaLichVersionSixWeapons;
 | 
			
		||||
        case "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionThree":
 | 
			
		||||
        case "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionFour":
 | 
			
		||||
        case "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionThree": // >= 35.6.0
 | 
			
		||||
        case "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionFour": // >= 37.0.0
 | 
			
		||||
            return corpusVersionThreeWeapons;
 | 
			
		||||
    }
 | 
			
		||||
    throw new Error(`unknown nemesis manifest: ${manifest}`);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const isNemesisCompatibleWithVersion = (
 | 
			
		||||
    nemesis: { manifest: string; Faction: string },
 | 
			
		||||
    buildLabel: string
 | 
			
		||||
): boolean => {
 | 
			
		||||
    // Anything below 35.6.0 is not going to be okay given our set of supported manifests.
 | 
			
		||||
    if (version_compare(buildLabel, "2024.05.15.11.07") < 0) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (nemesis.Faction == "FC_INFESTATION") {
 | 
			
		||||
        // Anything below 38.5.0 isn't gonna like an infested lich.
 | 
			
		||||
        if (version_compare(buildLabel, "2025.03.18.16.07") < 0) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    } else if (nemesis.manifest == "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionFour") {
 | 
			
		||||
        // Anything below 37.0.0 isn't gonna know version 4, but version 3 is identical in terms of weapon choices, so we can spoof it to that.
 | 
			
		||||
        if (version_compare(buildLabel, "2024.10.01.11.03") < 0) {
 | 
			
		||||
            nemesis.manifest = "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionThree";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const getInnateDamageTag = (
 | 
			
		||||
    KillingSuit: string
 | 
			
		||||
):
 | 
			
		||||
 | 
			
		||||
@ -1688,9 +1688,9 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
			
		||||
        //Like BossAladV,BossCaptainVor come for you on missions % chance
 | 
			
		||||
        DeathMarks: { type: [String], default: [] },
 | 
			
		||||
        //Zanuka
 | 
			
		||||
        Harvestable: { type: Boolean, default: true },
 | 
			
		||||
        Harvestable: Boolean,
 | 
			
		||||
        //Grustag three
 | 
			
		||||
        DeathSquadable: { type: Boolean, default: true },
 | 
			
		||||
        DeathSquadable: Boolean,
 | 
			
		||||
 | 
			
		||||
        EndlessXP: { type: [endlessXpProgressSchema], default: undefined },
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,7 @@ const databaseAccountSchema = new Schema<IDatabaseAccountJson>(
 | 
			
		||||
        ConsentNeeded: { type: Boolean, required: true },
 | 
			
		||||
        TrackedSettings: { type: [String], default: [] },
 | 
			
		||||
        Nonce: { type: Number, default: 0 },
 | 
			
		||||
        BuildLabel: String,
 | 
			
		||||
        Dropped: Boolean,
 | 
			
		||||
        LatestEventMessageDate: { type: Date, default: 0 },
 | 
			
		||||
        LastLoginRewardDate: { type: Number, default: 0 },
 | 
			
		||||
 | 
			
		||||
@ -332,7 +332,8 @@ export const addItem = async (
 | 
			
		||||
    quantity: number = 1,
 | 
			
		||||
    premiumPurchase: boolean = false,
 | 
			
		||||
    seed?: bigint,
 | 
			
		||||
    targetFingerprint?: string
 | 
			
		||||
    targetFingerprint?: string,
 | 
			
		||||
    exactQuantity: boolean = false
 | 
			
		||||
): Promise<IInventoryChanges> => {
 | 
			
		||||
    // Bundles are technically StoreItems but a) they don't have a normal counterpart, and b) they are used in non-StoreItem contexts, e.g. email attachments.
 | 
			
		||||
    if (typeName in ExportBundles) {
 | 
			
		||||
@ -490,7 +491,9 @@ export const addItem = async (
 | 
			
		||||
        // Multipling by purchase quantity for gear because:
 | 
			
		||||
        // - The Saya's Vigil scanner message has it as a non-counted attachment.
 | 
			
		||||
        // - Blueprints for Ancient Protector Specter, Shield Osprey Specter, etc. have num=1 despite giving their purchaseQuantity.
 | 
			
		||||
        if (!exactQuantity) {
 | 
			
		||||
            quantity *= ExportGear[typeName].purchaseQuantity ?? 1;
 | 
			
		||||
        }
 | 
			
		||||
        const consumablesChanges = [
 | 
			
		||||
            {
 | 
			
		||||
                ItemType: typeName,
 | 
			
		||||
@ -1506,7 +1509,9 @@ export const applyClientEquipmentUpdates = (
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (InfestationDate) {
 | 
			
		||||
            item.InfestationDate = fromMongoDate(InfestationDate);
 | 
			
		||||
            // 2147483647000 means cured, otherwise became infected
 | 
			
		||||
            item.InfestationDate =
 | 
			
		||||
                InfestationDate.$date.$numberLong == "2147483647000" ? new Date(0) : fromMongoDate(InfestationDate);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -858,8 +858,7 @@ export const addMissionRewards = async (
 | 
			
		||||
            for (const reward of fixedLevelRewards.levelKeyRewards2) {
 | 
			
		||||
                //quest stage completion credit rewards
 | 
			
		||||
                if (reward.rewardType == "RT_CREDITS") {
 | 
			
		||||
                    inventory.RegularCredits += reward.amount;
 | 
			
		||||
                    missionCompletionCredits += reward.amount;
 | 
			
		||||
                    missionCompletionCredits += reward.amount; // will be added to inventory in addCredits
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                MissionRewards.push({
 | 
			
		||||
 | 
			
		||||
@ -223,10 +223,10 @@ export const handlePurchase = async (
 | 
			
		||||
                                purchaseResponse.Standing = [
 | 
			
		||||
                                    {
 | 
			
		||||
                                        Tag: syndicateTag,
 | 
			
		||||
                                        Standing: favour.standingCost
 | 
			
		||||
                                        Standing: favour.standingCost * purchaseRequest.PurchaseParams.Quantity
 | 
			
		||||
                                    }
 | 
			
		||||
                                ];
 | 
			
		||||
                                affiliation.Standing -= favour.standingCost;
 | 
			
		||||
                                affiliation.Standing -= favour.standingCost * purchaseRequest.PurchaseParams.Quantity;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
@ -230,40 +230,6 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => {
 | 
			
		||||
 | 
			
		||||
    const boss = rng.randomElement(sortieBosses)!;
 | 
			
		||||
 | 
			
		||||
    const modifiers = [
 | 
			
		||||
        "SORTIE_MODIFIER_LOW_ENERGY",
 | 
			
		||||
        "SORTIE_MODIFIER_IMPACT",
 | 
			
		||||
        "SORTIE_MODIFIER_SLASH",
 | 
			
		||||
        "SORTIE_MODIFIER_PUNCTURE",
 | 
			
		||||
        "SORTIE_MODIFIER_EXIMUS",
 | 
			
		||||
        "SORTIE_MODIFIER_MAGNETIC",
 | 
			
		||||
        "SORTIE_MODIFIER_CORROSIVE",
 | 
			
		||||
        "SORTIE_MODIFIER_VIRAL",
 | 
			
		||||
        "SORTIE_MODIFIER_ELECTRICITY",
 | 
			
		||||
        "SORTIE_MODIFIER_RADIATION",
 | 
			
		||||
        "SORTIE_MODIFIER_GAS",
 | 
			
		||||
        "SORTIE_MODIFIER_FIRE",
 | 
			
		||||
        "SORTIE_MODIFIER_EXPLOSION",
 | 
			
		||||
        "SORTIE_MODIFIER_FREEZE",
 | 
			
		||||
        "SORTIE_MODIFIER_TOXIN",
 | 
			
		||||
        "SORTIE_MODIFIER_POISON",
 | 
			
		||||
        "SORTIE_MODIFIER_HAZARD_RADIATION",
 | 
			
		||||
        "SORTIE_MODIFIER_HAZARD_MAGNETIC",
 | 
			
		||||
        "SORTIE_MODIFIER_HAZARD_FOG", // TODO: push this if the mission tileset is Grineer Forest
 | 
			
		||||
        "SORTIE_MODIFIER_HAZARD_FIRE", // TODO: push this if the mission tileset is Corpus Ship or Grineer Galleon
 | 
			
		||||
        "SORTIE_MODIFIER_HAZARD_ICE",
 | 
			
		||||
        "SORTIE_MODIFIER_HAZARD_COLD",
 | 
			
		||||
        "SORTIE_MODIFIER_SECONDARY_ONLY",
 | 
			
		||||
        "SORTIE_MODIFIER_SHOTGUN_ONLY",
 | 
			
		||||
        "SORTIE_MODIFIER_SNIPER_ONLY",
 | 
			
		||||
        "SORTIE_MODIFIER_RIFLE_ONLY",
 | 
			
		||||
        "SORTIE_MODIFIER_MELEE_ONLY",
 | 
			
		||||
        "SORTIE_MODIFIER_BOW_ONLY"
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    if (sortieBossToFaction[boss] == "FC_CORPUS") modifiers.push("SORTIE_MODIFIER_SHIELDS");
 | 
			
		||||
    if (sortieBossToFaction[boss] != "FC_CORPUS") modifiers.push("SORTIE_MODIFIER_ARMOR");
 | 
			
		||||
 | 
			
		||||
    const nodes: string[] = [];
 | 
			
		||||
    const availableMissionIndexes: number[] = [];
 | 
			
		||||
    for (const [key, value] of Object.entries(ExportRegions)) {
 | 
			
		||||
@ -314,9 +280,38 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => {
 | 
			
		||||
                sortieFactionToSpecialMissionTileset[sortieBossToFaction[boss]]
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        const modifiers = [
 | 
			
		||||
            "SORTIE_MODIFIER_LOW_ENERGY",
 | 
			
		||||
            "SORTIE_MODIFIER_IMPACT",
 | 
			
		||||
            "SORTIE_MODIFIER_SLASH",
 | 
			
		||||
            "SORTIE_MODIFIER_PUNCTURE",
 | 
			
		||||
            "SORTIE_MODIFIER_EXIMUS",
 | 
			
		||||
            "SORTIE_MODIFIER_MAGNETIC",
 | 
			
		||||
            "SORTIE_MODIFIER_CORROSIVE",
 | 
			
		||||
            "SORTIE_MODIFIER_VIRAL",
 | 
			
		||||
            "SORTIE_MODIFIER_ELECTRICITY",
 | 
			
		||||
            "SORTIE_MODIFIER_RADIATION",
 | 
			
		||||
            "SORTIE_MODIFIER_GAS",
 | 
			
		||||
            "SORTIE_MODIFIER_FIRE",
 | 
			
		||||
            "SORTIE_MODIFIER_EXPLOSION",
 | 
			
		||||
            "SORTIE_MODIFIER_FREEZE",
 | 
			
		||||
            "SORTIE_MODIFIER_TOXIN",
 | 
			
		||||
            "SORTIE_MODIFIER_POISON",
 | 
			
		||||
            "SORTIE_MODIFIER_HAZARD_RADIATION",
 | 
			
		||||
            "SORTIE_MODIFIER_HAZARD_MAGNETIC",
 | 
			
		||||
            "SORTIE_MODIFIER_HAZARD_FOG", // TODO: push this if the mission tileset is Grineer Forest
 | 
			
		||||
            "SORTIE_MODIFIER_HAZARD_FIRE", // TODO: push this if the mission tileset is Corpus Ship or Grineer Galleon
 | 
			
		||||
            "SORTIE_MODIFIER_HAZARD_ICE",
 | 
			
		||||
            "SORTIE_MODIFIER_HAZARD_COLD",
 | 
			
		||||
            "SORTIE_MODIFIER_SECONDARY_ONLY",
 | 
			
		||||
            "SORTIE_MODIFIER_SHOTGUN_ONLY",
 | 
			
		||||
            "SORTIE_MODIFIER_SNIPER_ONLY",
 | 
			
		||||
            "SORTIE_MODIFIER_RIFLE_ONLY",
 | 
			
		||||
            "SORTIE_MODIFIER_BOW_ONLY"
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        if (i == 2 && boss != "SORTIE_BOSS_CORRUPTED_VOR" && rng.randomInt(0, 2) == 2) {
 | 
			
		||||
            const filteredModifiers = modifiers.filter(mod => mod !== "SORTIE_MODIFIER_MELEE_ONLY");
 | 
			
		||||
            const modifierType = rng.randomElement(filteredModifiers)!;
 | 
			
		||||
            const modifierType = rng.randomElement(modifiers)!;
 | 
			
		||||
 | 
			
		||||
            selectedNodes.push({
 | 
			
		||||
                missionType: "MT_ASSASSINATION",
 | 
			
		||||
@ -334,12 +329,21 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const filteredModifiers =
 | 
			
		||||
            missionType === "MT_TERRITORY"
 | 
			
		||||
                ? modifiers.filter(mod => mod != "SORTIE_MODIFIER_HAZARD_RADIATION")
 | 
			
		||||
                : modifiers;
 | 
			
		||||
        modifiers.push("SORTIE_MODIFIER_MELEE_ONLY"); // not an assassination mission, can now push this
 | 
			
		||||
 | 
			
		||||
        const modifierType = rng.randomElement(filteredModifiers)!;
 | 
			
		||||
        if (missionType != "MT_TERRITORY") {
 | 
			
		||||
            modifiers.push("SORTIE_MODIFIER_HAZARD_RADIATION");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (ExportRegions[node].factionIndex == 0) {
 | 
			
		||||
            // Grineer
 | 
			
		||||
            modifiers.push("SORTIE_MODIFIER_ARMOR");
 | 
			
		||||
        } else if (ExportRegions[node].factionIndex == 1) {
 | 
			
		||||
            // Corpus
 | 
			
		||||
            modifiers.push("SORTIE_MODIFIER_SHIELDS");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const modifierType = rng.randomElement(modifiers)!;
 | 
			
		||||
 | 
			
		||||
        selectedNodes.push({
 | 
			
		||||
            missionType,
 | 
			
		||||
@ -717,8 +721,8 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
 | 
			
		||||
        SyndicateMissions: [...staticWorldState.SyndicateMissions]
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Omit void fissures for versions prior to Whispers in the Walls to avoid errors with the unknown deimos nodes having void fissures.
 | 
			
		||||
    if (buildLabel && version_compare(buildLabel, "2023.11.06.13.39") <= 0) {
 | 
			
		||||
    // Omit void fissures for versions prior to Dante Unbound to avoid script errors.
 | 
			
		||||
    if (buildLabel && version_compare(buildLabel, "2024.03.24.20.00") < 0) {
 | 
			
		||||
        worldState.ActiveMissions = [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@ export interface IAccountAndLoginResponseCommons {
 | 
			
		||||
export interface IDatabaseAccountRequiredFields extends IAccountAndLoginResponseCommons {
 | 
			
		||||
    email: string;
 | 
			
		||||
    password: string;
 | 
			
		||||
    BuildLabel?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IDatabaseAccount extends IDatabaseAccountRequiredFields {
 | 
			
		||||
 | 
			
		||||
@ -1,38 +1,38 @@
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIGLzCCBRegAwIBAgIRAILIyLcitteoEGcJt1QBXvcwDQYJKoZIhvcNAQELBQAw
 | 
			
		||||
gY8xCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
 | 
			
		||||
BgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE3MDUGA1UE
 | 
			
		||||
AxMuU2VjdGlnbyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD
 | 
			
		||||
QTAeFw0yNDA4MDIwMDAwMDBaFw0yNTA4MDIyMzU5NTlaMBcxFTATBgNVBAMMDCou
 | 
			
		||||
dmlhdGxzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMTToSjY
 | 
			
		||||
3aUIxjghIkikJfFExVwSEzIM2XaQNJE+SxQ6Cc+xUR5QJrMJnM/39sH5c5imMEUo
 | 
			
		||||
2OnstCIaVMPx5ZPN+HXLsvmoVAe2/xYe7emnZ5ZFTUXPyqkzDRg0hkMJiWWo/Nmf
 | 
			
		||||
ypZfUJoz6hVkXwsgNFPTVuo7aECQFlZslh2HQVDOfBaNBxQBaOJ5vf6nllf/aLyB
 | 
			
		||||
tZ74nlLynVYV9kYzISP4dUcxQ+D4HZgIxyOQfcN3EHUS1ZVaIp8hupOygF8zGQyJ
 | 
			
		||||
uzFozzg5I59U+hT1yQG3FlwTBnP+sA0+hW0LBTbWSISm0If1SgHlUEqxLlosjuTG
 | 
			
		||||
BG45h9o2bAz9po0CAwEAAaOCAvswggL3MB8GA1UdIwQYMBaAFI2MXsRUrYrhd+mb
 | 
			
		||||
+ZsF4bgBjWHhMB0GA1UdDgQWBBQ/OeA2gLbVIKIuIitYRqSRUWMP3TAOBgNVHQ8B
 | 
			
		||||
MIIGMDCCBRigAwIBAgIQX4800cgswlDH/QexMSnnnjANBgkqhkiG9w0BAQsFADCB
 | 
			
		||||
jzELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
 | 
			
		||||
A1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQD
 | 
			
		||||
Ey5TZWN0aWdvIFJTQSBEb21haW4gVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB
 | 
			
		||||
MB4XDTI1MDMwNjAwMDAwMFoXDTI2MDMwNjIzNTk1OVowGDEWMBQGA1UEAwwNKi5m
 | 
			
		||||
YWtldGxzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMe42XWK
 | 
			
		||||
HJuR7doFTX79zrEKfTlD2hjRIif3dHKJNTJNvZa52mIoHelP7RVUuFOhp7aZCNLh
 | 
			
		||||
IEzDyZObl8vwO6L2PVu5tbBEEoNixbpfhc8ZICEBuVo2UAhnJFcMJtuvtrCq+7ye
 | 
			
		||||
oczM/k/nh8FBz2WnLzWs4CZt1sa5knZXFmBmsHJQtQIC6vx7QzVcKGOlAosIEHSK
 | 
			
		||||
X4nIz5fLgWSzor1Gay56j31PTk+qRvlPQM2aKiLWnlLfRED4zHJqLe94itu8llPX
 | 
			
		||||
b6g+cLxxRKUpMqtG/15cDdBZwv40Dja7bmNfe1u4w2QCVLjvHVaVpNXbcRay/Mhn
 | 
			
		||||
M1w5LzDZmV58b18CAwEAAaOCAvwwggL4MB8GA1UdIwQYMBaAFI2MXsRUrYrhd+mb
 | 
			
		||||
+ZsF4bgBjWHhMB0GA1UdDgQWBBS6/x/N38wMJrQq/cE1oIcRERMonTAOBgNVHQ8B
 | 
			
		||||
Af8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB
 | 
			
		||||
BQUHAwIwSQYDVR0gBEIwQDA0BgsrBgEEAbIxAQICBzAlMCMGCCsGAQUFBwIBFhdo
 | 
			
		||||
dHRwczovL3NlY3RpZ28uY29tL0NQUzAIBgZngQwBAgEwgYQGCCsGAQUFBwEBBHgw
 | 
			
		||||
djBPBggrBgEFBQcwAoZDaHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNB
 | 
			
		||||
RG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAjBggrBgEFBQcwAYYX
 | 
			
		||||
aHR0cDovL29jc3Auc2VjdGlnby5jb20wIwYDVR0RBBwwGoIMKi52aWF0bHMuY29t
 | 
			
		||||
ggp2aWF0bHMuY29tMIIBfwYKKwYBBAHWeQIEAgSCAW8EggFrAWkAdQDd3Mo0ldfh
 | 
			
		||||
FgXnlTL6x5/4PRxQ39sAOhQSdgosrLvIKgAAAZEVLi9VAAAEAwBGMEQCIGiZNOV7
 | 
			
		||||
IvcHKU7nEaxFgWPpUu2CxyULg1ueJTYwTT12AiAJWQv3RrqCtOJC7JEdztILs3Bn
 | 
			
		||||
an9s0Bf93uOE4C/LiAB3AA3h8jAr0w3BQGISCepVLvxHdHyx1+kw7w5CHrR+Tqo0
 | 
			
		||||
AAABkRUuLxAAAAQDAEgwRgIhAOhlC+IpJV3uAaDCRXi6RZ+V8++QaLaTEtqFp2UP
 | 
			
		||||
yWeSAiEA8qtGDk1RE1VGwQQcJCf3CBYU5YTlsZNi7F6hEONLuzMAdwAS8U40vVNy
 | 
			
		||||
TIQGGcOPP3oT+Oe1YoeInG0wBYTr5YYmOgAAAZEVLi7kAAAEAwBIMEYCIQDWCnSm
 | 
			
		||||
N+2/xxo8bl3pbpNBEBZZIwnYPQW0A+SJ0+dboQIhANjH2L0xV/+rPuPMzK40vk3J
 | 
			
		||||
1fWHLocLjpgaxGhsBAOzMA0GCSqGSIb3DQEBCwUAA4IBAQBcObVjc1zFdOER50ZF
 | 
			
		||||
mI+WyVF8t6nV6dm3zIDraLA4++zKUu9UKNJm9YPqLdPP7uTLHz6wuBNmyuWPdF0r
 | 
			
		||||
qAf4vsK3tcAds7kjK8injewEUCPG20mtNMUHyhlNEOJR2ySPPQ6Q+t+TtGAnimKa
 | 
			
		||||
Zr86quYgYaJYhoEEXcbB9fMoDQYlJDzgT2DXvfM4cyoden2tYZ3gQS6ftiXacBe0
 | 
			
		||||
WzFWYZ8mIP2Kb+D9tCapB9MVUzu3XJVy3S2FLQEWcWIvjnpad73a0/35i/nro6/k
 | 
			
		||||
TSK+MKBEBaNZuHJ8ubCToo1BftnsS8HuEPTNe8W1hyc2YmT9f5YQP6HWB2rxjH42
 | 
			
		||||
OTXh
 | 
			
		||||
aHR0cDovL29jc3Auc2VjdGlnby5jb20wJQYDVR0RBB4wHIINKi5mYWtldGxzLmNv
 | 
			
		||||
bYILZmFrZXRscy5jb20wggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB2AJaXZL9V
 | 
			
		||||
WJet90OHaDcIQnfp8DrV9qTzNm5GpD8PyqnGAAABlWsz5fgAAAQDAEcwRQIgTN7Y
 | 
			
		||||
/mDqiD3RbGVLEOQK2wvXsboBolBRwGJFuFEsDScCIQCQ0qfb/0V8qqSxrkx/PiVS
 | 
			
		||||
1lSn5gBEnQUiQOkefcnW0gB2ABmG1Mcoqm/+ugNveCpNAZGqzi1yMQ+uzl1wQS0l
 | 
			
		||||
TMfUAAABlWsz5dAAAAQDAEcwRQIhAJnQJyrSCWWdi9Kyoa7XuMGyDKt183jJMY0E
 | 
			
		||||
71abTuBOAiBC+WnK1esG6xr8aVGHRcc+1U/I7LiaG3LCRMYtCKrTGwB2AMs49xWJ
 | 
			
		||||
fIShRF9bwd37yW7ymlnNRwppBYWwyxTDFFjnAAABlWsz5f4AAAQDAEcwRQIhAJUs
 | 
			
		||||
4PWDwyQJnCxCyEwFlFUY2uYQkGrQPA9f9Sw5Xk1fAiB63eQtZQGjvzvhOghy6z9a
 | 
			
		||||
8oGYbDfDQ/zfisMYO7rM6zANBgkqhkiG9w0BAQsFAAOCAQEAEHnSoeBbWiK3CS3a
 | 
			
		||||
px0BL+YXxRxdUcTMHgn5o+LlI9sWlpf+JLXmn7Z4QA6fAwT4k/Ue7xsmIq0OraDk
 | 
			
		||||
/pEVXWm1HO/9wUkGQg0DBi77BpfHircd7OWIMdt250Q8UAmZkOyhVgnwBcScqMwq
 | 
			
		||||
2T5CPaYvYGgYWx/qkIBv7JqhVbrP82rnF9b9ZUZ8GIE31chBmtMva9AsnAN5dmRw
 | 
			
		||||
81bVvPWXUfX30CYu5sxeWL06Zpy9nfJumxZri1SWXNTBjSvud2jsZ8tSCUAWLL/4
 | 
			
		||||
ui3Vien9m2oMOpaA8xbS88ZTk9Alm/o5febEKJZUPlytQzij8gQpiovFw2v+Cdei
 | 
			
		||||
+tFXKw==
 | 
			
		||||
-----END CERTIFICATE-----
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIGEzCCA/ugAwIBAgIQfVtRJrR2uhHbdBYLvFMNpzANBgkqhkiG9w0BAQwFADCB
 | 
			
		||||
 | 
			
		||||
@ -1,28 +1,28 @@
 | 
			
		||||
-----BEGIN PRIVATE KEY-----
 | 
			
		||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDE06Eo2N2lCMY4
 | 
			
		||||
ISJIpCXxRMVcEhMyDNl2kDSRPksUOgnPsVEeUCazCZzP9/bB+XOYpjBFKNjp7LQi
 | 
			
		||||
GlTD8eWTzfh1y7L5qFQHtv8WHu3pp2eWRU1Fz8qpMw0YNIZDCYllqPzZn8qWX1Ca
 | 
			
		||||
M+oVZF8LIDRT01bqO2hAkBZWbJYdh0FQznwWjQcUAWjieb3+p5ZX/2i8gbWe+J5S
 | 
			
		||||
8p1WFfZGMyEj+HVHMUPg+B2YCMcjkH3DdxB1EtWVWiKfIbqTsoBfMxkMibsxaM84
 | 
			
		||||
OSOfVPoU9ckBtxZcEwZz/rANPoVtCwU21kiEptCH9UoB5VBKsS5aLI7kxgRuOYfa
 | 
			
		||||
NmwM/aaNAgMBAAECggEAEYK8bzxf96tAq0SzXqAP6heSsV7AS28eN7CbpKJUnp+N
 | 
			
		||||
OOePDnHWB46e31exoc82DAoY+EYqiiEvY2tRSD9wi8ZCyQQOz6w8kZUju42T3/ov
 | 
			
		||||
Ooy+06upXYU3sIQXv8YM7bjridbv+JHRQ27D8BRGamB6l0yRinQvkbLf8d9mOYkj
 | 
			
		||||
P5yYrpMPV/mfgkCir/aBlGOzmI+CuOv7FdF9DIz2OehtPXOzbExuab4xOQ4NQrN9
 | 
			
		||||
TfzWWS798D86e5uDx+Ab0pfege8IJvEBjU5ngZo3aeS/F5i2us+BXImu1P6IrYdb
 | 
			
		||||
ekXUo9VJPEHiD02iyLW/gFz3/AsWa3ztinXN0I069wKBgQD7yGPX6LG7MXlXEqL2
 | 
			
		||||
DuCrFsKzVC4z0c/cpPXO8Xb8rGzvHR7Oa0i5Bo7i5wRiVXS87HT25iZmB78yjKnI
 | 
			
		||||
bVmWA3tVWInx6fixbZUO7L4D/Q1Ddfin/DiXyNpAhKii0QgpD61P7HJnrfnwUar5
 | 
			
		||||
Vpwd2grnPNCbuILZxAZhtIXRnwKBgQDIH5hmyiIUAvrz+4UpE55ecxTMOkj0+Pgx
 | 
			
		||||
79KpSjXfEIk5V7UmCSk1SusQWq8Ri9d6QqPcTptVhxmC/geolp9bCW14JdORbjNv
 | 
			
		||||
5+3JfAwgZJtbDP4l3GKf168fLQXzSpWCW3vT1lCBz4x4nNs2EudTdDCn5aUVLGEJ
 | 
			
		||||
v15Iz0dQUwKBgHuZh8n55SXrx5FDCNSZwRi796Bo9rVhjhTWtgR87NhlHKTVOsZC
 | 
			
		||||
TFToL0Sb+776DHCh81kw6jC0JNv/yWkmpQ/LbcQbzrv/C6KuFLpa5Xy3wMcZJpPw
 | 
			
		||||
cSex5dI+TTqAOu1NUNsnS5IyCbw7mx8DsWfGHgweApovHa0hWbClGfwpAoGAfSt9
 | 
			
		||||
6DTfkcK3cilMhX+2236BcKe4ADlFC/7jtW0sOsQeAFbCf/LU6ndchVMjEwdzlA3g
 | 
			
		||||
bahg8eLZaxw2cBUdwRQpey+1n83csE7RZOeIsi4bGZ0LzWSF71I5P3eqtBxfXTSZ
 | 
			
		||||
Q8tVeYv2YW5CkhTKyWDwGePCGHc0jqM6drHm+e8CgYEA+IkvplnK76zx3M579TpI
 | 
			
		||||
M2ffiC2b12FtJMpgnNrk6HZ19o2mhbte/7wf9SHVqsRw4V7/n6rzBJ5wzEHOWre7
 | 
			
		||||
7PrkLgS0mY2SRfMmeT74m59dA8GpvhBUW/Xa4wlDtZkU2iIcDkKnYLjgrTKjlK86
 | 
			
		||||
ER+evzmHeTqYJzuK8Mfq93I=
 | 
			
		||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHuNl1ihybke3a
 | 
			
		||||
BU1+/c6xCn05Q9oY0SIn93RyiTUyTb2WudpiKB3pT+0VVLhToae2mQjS4SBMw8mT
 | 
			
		||||
m5fL8Dui9j1bubWwRBKDYsW6X4XPGSAhAblaNlAIZyRXDCbbr7awqvu8nqHMzP5P
 | 
			
		||||
54fBQc9lpy81rOAmbdbGuZJ2VxZgZrByULUCAur8e0M1XChjpQKLCBB0il+JyM+X
 | 
			
		||||
y4Fks6K9Rmsueo99T05Pqkb5T0DNmioi1p5S30RA+Mxyai3veIrbvJZT12+oPnC8
 | 
			
		||||
cUSlKTKrRv9eXA3QWcL+NA42u25jX3tbuMNkAlS47x1WlaTV23EWsvzIZzNcOS8w
 | 
			
		||||
2ZlefG9fAgMBAAECggEAT1Tti/LASks8300b60WFxG0WMJjzGMh5eMaiSpyVtNWM
 | 
			
		||||
aUKJrFOjDfnhgoeUcCPWKoG/L4Sc/+EFQMydDzTte120IasysEFZ2TZytAUdcZXZ
 | 
			
		||||
XUMCDQNl5vCRTsJU7Q5u0t4YAGRCgMcsfTDKi8lISGiQKBHzN1CJ74Xm13rgOInd
 | 
			
		||||
lAc0wd5S89sL6RYmRTj1LvuZ95EHXHqQGdv0fIFEyP3pF1iPwcoTuIVEeICqnEvW
 | 
			
		||||
vd8CVO68eH3HFIwioqjp4qW3pxPZMhVq4161805uAMkoQlE+7MtEVenmP++1u1gM
 | 
			
		||||
FjvAs3j9CZqOHZKcLlOtcGSwDlD++fCMMT4slLgLgQKBgQDy58E5nuYXdxlFQQk4
 | 
			
		||||
QccUKpyJ2aVXyp9xvTFBot/5Pik1SkuDzv2XU1OTxdxf3EongLy91nMJ2/6/39Je
 | 
			
		||||
lf0/2MjzCtJ/lSzZ/zpJAu86UkBkWBAA5loGIof6OKedbEIgqpJqtK59S+j3ExO9
 | 
			
		||||
eqa+uFrtt1UfaJG4A7TT+dIvIwKBgQDSfSOdSM5Dh3KsQHVnIWcIkzwTtlJlO+rG
 | 
			
		||||
6rDEADxw6Kp8VIL/dq4Foe8yW4VqLVrWUuZsU6jzC9GdnyYi6VaqZ/iSUtGkBMOT
 | 
			
		||||
WTTYhqXlURaQ13jhqdwCZJRbVI72JbXn2OGEv8DgXnk//QKED/8VdKqAzCSr1t1f
 | 
			
		||||
3yfwei0AlQKBgD19KU66yKg7/+umEP1quUiDmOjUbaSRqFcUe3mQD356m9ffnMob
 | 
			
		||||
BdrevxNzTNv/Wc4yKpUryic+x3gu4oQLF/annAbaQHsHejkdANYmpgRvedls6XAw
 | 
			
		||||
360Z5K4U1WlmVD8Mrs/QOTOCmdChxad7euZgqLPwat3ujKS2W3oljW1dAoGBAM4/
 | 
			
		||||
AB6lsDZLCfnuTxt2h1bHrh5CkAnR5AJ1BC+Ja6/WyvZ4eMOIroumWJKnStr3BgLr
 | 
			
		||||
yAxtDSbZddNUljGvIdRnfBEkRXbJlDlVN4rSpMtF4S6bcz7rCUDu/M9g05Qs70j2
 | 
			
		||||
IkPJAFzZNUWVzFlKs096uXbqkSQvrUq7ho8DqAThAoGBAL7Nrbr5LWcBgvwEhEla
 | 
			
		||||
VRfYb0FUrDwLIrVWntJjW566/pVQQ4BmatsblLjlQYWk9MCIYXWZbnB+2fRx9yjQ
 | 
			
		||||
Adggez7Dws/Mrh/wVudKgayHCy5Lgd8rYjNgC+VZf8XGrWX3QXMJ6UWAyQLTeoO7
 | 
			
		||||
hToW9o9CQMIhaR43G8di1kjF
 | 
			
		||||
-----END PRIVATE KEY-----
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user