forked from OpenWF/SpaceNinjaServer
		
	chore: cleanup missionInventoryUpdateService (#349)
Co-authored-by: Sainan <Sainan@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									56f9be9725
								
							
						
					
					
						commit
						079d67807a
					
				
							
								
								
									
										8
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -13,7 +13,7 @@
 | 
			
		||||
        "express": "^5.0.0-beta.3",
 | 
			
		||||
        "mongoose": "^8.1.1",
 | 
			
		||||
        "warframe-items": "^1.1262.74",
 | 
			
		||||
        "warframe-public-export-plus": "^0.2.5",
 | 
			
		||||
        "warframe-public-export-plus": "^0.3.0",
 | 
			
		||||
        "warframe-riven-info": "^0.1.0",
 | 
			
		||||
        "winston": "^3.11.0",
 | 
			
		||||
        "winston-daily-rotate-file": "^4.7.1"
 | 
			
		||||
@ -3678,9 +3678,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/warframe-public-export-plus": {
 | 
			
		||||
      "version": "0.2.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.2.5.tgz",
 | 
			
		||||
      "integrity": "sha512-IsS2Z14CeTpGSpfeUxqTi8wAQjQ6qjh2kV8RC9St5hcDmII3NpwEFXmStEqz7r+JPfea72D3cZMMl+4QLHqvXw=="
 | 
			
		||||
      "version": "0.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.3.0.tgz",
 | 
			
		||||
      "integrity": "sha512-BYkTkCq9jsA8NzSiWsTW48ezK7kI/op2NrLf+j4j3bJi2cNjoSLf/D4bMEui6yCADjcoV89ramRTFbPjn6UpLA=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/warframe-riven-info": {
 | 
			
		||||
      "version": "0.1.0",
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@
 | 
			
		||||
    "express": "^5.0.0-beta.3",
 | 
			
		||||
    "mongoose": "^8.1.1",
 | 
			
		||||
    "warframe-items": "^1.1262.74",
 | 
			
		||||
    "warframe-public-export-plus": "^0.2.5",
 | 
			
		||||
    "warframe-public-export-plus": "^0.3.0",
 | 
			
		||||
    "warframe-riven-info": "^0.1.0",
 | 
			
		||||
    "winston": "^3.11.0",
 | 
			
		||||
    "winston-daily-rotate-file": "^4.7.1"
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
import { getIndexAfter } from "@/src/helpers/stringHelpers";
 | 
			
		||||
import { logger } from "@/src/utils/logger";
 | 
			
		||||
import Items, { Category, MinimalItem, Warframe, Weapon } from "warframe-items";
 | 
			
		||||
import badItems from "@/static/json/exclude-mods.json";
 | 
			
		||||
import Items, { MinimalItem, Warframe, Weapon } from "warframe-items";
 | 
			
		||||
import {
 | 
			
		||||
    dict_en,
 | 
			
		||||
    ExportRecipes,
 | 
			
		||||
@ -53,23 +52,6 @@ export const getWeaponType = (weaponName: string): WeaponTypeInternal => {
 | 
			
		||||
    return weaponType;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const getNamesObj = (category: Category) =>
 | 
			
		||||
    new Items({ category: [category] }).reduce<{ [index: string]: string }>((acc, item) => {
 | 
			
		||||
        if (!(item.uniqueName! in badItems)) {
 | 
			
		||||
            acc[item.name!.replace("'S", "'s")] = item.uniqueName!;
 | 
			
		||||
        }
 | 
			
		||||
        return acc;
 | 
			
		||||
    }, {});
 | 
			
		||||
 | 
			
		||||
export const modNames = getNamesObj("Mods");
 | 
			
		||||
export const resourceNames = getNamesObj("Resources");
 | 
			
		||||
export const miscNames = getNamesObj("Misc");
 | 
			
		||||
export const relicNames = getNamesObj("Relics");
 | 
			
		||||
export const skinNames = getNamesObj("Skins");
 | 
			
		||||
export const arcaneNames = getNamesObj("Arcanes");
 | 
			
		||||
export const gearNames = getNamesObj("Gear");
 | 
			
		||||
//logger.debug(`gear names`, { gearNames });
 | 
			
		||||
 | 
			
		||||
export const craftNames = Object.fromEntries(
 | 
			
		||||
    (
 | 
			
		||||
        new Items({
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,14 @@
 | 
			
		||||
import { IMissionRewardResponse, IReward, IInventoryFieldType, inventoryFields } from "@/src/types/missionTypes";
 | 
			
		||||
import { IMissionRewardResponse, IInventoryFieldType, inventoryFields } from "@/src/types/missionTypes";
 | 
			
		||||
 | 
			
		||||
import missionsDropTable from "@/static/json/missions-drop-table.json";
 | 
			
		||||
import {
 | 
			
		||||
    modNames,
 | 
			
		||||
    relicNames,
 | 
			
		||||
    miscNames,
 | 
			
		||||
    resourceNames,
 | 
			
		||||
    gearNames,
 | 
			
		||||
    blueprintNames
 | 
			
		||||
} from "@/src/services/itemDataService";
 | 
			
		||||
    ExportRegions,
 | 
			
		||||
    ExportRewards,
 | 
			
		||||
    ExportUpgrades,
 | 
			
		||||
    ExportGear,
 | 
			
		||||
    ExportRecipes,
 | 
			
		||||
    ExportRelics,
 | 
			
		||||
    IReward
 | 
			
		||||
} from "warframe-public-export-plus";
 | 
			
		||||
import { IMissionInventoryUpdateRequest } from "../types/requestTypes";
 | 
			
		||||
import { logger } from "@/src/utils/logger";
 | 
			
		||||
 | 
			
		||||
@ -23,49 +23,25 @@ const getRewards = ({
 | 
			
		||||
        return { InventoryChanges: {}, MissionRewards: [] };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const rewards = (missionsDropTable as { [key: string]: IReward[] })[RewardInfo.node];
 | 
			
		||||
    if (!rewards) {
 | 
			
		||||
    const rewardManifests = ExportRegions[RewardInfo.node]?.rewardManifests ?? [];
 | 
			
		||||
    if (rewardManifests.length == 0) {
 | 
			
		||||
        return { InventoryChanges: {}, MissionRewards: [] };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const rotationCount = RewardInfo.rewardQualifications?.length || 0;
 | 
			
		||||
    const rotations = getRotations(rotationCount);
 | 
			
		||||
    const drops: IReward[] = [];
 | 
			
		||||
    for (const rotation of rotations) {
 | 
			
		||||
        const rotationRewards = rewards.filter(reward => reward.rotation === rotation);
 | 
			
		||||
 | 
			
		||||
        // Separate guaranteed and chance drops
 | 
			
		||||
        const guaranteedDrops: IReward[] = [];
 | 
			
		||||
        const chanceDrops: IReward[] = [];
 | 
			
		||||
        for (const reward of rotationRewards) {
 | 
			
		||||
            if (reward.chance === 100) {
 | 
			
		||||
                guaranteedDrops.push(reward);
 | 
			
		||||
            } else {
 | 
			
		||||
                chanceDrops.push(reward);
 | 
			
		||||
    rewardManifests
 | 
			
		||||
        .map(name => ExportRewards[name])
 | 
			
		||||
        .forEach(table => {
 | 
			
		||||
            for (const rotation of rotations) {
 | 
			
		||||
                const rotationRewards = table[rotation];
 | 
			
		||||
                const drop = getRandomRewardByChance(rotationRewards);
 | 
			
		||||
                if (drop) {
 | 
			
		||||
                    drops.push(drop);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const randomDrop = getRandomRewardByChance(chanceDrops);
 | 
			
		||||
        if (randomDrop) {
 | 
			
		||||
            guaranteedDrops.push(randomDrop);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        drops.push(...guaranteedDrops);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // const testDrops = [
 | 
			
		||||
    //     { chance: 7.69, name: "Lith W3 Relic", rotation: "B" },
 | 
			
		||||
    //     { chance: 7.69, name: "Lith W3 Relic", rotation: "B" },
 | 
			
		||||
    //     { chance: 10.82, name: "2X Orokin Cell", rotation: "C" },
 | 
			
		||||
    //     { chance: 10.82, name: "Arrow Mutation", rotation: "C" },
 | 
			
		||||
    //     { chance: 10.82, name: "200 Endo", rotation: "C" },
 | 
			
		||||
    //     { chance: 10.82, name: "200 Endo", rotation: "C" },
 | 
			
		||||
    //     { chance: 10.82, name: "2,000,000 Credits Cache", rotation: "C" },
 | 
			
		||||
    //     { chance: 7.69, name: "Health Restore (Large)", rotation: "C" },
 | 
			
		||||
    //     { chance: 7.69, name: "Vapor Specter Blueprint", rotation: "C" }
 | 
			
		||||
    // ];
 | 
			
		||||
    // logger.debug("Mission rewards:", testDrops);
 | 
			
		||||
    // return formatRewardsToInventoryType(testDrops);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    logger.debug("Mission rewards:", drops);
 | 
			
		||||
    return formatRewardsToInventoryType(drops);
 | 
			
		||||
@ -100,10 +76,10 @@ const combineRewardAndLootInventory = (
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const getRotations = (rotationCount: number): (string | undefined)[] => {
 | 
			
		||||
    if (rotationCount === 0) return [undefined];
 | 
			
		||||
const getRotations = (rotationCount: number): number[] => {
 | 
			
		||||
    if (rotationCount === 0) return [0];
 | 
			
		||||
 | 
			
		||||
    const rotationPattern = ["A", "A", "B", "C"];
 | 
			
		||||
    const rotationPattern = [0, 0, 1, 2]; // A, A, B, C
 | 
			
		||||
    const rotatedValues = [];
 | 
			
		||||
 | 
			
		||||
    for (let i = 0; i < rotationCount; i++) {
 | 
			
		||||
@ -113,15 +89,15 @@ const getRotations = (rotationCount: number): (string | undefined)[] => {
 | 
			
		||||
    return rotatedValues;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const getRandomRewardByChance = (data: IReward[] | undefined): IReward | undefined => {
 | 
			
		||||
    if (!data || data.length == 0) return;
 | 
			
		||||
const getRandomRewardByChance = (data: IReward[]): IReward | undefined => {
 | 
			
		||||
    if (data.length == 0) return;
 | 
			
		||||
 | 
			
		||||
    const totalChance = data.reduce((sum, item) => sum + item.chance, 0);
 | 
			
		||||
    const totalChance = data.reduce((sum, item) => sum + item.probability!, 0);
 | 
			
		||||
    const randomValue = Math.random() * totalChance;
 | 
			
		||||
 | 
			
		||||
    let cumulativeChance = 0;
 | 
			
		||||
    for (const item of data) {
 | 
			
		||||
        cumulativeChance += item.chance;
 | 
			
		||||
        cumulativeChance += item.probability!;
 | 
			
		||||
        if (randomValue <= cumulativeChance) {
 | 
			
		||||
            return item;
 | 
			
		||||
        }
 | 
			
		||||
@ -130,68 +106,62 @@ const getRandomRewardByChance = (data: IReward[] | undefined): IReward | undefin
 | 
			
		||||
    return;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const creditBundles: Record<string, number> = {
 | 
			
		||||
    "/Lotus/StoreItems/Types/PickUps/Credits/1500Credits": 1500,
 | 
			
		||||
    "/Lotus/StoreItems/Types/PickUps/Credits/2000Credits": 2000,
 | 
			
		||||
    "/Lotus/StoreItems/Types/PickUps/Credits/2500Credits": 2500,
 | 
			
		||||
    "/Lotus/StoreItems/Types/PickUps/Credits/3000Credits": 3000,
 | 
			
		||||
    "/Lotus/StoreItems/Types/PickUps/Credits/4000Credits": 4000,
 | 
			
		||||
    "/Lotus/StoreItems/Types/PickUps/Credits/5000Credits": 5000,
 | 
			
		||||
    "/Lotus/StoreItems/Types/PickUps/Credits/7500Credits": 7500,
 | 
			
		||||
    "/Lotus/StoreItems/Types/PickUps/Credits/10000Credits": 10000,
 | 
			
		||||
    "/Lotus/StoreItems/Types/StoreItems/CreditBundles/Zariman/TableACreditsCommon": 15000,
 | 
			
		||||
    "/Lotus/StoreItems/Types/StoreItems/CreditBundles/Zariman/TableACreditsUncommon": 30000,
 | 
			
		||||
    "/Lotus/StoreItems/Types/PickUps/Credits/CorpusArenaCreditRewards/CorpusArenaRewardOneHard": 105000,
 | 
			
		||||
    "/Lotus/StoreItems/Types/PickUps/Credits/CorpusArenaCreditRewards/CorpusArenaRewardTwoHard": 175000,
 | 
			
		||||
    "/Lotus/StoreItems/Types/PickUps/Credits/CorpusArenaCreditRewards/CorpusArenaRewardThreeHard": 25000
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const fusionBundles: Record<string, number> = {
 | 
			
		||||
    "/Lotus/StoreItems/Upgrades/Mods/FusionBundles/UncommonFusionBundle": 50,
 | 
			
		||||
    "/Lotus/StoreItems/Upgrades/Mods/FusionBundles/RareFusionBundle": 80
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const formatRewardsToInventoryType = (
 | 
			
		||||
    rewards: IReward[]
 | 
			
		||||
): { InventoryChanges: IMissionInventoryUpdateRequest; MissionRewards: IMissionRewardResponse[] } => {
 | 
			
		||||
    const InventoryChanges: IMissionInventoryUpdateRequest = {};
 | 
			
		||||
    const MissionRewards: IMissionRewardResponse[] = [];
 | 
			
		||||
    for (const reward of rewards) {
 | 
			
		||||
        if (itemCheck(InventoryChanges, MissionRewards, reward.name)) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (reward.name.includes(" Endo")) {
 | 
			
		||||
            if (!InventoryChanges.FusionPoints) {
 | 
			
		||||
                InventoryChanges.FusionPoints = 0;
 | 
			
		||||
        if (reward.type in creditBundles) {
 | 
			
		||||
            InventoryChanges.RegularCredits ??= 0;
 | 
			
		||||
            InventoryChanges.RegularCredits += creditBundles[reward.type] * reward.itemCount;
 | 
			
		||||
        } else if (reward.type in fusionBundles) {
 | 
			
		||||
            InventoryChanges.FusionPoints ??= 0;
 | 
			
		||||
            InventoryChanges.FusionPoints += fusionBundles[reward.type] * reward.itemCount;
 | 
			
		||||
        } else {
 | 
			
		||||
            const type = reward.type.replace("/Lotus/StoreItems/", "/Lotus/");
 | 
			
		||||
            if (type in ExportUpgrades) {
 | 
			
		||||
                addRewardResponse(InventoryChanges, MissionRewards, type, reward.itemCount, "RawUpgrades");
 | 
			
		||||
            } else if (type in ExportGear) {
 | 
			
		||||
                addRewardResponse(InventoryChanges, MissionRewards, type, reward.itemCount, "Consumables");
 | 
			
		||||
            } else if (type in ExportRecipes) {
 | 
			
		||||
                addRewardResponse(InventoryChanges, MissionRewards, type, reward.itemCount, "Recipes");
 | 
			
		||||
            } else if (type in ExportRelics) {
 | 
			
		||||
                addRewardResponse(InventoryChanges, MissionRewards, type, reward.itemCount, "MiscItems");
 | 
			
		||||
            } else {
 | 
			
		||||
                logger.error(`rolled reward ${reward.itemCount}X ${reward.type} but unsure how to give it`);
 | 
			
		||||
            }
 | 
			
		||||
            InventoryChanges.FusionPoints += getCountFromName(reward.name);
 | 
			
		||||
        } else if (reward.name.includes(" Credits Cache") || reward.name.includes("Return: ")) {
 | 
			
		||||
            if (!InventoryChanges.RegularCredits) {
 | 
			
		||||
                InventoryChanges.RegularCredits = 0;
 | 
			
		||||
            }
 | 
			
		||||
            InventoryChanges.RegularCredits += getCountFromName(reward.name);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return { InventoryChanges, MissionRewards };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const itemCheck = (
 | 
			
		||||
    InventoryChanges: IMissionInventoryUpdateRequest,
 | 
			
		||||
    MissionRewards: IMissionRewardResponse[],
 | 
			
		||||
    name: string
 | 
			
		||||
) => {
 | 
			
		||||
    const rewardCheck = {
 | 
			
		||||
        RawUpgrades: modNames[name],
 | 
			
		||||
        Consumables: gearNames[name],
 | 
			
		||||
        MiscItems:
 | 
			
		||||
            miscNames[name] ||
 | 
			
		||||
            miscNames[name.replace(/\d+X\s*/, "")] ||
 | 
			
		||||
            resourceNames[name] ||
 | 
			
		||||
            resourceNames[name.replace(/\d+X\s*/, "")] ||
 | 
			
		||||
            relicNames[name.replace("Relic", "Intact")] ||
 | 
			
		||||
            relicNames[name.replace("Relic (Radiant)", "Radiant")],
 | 
			
		||||
        Recipes: blueprintNames[name]
 | 
			
		||||
    };
 | 
			
		||||
    for (const key of Object.keys(rewardCheck) as IInventoryFieldType[]) {
 | 
			
		||||
        if (rewardCheck[key]) {
 | 
			
		||||
            addRewardResponse(InventoryChanges, MissionRewards, name, rewardCheck[key], key);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const getCountFromName = (name: string) => {
 | 
			
		||||
    const regex = /(^(?:\d{1,3}(?:,\d{3})*(?:\.\d+)?)(\s|X))|(\s(?:\d{1,3}(?:,\d{3})*(?:\.\d+)?)$)/;
 | 
			
		||||
    const countMatches = name.match(regex);
 | 
			
		||||
    return countMatches ? parseInt(countMatches[0].replace(/,/g, ""), 10) : 1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const addRewardResponse = (
 | 
			
		||||
    InventoryChanges: IMissionInventoryUpdateRequest,
 | 
			
		||||
    MissionRewards: IMissionRewardResponse[],
 | 
			
		||||
    ItemName: string,
 | 
			
		||||
    ItemType: string,
 | 
			
		||||
    ItemCount: number,
 | 
			
		||||
    InventoryCategory: IInventoryFieldType
 | 
			
		||||
) => {
 | 
			
		||||
    if (!ItemType) return;
 | 
			
		||||
@ -200,9 +170,6 @@ const addRewardResponse = (
 | 
			
		||||
        InventoryChanges[InventoryCategory] = [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const ItemCount = getCountFromName(ItemName);
 | 
			
		||||
    const TweetText = `${ItemName}`;
 | 
			
		||||
 | 
			
		||||
    const existReward = InventoryChanges[InventoryCategory]!.find(item => item.ItemType === ItemType);
 | 
			
		||||
    if (existReward) {
 | 
			
		||||
        existReward.ItemCount += ItemCount;
 | 
			
		||||
@ -214,7 +181,7 @@ const addRewardResponse = (
 | 
			
		||||
        InventoryChanges[InventoryCategory]!.push({ ItemType, ItemCount });
 | 
			
		||||
        MissionRewards.push({
 | 
			
		||||
            ItemCount,
 | 
			
		||||
            TweetText,
 | 
			
		||||
            TweetText: ItemType, // ensure if/how this even still used, or if it's needed at all
 | 
			
		||||
            ProductCategory: InventoryCategory,
 | 
			
		||||
            StoreItem: ItemType.replace("/Lotus/", "/Lotus/StoreItems/"),
 | 
			
		||||
            TypeName: ItemType
 | 
			
		||||
@ -222,32 +189,4 @@ const addRewardResponse = (
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
			
		||||
const _missionRewardsCheckAllNamings = () => {
 | 
			
		||||
    let tempRewards: IReward[] = [];
 | 
			
		||||
    Object.values(missionsDropTable as { [key: string]: IReward[] }).forEach(rewards => {
 | 
			
		||||
        rewards.forEach(reward => {
 | 
			
		||||
            tempRewards.push(reward);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    tempRewards = tempRewards
 | 
			
		||||
        .filter(reward => !modNames[reward.name])
 | 
			
		||||
        .filter(reward => !miscNames[reward.name])
 | 
			
		||||
        .filter(reward => !miscNames[reward.name.replace(/\d+X\s*/, "")])
 | 
			
		||||
        .filter(reward => !resourceNames[reward.name])
 | 
			
		||||
        .filter(reward => !resourceNames[reward.name.replace(/\d+X\s*/, "")])
 | 
			
		||||
        .filter(reward => !gearNames[reward.name])
 | 
			
		||||
        .filter(reward => {
 | 
			
		||||
            return (
 | 
			
		||||
                !relicNames[reward.name.replace("Relic", "Intact")] &&
 | 
			
		||||
                !relicNames[reward.name.replace("Relic (Radiant)", "Radiant")]
 | 
			
		||||
            );
 | 
			
		||||
        })
 | 
			
		||||
        .filter(reward => !blueprintNames[reward.name])
 | 
			
		||||
        .filter(reward => !reward.name.includes(" Endo"))
 | 
			
		||||
        .filter(reward => !reward.name.includes(" Credits Cache") && !reward.name.includes("Return: "));
 | 
			
		||||
    logger.debug(`temp rewards`, { tempRewards });
 | 
			
		||||
};
 | 
			
		||||
// _missionRewardsCheckAllNamings();
 | 
			
		||||
 | 
			
		||||
export { getRewards, combineRewardAndLootInventory };
 | 
			
		||||
 | 
			
		||||
@ -9,9 +9,3 @@ export interface IMissionRewardResponse {
 | 
			
		||||
    TweetText: string;
 | 
			
		||||
    ProductCategory: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IReward {
 | 
			
		||||
    name: string;
 | 
			
		||||
    chance: number;
 | 
			
		||||
    rotation?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -67,7 +67,7 @@ export interface IMissionInventoryUpdateRequestRewardInfo {
 | 
			
		||||
    lostTargetWave?: number;
 | 
			
		||||
    defenseTargetCount?: number;
 | 
			
		||||
    EOM_AFK?: number;
 | 
			
		||||
    rewardQualifications?: string;
 | 
			
		||||
    rewardQualifications?: string; // did a Survival for 5 minutes and this was "1"
 | 
			
		||||
    PurgatoryRewardQualifications?: string;
 | 
			
		||||
    rewardSeed?: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user