feat(webui): more equipment (#826)
This commit is contained in:
		
							parent
							
								
									3c99b748dc
								
							
						
					
					
						commit
						86a2b57e22
					
				@ -51,6 +51,41 @@ export const sellController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
            inventory.Melee.pull({ _id: sellItem.String });
 | 
					            inventory.Melee.pull({ _id: sellItem.String });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (payload.Items.SpaceSuits) {
 | 
				
			||||||
 | 
					        payload.Items.SpaceSuits.forEach(sellItem => {
 | 
				
			||||||
 | 
					            inventory.SpaceSuits.pull({ _id: sellItem.String });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (payload.Items.SpaceGuns) {
 | 
				
			||||||
 | 
					        payload.Items.SpaceGuns.forEach(sellItem => {
 | 
				
			||||||
 | 
					            inventory.SpaceGuns.pull({ _id: sellItem.String });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (payload.Items.SpaceMelee) {
 | 
				
			||||||
 | 
					        payload.Items.SpaceMelee.forEach(sellItem => {
 | 
				
			||||||
 | 
					            inventory.SpaceMelee.pull({ _id: sellItem.String });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (payload.Items.Sentinels) {
 | 
				
			||||||
 | 
					        payload.Items.Sentinels.forEach(sellItem => {
 | 
				
			||||||
 | 
					            inventory.Sentinels.pull({ _id: sellItem.String });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (payload.Items.SentinelWeapons) {
 | 
				
			||||||
 | 
					        payload.Items.SentinelWeapons.forEach(sellItem => {
 | 
				
			||||||
 | 
					            inventory.SentinelWeapons.pull({ _id: sellItem.String });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (payload.Items.OperatorAmps) {
 | 
				
			||||||
 | 
					        payload.Items.OperatorAmps.forEach(sellItem => {
 | 
				
			||||||
 | 
					            inventory.OperatorAmps.pull({ _id: sellItem.String });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (payload.Items.Hoverboards) {
 | 
				
			||||||
 | 
					        payload.Items.Hoverboards.forEach(sellItem => {
 | 
				
			||||||
 | 
					            inventory.Hoverboards.pull({ _id: sellItem.String });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (payload.Items.Consumables) {
 | 
					    if (payload.Items.Consumables) {
 | 
				
			||||||
        const consumablesChanges = [];
 | 
					        const consumablesChanges = [];
 | 
				
			||||||
        for (const sellItem of payload.Items.Consumables) {
 | 
					        for (const sellItem of payload.Items.Consumables) {
 | 
				
			||||||
@ -110,6 +145,13 @@ interface ISellRequest {
 | 
				
			|||||||
        Recipes?: ISellItem[];
 | 
					        Recipes?: ISellItem[];
 | 
				
			||||||
        Upgrades?: ISellItem[];
 | 
					        Upgrades?: ISellItem[];
 | 
				
			||||||
        MiscItems?: ISellItem[];
 | 
					        MiscItems?: ISellItem[];
 | 
				
			||||||
 | 
					        SpaceSuits?: ISellItem[];
 | 
				
			||||||
 | 
					        SpaceGuns?: ISellItem[];
 | 
				
			||||||
 | 
					        SpaceMelee?: ISellItem[];
 | 
				
			||||||
 | 
					        Sentinels?: ISellItem[];
 | 
				
			||||||
 | 
					        SentinelWeapons?: ISellItem[];
 | 
				
			||||||
 | 
					        OperatorAmps?: ISellItem[];
 | 
				
			||||||
 | 
					        Hoverboards?: ISellItem[];
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    SellPrice: number;
 | 
					    SellPrice: number;
 | 
				
			||||||
    SellCurrency:
 | 
					    SellCurrency:
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,8 @@
 | 
				
			|||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
import { getWeaponType } from "@/src/services/itemDataService";
 | 
					import { addEquipment, addPowerSuit, getInventory, updateSlots } from "@/src/services/inventoryService";
 | 
				
			||||||
import { addPowerSuit, addEquipment, getInventory, updateSlots } from "@/src/services/inventoryService";
 | 
					import { SlotNames } from "@/src/types/purchaseTypes";
 | 
				
			||||||
import { RequestHandler } from "express";
 | 
					 | 
				
			||||||
import { InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
					import { InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
				
			||||||
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const addItemsController: RequestHandler = async (req, res) => {
 | 
					export const addItemsController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const accountId = await getAccountIdForRequest(req);
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
@ -10,14 +10,14 @@ export const addItemsController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
    const inventory = await getInventory(accountId);
 | 
					    const inventory = await getInventory(accountId);
 | 
				
			||||||
    for (const request of requests) {
 | 
					    for (const request of requests) {
 | 
				
			||||||
        switch (request.type) {
 | 
					        switch (request.type) {
 | 
				
			||||||
            case ItemType.Powersuit:
 | 
					            case ItemType.Suits:
 | 
				
			||||||
                updateSlots(inventory, InventorySlot.SUITS, 0, 1);
 | 
					                updateSlots(inventory, productCategoryToSlotName[request.type], 0, 1);
 | 
				
			||||||
                addPowerSuit(inventory, request.internalName);
 | 
					                addPowerSuit(inventory, request.internalName);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            case ItemType.Weapon:
 | 
					            default:
 | 
				
			||||||
                updateSlots(inventory, InventorySlot.WEAPONS, 0, 1);
 | 
					                updateSlots(inventory, productCategoryToSlotName[request.type], 0, 1);
 | 
				
			||||||
                addEquipment(inventory, getWeaponType(request.internalName), request.internalName);
 | 
					                addEquipment(inventory, request.type, request.internalName);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -25,9 +25,28 @@ export const addItemsController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
    res.end();
 | 
					    res.end();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const productCategoryToSlotName: Record<ItemType, SlotNames> = {
 | 
				
			||||||
 | 
					    Suits: InventorySlot.SUITS,
 | 
				
			||||||
 | 
					    Pistols: InventorySlot.WEAPONS,
 | 
				
			||||||
 | 
					    Melee: InventorySlot.WEAPONS,
 | 
				
			||||||
 | 
					    LongGuns: InventorySlot.WEAPONS,
 | 
				
			||||||
 | 
					    SpaceSuits: InventorySlot.SPACESUITS,
 | 
				
			||||||
 | 
					    SpaceGuns: InventorySlot.SPACESUITS,
 | 
				
			||||||
 | 
					    SpaceMelee: InventorySlot.SPACESUITS,
 | 
				
			||||||
 | 
					    Sentinels: InventorySlot.SENTINELS,
 | 
				
			||||||
 | 
					    SentinelWeapons: InventorySlot.SENTINELS
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum ItemType {
 | 
					enum ItemType {
 | 
				
			||||||
    Powersuit = "Powersuit",
 | 
					    Suits = "Suits",
 | 
				
			||||||
    Weapon = "Weapon"
 | 
					    SpaceSuits = "SpaceSuits",
 | 
				
			||||||
 | 
					    LongGuns = "LongGuns",
 | 
				
			||||||
 | 
					    Pistols = "Pistols",
 | 
				
			||||||
 | 
					    Melee = "Melee",
 | 
				
			||||||
 | 
					    SpaceGuns = "SpaceGuns",
 | 
				
			||||||
 | 
					    SpaceMelee = "SpaceMelee",
 | 
				
			||||||
 | 
					    SentinelWeapons = "SentinelWeapons",
 | 
				
			||||||
 | 
					    Sentinels = "Sentinels"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IAddItemRequest {
 | 
					interface IAddItemRequest {
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,7 @@ import {
 | 
				
			|||||||
    ExportGear,
 | 
					    ExportGear,
 | 
				
			||||||
    ExportRecipes,
 | 
					    ExportRecipes,
 | 
				
			||||||
    ExportResources,
 | 
					    ExportResources,
 | 
				
			||||||
 | 
					    ExportSentinels,
 | 
				
			||||||
    ExportUpgrades,
 | 
					    ExportUpgrades,
 | 
				
			||||||
    ExportWarframes,
 | 
					    ExportWarframes,
 | 
				
			||||||
    ExportWeapons
 | 
					    ExportWeapons
 | 
				
			||||||
@ -15,21 +16,66 @@ interface ListedItem {
 | 
				
			|||||||
    uniqueName: string;
 | 
					    uniqueName: string;
 | 
				
			||||||
    name: string;
 | 
					    name: string;
 | 
				
			||||||
    fusionLimit?: number;
 | 
					    fusionLimit?: number;
 | 
				
			||||||
 | 
					    exalted?: string[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getItemListsController: RequestHandler = (req, response) => {
 | 
					const getItemListsController: RequestHandler = (req, response) => {
 | 
				
			||||||
    const lang = getDict(typeof req.query.lang == "string" ? req.query.lang : "en");
 | 
					    const lang = getDict(typeof req.query.lang == "string" ? req.query.lang : "en");
 | 
				
			||||||
    const res: Record<string, ListedItem[]> = {};
 | 
					    const res: Record<string, ListedItem[]> = {};
 | 
				
			||||||
    res.LongGuns = [];
 | 
					    res.LongGuns = [];
 | 
				
			||||||
    res.Pistols = [];
 | 
					 | 
				
			||||||
    res.Melee = [];
 | 
					    res.Melee = [];
 | 
				
			||||||
 | 
					    res.ModularParts = [];
 | 
				
			||||||
 | 
					    res.Pistols = [];
 | 
				
			||||||
 | 
					    res.Sentinels = [];
 | 
				
			||||||
 | 
					    res.SentinelWeapons = [];
 | 
				
			||||||
 | 
					    res.SpaceGuns = [];
 | 
				
			||||||
 | 
					    res.SpaceMelee = [];
 | 
				
			||||||
 | 
					    res.SpaceSuits = [];
 | 
				
			||||||
 | 
					    res.Suits = [];
 | 
				
			||||||
    res.miscitems = [];
 | 
					    res.miscitems = [];
 | 
				
			||||||
 | 
					    for (const [uniqueName, item] of Object.entries(ExportWarframes)) {
 | 
				
			||||||
 | 
					        if (item.productCategory == "Suits" || item.productCategory == "SpaceSuits") {
 | 
				
			||||||
 | 
					            res[item.productCategory].push({
 | 
				
			||||||
 | 
					                uniqueName,
 | 
				
			||||||
 | 
					                name: getString(item.name, lang),
 | 
				
			||||||
 | 
					                exalted: item.exalted
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    for (const [uniqueName, item] of Object.entries(ExportSentinels)) {
 | 
				
			||||||
 | 
					        if (item.productCategory == "Sentinels") {
 | 
				
			||||||
 | 
					            res[item.productCategory].push({
 | 
				
			||||||
 | 
					                uniqueName,
 | 
				
			||||||
 | 
					                name: getString(item.name, lang)
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    for (const [uniqueName, item] of Object.entries(ExportWeapons)) {
 | 
					    for (const [uniqueName, item] of Object.entries(ExportWeapons)) {
 | 
				
			||||||
        if (item.totalDamage !== 0) {
 | 
					        if (
 | 
				
			||||||
 | 
					            uniqueName.split("/")[4] == "OperatorAmplifiers" ||
 | 
				
			||||||
 | 
					            uniqueName.split("/")[5] == "SUModularSecondarySet1" ||
 | 
				
			||||||
 | 
					            uniqueName.split("/")[5] == "SUModularPrimarySet1" ||
 | 
				
			||||||
 | 
					            uniqueName.split("/")[5] == "InfKitGun" ||
 | 
				
			||||||
 | 
					            uniqueName.split("/")[5] == "HoverboardParts"
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            res.ModularParts.push({
 | 
				
			||||||
 | 
					                uniqueName,
 | 
				
			||||||
 | 
					                name: getString(item.name, lang)
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            if (uniqueName.split("/")[5] != "SentTrainingAmplifier") {
 | 
				
			||||||
 | 
					                res.miscitems.push({
 | 
				
			||||||
 | 
					                    uniqueName: "MiscItems:" + uniqueName,
 | 
				
			||||||
 | 
					                    name: getString(item.name, lang)
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else if (item.totalDamage !== 0) {
 | 
				
			||||||
            if (
 | 
					            if (
 | 
				
			||||||
                item.productCategory == "LongGuns" ||
 | 
					                item.productCategory == "LongGuns" ||
 | 
				
			||||||
                item.productCategory == "Pistols" ||
 | 
					                item.productCategory == "Pistols" ||
 | 
				
			||||||
                item.productCategory == "Melee"
 | 
					                item.productCategory == "Melee" ||
 | 
				
			||||||
 | 
					                item.productCategory == "SpaceGuns" ||
 | 
				
			||||||
 | 
					                item.productCategory == "SpaceMelee" ||
 | 
				
			||||||
 | 
					                item.productCategory == "SentinelWeapons"
 | 
				
			||||||
            ) {
 | 
					            ) {
 | 
				
			||||||
                res[item.productCategory].push({
 | 
					                res[item.productCategory].push({
 | 
				
			||||||
                    uniqueName,
 | 
					                    uniqueName,
 | 
				
			||||||
@ -102,15 +148,6 @@ const getItemListsController: RequestHandler = (req, response) => {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    response.json({
 | 
					    response.json({
 | 
				
			||||||
        warframes: Object.entries(ExportWarframes)
 | 
					 | 
				
			||||||
            .filter(([_uniqueName, warframe]) => warframe.productCategory == "Suits")
 | 
					 | 
				
			||||||
            .map(([uniqueName, warframe]) => {
 | 
					 | 
				
			||||||
                return {
 | 
					 | 
				
			||||||
                    uniqueName,
 | 
					 | 
				
			||||||
                    name: getString(warframe.name, lang),
 | 
					 | 
				
			||||||
                    exalted: warframe.exalted
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
            }),
 | 
					 | 
				
			||||||
        badItems,
 | 
					        badItems,
 | 
				
			||||||
        archonCrystalUpgrades,
 | 
					        archonCrystalUpgrades,
 | 
				
			||||||
        ...res
 | 
					        ...res
 | 
				
			||||||
 | 
				
			|||||||
@ -365,7 +365,7 @@ export const addSentinelWeapon = (
 | 
				
			|||||||
    typeName: string,
 | 
					    typeName: string,
 | 
				
			||||||
    inventoryChanges: IInventoryChanges
 | 
					    inventoryChanges: IInventoryChanges
 | 
				
			||||||
): void => {
 | 
					): void => {
 | 
				
			||||||
    const index = inventory.SentinelWeapons.push({ ItemType: typeName }) - 1;
 | 
					    const index = inventory.SentinelWeapons.push({ ItemType: typeName, XP: 0 }) - 1;
 | 
				
			||||||
    inventoryChanges.SentinelWeapons ??= [];
 | 
					    inventoryChanges.SentinelWeapons ??= [];
 | 
				
			||||||
    (inventoryChanges.SentinelWeapons as IEquipmentClient[]).push(
 | 
					    (inventoryChanges.SentinelWeapons as IEquipmentClient[]).push(
 | 
				
			||||||
        inventory.SentinelWeapons[index].toJSON<IEquipmentClient>()
 | 
					        inventory.SentinelWeapons[index].toJSON<IEquipmentClient>()
 | 
				
			||||||
 | 
				
			|||||||
@ -99,12 +99,12 @@
 | 
				
			|||||||
                        <div class="card mb-3" style="height: 400px;">
 | 
					                        <div class="card mb-3" style="height: 400px;">
 | 
				
			||||||
                            <h5 class="card-header">Warframes</h5>
 | 
					                            <h5 class="card-header">Warframes</h5>
 | 
				
			||||||
                            <div class="card-body overflow-auto">
 | 
					                            <div class="card-body overflow-auto">
 | 
				
			||||||
                                <form class="input-group mb-3" onsubmit="doAcquireWarframe();return false;">
 | 
					                                <form class="input-group mb-3" onsubmit="doAcquireEquipment('Suits');return false;">
 | 
				
			||||||
                                    <input class="form-control" id="warframe-to-acquire" list="datalist-warframes" />
 | 
					                                    <input class="form-control" id="acquire-type-Suits" list="datalist-Suits" />
 | 
				
			||||||
                                    <button class="btn btn-primary" type="submit">Add</button>
 | 
					                                    <button class="btn btn-primary" type="submit">Add</button>
 | 
				
			||||||
                                </form>
 | 
					                                </form>
 | 
				
			||||||
                                <table class="table table-hover w-100">
 | 
					                                <table class="table table-hover w-100">
 | 
				
			||||||
                                    <tbody id="warframe-list"></tbody>
 | 
					                                    <tbody id="Suits-list"></tbody>
 | 
				
			||||||
                                </table>
 | 
					                                </table>
 | 
				
			||||||
                            </div>
 | 
					                            </div>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
@ -113,7 +113,7 @@
 | 
				
			|||||||
                        <div class="card mb-3" style="height: 400px;">
 | 
					                        <div class="card mb-3" style="height: 400px;">
 | 
				
			||||||
                            <h5 class="card-header">Primary Weapons</h5>
 | 
					                            <h5 class="card-header">Primary Weapons</h5>
 | 
				
			||||||
                            <div class="card-body overflow-auto">
 | 
					                            <div class="card-body overflow-auto">
 | 
				
			||||||
                                <form class="input-group mb-3" onsubmit="doAcquireWeapon('LongGuns');return false;">
 | 
					                                <form class="input-group mb-3" onsubmit="doAcquireEquipment('LongGuns');return false;">
 | 
				
			||||||
                                    <input class="form-control" id="acquire-type-LongGuns" list="datalist-LongGuns" />
 | 
					                                    <input class="form-control" id="acquire-type-LongGuns" list="datalist-LongGuns" />
 | 
				
			||||||
                                    <button class="btn btn-primary" type="submit">Add</button>
 | 
					                                    <button class="btn btn-primary" type="submit">Add</button>
 | 
				
			||||||
                                </form>
 | 
					                                </form>
 | 
				
			||||||
@ -129,7 +129,7 @@
 | 
				
			|||||||
                        <div class="card mb-3" style="height: 400px;">
 | 
					                        <div class="card mb-3" style="height: 400px;">
 | 
				
			||||||
                            <h5 class="card-header">Secondary Weapons</h5>
 | 
					                            <h5 class="card-header">Secondary Weapons</h5>
 | 
				
			||||||
                            <div class="card-body overflow-auto">
 | 
					                            <div class="card-body overflow-auto">
 | 
				
			||||||
                                <form class="input-group mb-3" onsubmit="doAcquireWeapon('Pistols');return false;">
 | 
					                                <form class="input-group mb-3" onsubmit="doAcquireEquipment('Pistols');return false;">
 | 
				
			||||||
                                    <input class="form-control" id="acquire-type-Pistols" list="datalist-Pistols" />
 | 
					                                    <input class="form-control" id="acquire-type-Pistols" list="datalist-Pistols" />
 | 
				
			||||||
                                    <button class="btn btn-primary" type="submit">Add</button>
 | 
					                                    <button class="btn btn-primary" type="submit">Add</button>
 | 
				
			||||||
                                </form>
 | 
					                                </form>
 | 
				
			||||||
@ -143,7 +143,7 @@
 | 
				
			|||||||
                        <div class="card mb-3" style="height: 400px;">
 | 
					                        <div class="card mb-3" style="height: 400px;">
 | 
				
			||||||
                            <h5 class="card-header">Melee Weapons</h5>
 | 
					                            <h5 class="card-header">Melee Weapons</h5>
 | 
				
			||||||
                            <div class="card-body overflow-auto">
 | 
					                            <div class="card-body overflow-auto">
 | 
				
			||||||
                                <form class="input-group mb-3" onsubmit="doAcquireWeapon('Melee');return false;">
 | 
					                                <form class="input-group mb-3" onsubmit="doAcquireEquipment('Melee');return false;">
 | 
				
			||||||
                                    <input class="form-control" id="acquire-type-Melee" list="datalist-Melee" />
 | 
					                                    <input class="form-control" id="acquire-type-Melee" list="datalist-Melee" />
 | 
				
			||||||
                                    <button class="btn btn-primary" type="submit">Add</button>
 | 
					                                    <button class="btn btn-primary" type="submit">Add</button>
 | 
				
			||||||
                                </form>
 | 
					                                </form>
 | 
				
			||||||
@ -154,13 +154,123 @@
 | 
				
			|||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="row g-3">
 | 
				
			||||||
 | 
					                    <div class="col-lg-6">
 | 
				
			||||||
 | 
					                        <div class="card mb-3" style="height: 400px;">
 | 
				
			||||||
 | 
					                            <h5 class="card-header">Archwing</h5>
 | 
				
			||||||
 | 
					                            <div class="card-body overflow-auto">
 | 
				
			||||||
 | 
					                                <form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceSuits');return false;">
 | 
				
			||||||
 | 
					                                    <input class="form-control" id="acquire-type-SpaceSuits" list="datalist-SpaceSuits" />
 | 
				
			||||||
 | 
					                                    <button class="btn btn-primary" type="submit">Add</button>
 | 
				
			||||||
 | 
					                                </form>
 | 
				
			||||||
 | 
					                                <table class="table table-hover w-100">
 | 
				
			||||||
 | 
					                                    <tbody id="SpaceSuits-list"></tbody>
 | 
				
			||||||
 | 
					                                </table>
 | 
				
			||||||
 | 
					                            </div>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                    <div class="col-lg-6">
 | 
				
			||||||
 | 
					                        <div class="card mb-3" style="height: 400px;">
 | 
				
			||||||
 | 
					                            <h5 class="card-header">Archwing Primary Weapons</h5>
 | 
				
			||||||
 | 
					                            <div class="card-body overflow-auto">
 | 
				
			||||||
 | 
					                                <form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceGuns');return false;">
 | 
				
			||||||
 | 
					                                    <input class="form-control" id="acquire-type-SpaceGuns" list="datalist-SpaceGuns" />
 | 
				
			||||||
 | 
					                                    <button class="btn btn-primary" type="submit">Add</button>
 | 
				
			||||||
 | 
					                                </form>
 | 
				
			||||||
 | 
					                                <table class="table table-hover w-100">
 | 
				
			||||||
 | 
					                                    <tbody id="SpaceGuns-list"></tbody>
 | 
				
			||||||
 | 
					                                </table>
 | 
				
			||||||
 | 
					                            </div>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="row g-3">
 | 
				
			||||||
 | 
					                    <div class="col-lg-6">
 | 
				
			||||||
 | 
					                        <div class="card mb-3" style="height: 400px;">
 | 
				
			||||||
 | 
					                            <h5 class="card-header">Archwing Melee Weapons</h5>
 | 
				
			||||||
 | 
					                            <div class="card-body overflow-auto">
 | 
				
			||||||
 | 
					                                <form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceMelee');return false;">
 | 
				
			||||||
 | 
					                                    <input class="form-control" id="acquire-type-SpaceMelee" list="datalist-SpaceMelee" />
 | 
				
			||||||
 | 
					                                    <button class="btn btn-primary" type="submit">Add</button>
 | 
				
			||||||
 | 
					                                </form>
 | 
				
			||||||
 | 
					                                <table class="table table-hover w-100">
 | 
				
			||||||
 | 
					                                    <tbody id="SpaceMelee-list"></tbody>
 | 
				
			||||||
 | 
					                                </table>
 | 
				
			||||||
 | 
					                            </div>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                    <div class="col-lg-6">
 | 
				
			||||||
 | 
					                        <div class="card mb-3" style="height: 400px;">
 | 
				
			||||||
 | 
					                            <h5 class="card-header">Sentinel Weapons</h5>
 | 
				
			||||||
 | 
					                            <div class="card-body overflow-auto">
 | 
				
			||||||
 | 
					                                <form class="input-group mb-3" onsubmit="doAcquireEquipment('SentinelWeapons');return false;">
 | 
				
			||||||
 | 
					                                    <input class="form-control" id="acquire-type-SentinelWeapons" list="datalist-SentinelWeapons" />
 | 
				
			||||||
 | 
					                                    <button class="btn btn-primary" type="submit">Add</button>
 | 
				
			||||||
 | 
					                                </form>
 | 
				
			||||||
 | 
					                                <table class="table table-hover w-100">
 | 
				
			||||||
 | 
					                                    <tbody id="SentinelWeapons-list"></tbody>
 | 
				
			||||||
 | 
					                                </table>
 | 
				
			||||||
 | 
					                            </div>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="row g-3">
 | 
				
			||||||
 | 
					                    <div class="col-lg-6">
 | 
				
			||||||
 | 
					                        <div class="card mb-3" style="height: 400px;">
 | 
				
			||||||
 | 
					                            <h5 class="card-header">Sentinels</h5>
 | 
				
			||||||
 | 
					                            <div class="card-body overflow-auto">
 | 
				
			||||||
 | 
					                                <form class="input-group mb-3" onsubmit="doAcquireEquipment('Sentinels');return false;">
 | 
				
			||||||
 | 
					                                    <input class="form-control" id="acquire-type-Sentinels" list="datalist-Sentinels" />
 | 
				
			||||||
 | 
					                                    <button class="btn btn-primary" type="submit">Add</button>
 | 
				
			||||||
 | 
					                                </form>
 | 
				
			||||||
 | 
					                                <table class="table table-hover w-100">
 | 
				
			||||||
 | 
					                                    <tbody id="Sentinels-list"></tbody>
 | 
				
			||||||
 | 
					                                </table>
 | 
				
			||||||
 | 
					                            </div>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="row g-3">
 | 
				
			||||||
 | 
					                    <div class="col-lg-6">
 | 
				
			||||||
 | 
					                        <div class="card mb-3" style="height: 400px;">
 | 
				
			||||||
 | 
					                            <h5 class="card-header">Amps</h5>
 | 
				
			||||||
 | 
					                            <div class="card-body overflow-auto">
 | 
				
			||||||
 | 
					                                <table class="table table-hover w-100">
 | 
				
			||||||
 | 
					                                    <tbody id="OperatorAmps-list"></tbody>
 | 
				
			||||||
 | 
					                                </table>
 | 
				
			||||||
 | 
					                            </div>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                    <div class="col-lg-6">
 | 
				
			||||||
 | 
					                        <div class="card mb-3" style="height: 400px;">
 | 
				
			||||||
 | 
					                            <h5 class="card-header">K-Drives</h5>
 | 
				
			||||||
 | 
					                            <div class="card-body overflow-auto">
 | 
				
			||||||
 | 
					                                <table class="table table-hover w-100">
 | 
				
			||||||
 | 
					                                    <tbody id="Hoverboards-list"></tbody>
 | 
				
			||||||
 | 
					                                </table>
 | 
				
			||||||
 | 
					                            </div>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
                <div class="card mb-3">
 | 
					                <div class="card mb-3">
 | 
				
			||||||
                    <h5 class="card-header">Bulk Actions</h5>
 | 
					                    <h5 class="card-header">Bulk Actions</h5>
 | 
				
			||||||
                    <div class="card-body d-flex flex-wrap gap-2">
 | 
					                    <div class="card-body">
 | 
				
			||||||
                        <button class="btn btn-primary" onclick="addMissingWarframes();">Add Missing Warframes</button>
 | 
					                        <div class="mb-2 d-flex flex-wrap gap-2">
 | 
				
			||||||
                        <button class="btn btn-primary" onclick="addMissingWeapons();">Add Missing Weapons</button>
 | 
					                            <button class="btn btn-primary" onclick="addMissingEquipment(['Suits']);">Add Missing Warframes</button>
 | 
				
			||||||
                        <button class="btn btn-success" onclick="maxRankAllWarframes()">Max Rank All Warframes</button>
 | 
					                            <button class="btn btn-primary" onclick="addMissingEquipment(['Melee', 'LongGuns', 'Pistols']);">Add Missing Weapons</button>
 | 
				
			||||||
                        <button class="btn btn-success" onclick="maxRankAllWeapons()">Max Rank All Weapons</button>
 | 
					                            <button class="btn btn-primary" onclick="addMissingEquipment(['SpaceSuits']);">Add Missing Archwings</button>
 | 
				
			||||||
 | 
					                            <button class="btn btn-primary" onclick="addMissingEquipment(['SpaceGuns', 'SpaceMelee']);">Add Missing Archwing Weapons</button>
 | 
				
			||||||
 | 
					                            <button class="btn btn-primary" onclick="addMissingEquipment(['Sentinels']);">Add Missing Sentinels</button>
 | 
				
			||||||
 | 
					                            <button class="btn btn-primary" onclick="addMissingEquipment(['SentinelWeapons']);">Add Missing Sentinel Weapons</button>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                        <div class="mb-2 d-flex flex-wrap gap-2">
 | 
				
			||||||
 | 
					                            <button class="btn btn-success" onclick="maxRankAllEquipment(['Suits']);">Max Rank All Warframes</button>
 | 
				
			||||||
 | 
					                            <button class="btn btn-success" onclick="maxRankAllEquipment(['Melee', 'LongGuns', 'Pistols']);">Max Rank All Weapons</button>
 | 
				
			||||||
 | 
					                            <button class="btn btn-success" onclick="maxRankAllEquipment(['SpaceSuits']);">Max Rank All Archwings</button>
 | 
				
			||||||
 | 
					                            <button class="btn btn-success" onclick="maxRankAllEquipment(['SpaceGuns', 'SpaceMelee']);">Max Rank All Archwing Weapons</button>
 | 
				
			||||||
 | 
					                            <button class="btn btn-success" onclick="maxRankAllEquipment(['Sentinels']);">Max Rank All Sentinels</button>
 | 
				
			||||||
 | 
					                            <button class="btn btn-success" onclick="maxRankAllEquipment(['SentinelWeapons']);">Max Rank All Sentinel Weapons</button>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
@ -384,10 +494,16 @@
 | 
				
			|||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <datalist id="datalist-warframes"></datalist>
 | 
					    <datalist id="datalist-Suits"></datalist>
 | 
				
			||||||
 | 
					    <datalist id="datalist-SpaceSuits"></datalist>
 | 
				
			||||||
    <datalist id="datalist-LongGuns"></datalist>
 | 
					    <datalist id="datalist-LongGuns"></datalist>
 | 
				
			||||||
    <datalist id="datalist-Pistols"></datalist>
 | 
					    <datalist id="datalist-Pistols"></datalist>
 | 
				
			||||||
    <datalist id="datalist-Melee"></datalist>
 | 
					    <datalist id="datalist-Melee"></datalist>
 | 
				
			||||||
 | 
					    <datalist id="datalist-SpaceGuns"></datalist>
 | 
				
			||||||
 | 
					    <datalist id="datalist-SpaceMelee"></datalist>
 | 
				
			||||||
 | 
					    <datalist id="datalist-SentinelWeapons"></datalist>
 | 
				
			||||||
 | 
					    <datalist id="datalist-Sentinels"></datalist>
 | 
				
			||||||
 | 
					    <datalist id="datalist-ModularParts"></datalist>
 | 
				
			||||||
    <datalist id="datalist-miscitems"></datalist>
 | 
					    <datalist id="datalist-miscitems"></datalist>
 | 
				
			||||||
    <datalist id="datalist-mods">
 | 
					    <datalist id="datalist-mods">
 | 
				
			||||||
        <option data-key="/Lotus/Upgrades/Mods/Fusers/LegendaryModFuser" value="Legendary Core"></option>
 | 
					        <option data-key="/Lotus/Upgrades/Mods/Fusers/LegendaryModFuser" value="Legendary Core"></option>
 | 
				
			||||||
 | 
				
			|||||||
@ -149,6 +149,12 @@ function fetchItemList() {
 | 
				
			|||||||
                "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryBeam": { name: "Kitgun" },
 | 
					                "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryBeam": { name: "Kitgun" },
 | 
				
			||||||
                "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryShotgun": { name: "Kitgun" },
 | 
					                "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryShotgun": { name: "Kitgun" },
 | 
				
			||||||
                "/Lotus/Weapons/Ostron/Melee/LotusModularWeapon": { name: "Zaw" },
 | 
					                "/Lotus/Weapons/Ostron/Melee/LotusModularWeapon": { name: "Zaw" },
 | 
				
			||||||
 | 
					                "/Lotus/Weapons/Sentients/OperatorAmplifiers/SentTrainingAmplifier/OperatorTrainingAmpWeapon": {
 | 
				
			||||||
 | 
					                    name: "Mote Amp"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "/Lotus/Weapons/Sentients/OperatorAmplifiers/OperatorAmpWeapon": { name: "Amp" },
 | 
				
			||||||
 | 
					                "/Lotus/Weapons/Operator/Pistols/DrifterPistol/DrifterPistolPlayerWeapon": { name: "Sirocco" },
 | 
				
			||||||
 | 
					                "/Lotus/Types/Vehicles/Hoverboard/HoverboardSuit": { name: "K-Drive" },
 | 
				
			||||||
                // Missing in data sources
 | 
					                // Missing in data sources
 | 
				
			||||||
                "/Lotus/Upgrades/Mods/Fusers/LegendaryModFuser": { name: "Legendary Core" },
 | 
					                "/Lotus/Upgrades/Mods/Fusers/LegendaryModFuser": { name: "Legendary Core" },
 | 
				
			||||||
                "/Lotus/Upgrades/CosmeticEnhancers/Peculiars/CyoteMod": { name: "Traumatic Peculiar" }
 | 
					                "/Lotus/Upgrades/CosmeticEnhancers/Peculiars/CyoteMod": { name: "Traumatic Peculiar" }
 | 
				
			||||||
@ -188,84 +194,19 @@ function updateInventory() {
 | 
				
			|||||||
            window.didInitialInventoryUpdate = true;
 | 
					            window.didInitialInventoryUpdate = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Populate inventory route
 | 
					            // Populate inventory route
 | 
				
			||||||
            document.getElementById("warframe-list").innerHTML = "";
 | 
					            [
 | 
				
			||||||
            data.Suits.forEach(item => {
 | 
					                "Suits",
 | 
				
			||||||
                const tr = document.createElement("tr");
 | 
					                "SpaceSuits",
 | 
				
			||||||
                tr.setAttribute("data-item-type", item.ItemType);
 | 
					                "Sentinels",
 | 
				
			||||||
                {
 | 
					                "LongGuns",
 | 
				
			||||||
                    const td = document.createElement("td");
 | 
					                "Pistols",
 | 
				
			||||||
                    td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
 | 
					                "Melee",
 | 
				
			||||||
                    if (item.ItemName) {
 | 
					                "SpaceGuns",
 | 
				
			||||||
                        td.textContent = item.ItemName + " (" + td.textContent + ")";
 | 
					                "SpaceMelee",
 | 
				
			||||||
                    }
 | 
					                "SentinelWeapons",
 | 
				
			||||||
                    tr.appendChild(td);
 | 
					                "Hoverboards",
 | 
				
			||||||
                }
 | 
					                "OperatorAmps"
 | 
				
			||||||
                {
 | 
					            ].forEach(category => {
 | 
				
			||||||
                    const td = document.createElement("td");
 | 
					 | 
				
			||||||
                    td.classList = "text-end";
 | 
					 | 
				
			||||||
                    if (item.XP < 1_600_000) {
 | 
					 | 
				
			||||||
                        const a = document.createElement("a");
 | 
					 | 
				
			||||||
                        a.href = "#";
 | 
					 | 
				
			||||||
                        a.onclick = function (event) {
 | 
					 | 
				
			||||||
                            event.preventDefault();
 | 
					 | 
				
			||||||
                            addGearExp("Suits", item.ItemId.$oid, 1_600_000 - item.XP);
 | 
					 | 
				
			||||||
                            if ("exalted" in itemMap[item.ItemType]) {
 | 
					 | 
				
			||||||
                                for (const exaltedType of itemMap[item.ItemType].exalted) {
 | 
					 | 
				
			||||||
                                    const exaltedItem = data.SpecialItems.find(x => x.ItemType == exaltedType);
 | 
					 | 
				
			||||||
                                    if (exaltedItem) {
 | 
					 | 
				
			||||||
                                        const exaltedCap =
 | 
					 | 
				
			||||||
                                            itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000;
 | 
					 | 
				
			||||||
                                        if (exaltedItem.XP < exaltedCap) {
 | 
					 | 
				
			||||||
                                            addGearExp(
 | 
					 | 
				
			||||||
                                                "SpecialItems",
 | 
					 | 
				
			||||||
                                                exaltedItem.ItemId.$oid,
 | 
					 | 
				
			||||||
                                                exaltedCap - exaltedItem.XP
 | 
					 | 
				
			||||||
                                            );
 | 
					 | 
				
			||||||
                                        }
 | 
					 | 
				
			||||||
                                    }
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        };
 | 
					 | 
				
			||||||
                        a.title = "Make Rank 30";
 | 
					 | 
				
			||||||
                        a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`;
 | 
					 | 
				
			||||||
                        td.appendChild(a);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        const a = document.createElement("a");
 | 
					 | 
				
			||||||
                        a.href = "/webui/powersuit/" + item.ItemId.$oid;
 | 
					 | 
				
			||||||
                        a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M278.5 215.6L23 471c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l57-57h68c49.7 0 97.9-14.4 139-41c11.1-7.2 5.5-23-7.8-23c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l81-24.3c2.5-.8 4.8-2.1 6.7-4l22.4-22.4c10.1-10.1 2.9-27.3-11.3-27.3l-32.2 0c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l112-33.6c4-1.2 7.4-3.9 9.3-7.7C506.4 207.6 512 184.1 512 160c0-41-16.3-80.3-45.3-109.3l-5.5-5.5C432.3 16.3 393 0 352 0s-80.3 16.3-109.3 45.3L139 149C91 197 64 262.1 64 330v55.3L253.6 195.8c6.2-6.2 16.4-6.2 22.6 0c5.4 5.4 6.1 13.6 2.2 19.8z"/></svg>`;
 | 
					 | 
				
			||||||
                        td.appendChild(a);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        const a = document.createElement("a");
 | 
					 | 
				
			||||||
                        a.href = "#";
 | 
					 | 
				
			||||||
                        a.onclick = function (event) {
 | 
					 | 
				
			||||||
                            event.preventDefault();
 | 
					 | 
				
			||||||
                            const name = prompt("Enter new custom name:");
 | 
					 | 
				
			||||||
                            if (name !== null) {
 | 
					 | 
				
			||||||
                                renameGear("Suits", item.ItemId.$oid, name);
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        };
 | 
					 | 
				
			||||||
                        a.title = "Rename";
 | 
					 | 
				
			||||||
                        a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M0 80V229.5c0 17 6.7 33.3 18.7 45.3l176 176c25 25 65.5 25 90.5 0L418.7 317.3c25-25 25-65.5 0-90.5l-176-176c-12-12-28.3-18.7-45.3-18.7H48C21.5 32 0 53.5 0 80zm112 32a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>`;
 | 
					 | 
				
			||||||
                        td.appendChild(a);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        const a = document.createElement("a");
 | 
					 | 
				
			||||||
                        a.href = "#";
 | 
					 | 
				
			||||||
                        a.onclick = function (event) {
 | 
					 | 
				
			||||||
                            event.preventDefault();
 | 
					 | 
				
			||||||
                            disposeOfGear("Suits", item.ItemId.$oid);
 | 
					 | 
				
			||||||
                        };
 | 
					 | 
				
			||||||
                        a.title = "Remove";
 | 
					 | 
				
			||||||
                        a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>`;
 | 
					 | 
				
			||||||
                        td.appendChild(a);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    tr.appendChild(td);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                document.getElementById("warframe-list").appendChild(tr);
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            ["LongGuns", "Pistols", "Melee"].forEach(category => {
 | 
					 | 
				
			||||||
                document.getElementById(category + "-list").innerHTML = "";
 | 
					                document.getElementById(category + "-list").innerHTML = "";
 | 
				
			||||||
                data[category].forEach(item => {
 | 
					                data[category].forEach(item => {
 | 
				
			||||||
                    const tr = document.createElement("tr");
 | 
					                    const tr = document.createElement("tr");
 | 
				
			||||||
@ -276,22 +217,59 @@ function updateInventory() {
 | 
				
			|||||||
                        if (item.ItemName) {
 | 
					                        if (item.ItemName) {
 | 
				
			||||||
                            td.textContent = item.ItemName + " (" + td.textContent + ")";
 | 
					                            td.textContent = item.ItemName + " (" + td.textContent + ")";
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					                        if (item.ModularParts) {
 | 
				
			||||||
 | 
					                            td.textContent += " [";
 | 
				
			||||||
 | 
					                            item.ModularParts.forEach(part => {
 | 
				
			||||||
 | 
					                                td.textContent += " " + (itemMap[part]?.name ?? part) + ",";
 | 
				
			||||||
 | 
					                            });
 | 
				
			||||||
 | 
					                            td.textContent = td.textContent.slice(0, -1) + " ]";
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                        tr.appendChild(td);
 | 
					                        tr.appendChild(td);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        const td = document.createElement("td");
 | 
					                        const td = document.createElement("td");
 | 
				
			||||||
                        td.classList = "text-end";
 | 
					                        td.classList = "text-end";
 | 
				
			||||||
                        if (item.XP < 800_000) {
 | 
					                        const maxXP =
 | 
				
			||||||
 | 
					                            category === "Suits" ||
 | 
				
			||||||
 | 
					                            category === "SpaceSuits" ||
 | 
				
			||||||
 | 
					                            category === "Sentinels" ||
 | 
				
			||||||
 | 
					                            category === "Hoverboards"
 | 
				
			||||||
 | 
					                                ? 1_600_000
 | 
				
			||||||
 | 
					                                : 800_000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (item.XP < maxXP) {
 | 
				
			||||||
                            const a = document.createElement("a");
 | 
					                            const a = document.createElement("a");
 | 
				
			||||||
                            a.href = "#";
 | 
					                            a.href = "#";
 | 
				
			||||||
                            a.onclick = function (event) {
 | 
					                            a.onclick = function (event) {
 | 
				
			||||||
                                event.preventDefault();
 | 
					                                event.preventDefault();
 | 
				
			||||||
                                addGearExp(category, item.ItemId.$oid, 800_000 - item.XP);
 | 
					                                addGearExp(category, item.ItemId.$oid, maxXP - item.XP);
 | 
				
			||||||
 | 
					                                if ("exalted" in itemMap[item.ItemType]) {
 | 
				
			||||||
 | 
					                                    for (const exaltedType of itemMap[item.ItemType].exalted) {
 | 
				
			||||||
 | 
					                                        const exaltedItem = data.SpecialItems.find(x => x.ItemType == exaltedType);
 | 
				
			||||||
 | 
					                                        if (exaltedItem) {
 | 
				
			||||||
 | 
					                                            const exaltedCap =
 | 
				
			||||||
 | 
					                                                itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000;
 | 
				
			||||||
 | 
					                                            if (exaltedItem.XP < exaltedCap) {
 | 
				
			||||||
 | 
					                                                addGearExp(
 | 
				
			||||||
 | 
					                                                    "SpecialItems",
 | 
				
			||||||
 | 
					                                                    exaltedItem.ItemId.$oid,
 | 
				
			||||||
 | 
					                                                    exaltedCap - exaltedItem.XP
 | 
				
			||||||
 | 
					                                                );
 | 
				
			||||||
 | 
					                                            }
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
                            };
 | 
					                            };
 | 
				
			||||||
                            a.title = "Make Rank 30";
 | 
					                            a.title = "Make Rank 30";
 | 
				
			||||||
                            a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`;
 | 
					                            a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`;
 | 
				
			||||||
                            td.appendChild(a);
 | 
					                            td.appendChild(a);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					                        if (category == "Suits") {
 | 
				
			||||||
 | 
					                            const a = document.createElement("a");
 | 
				
			||||||
 | 
					                            a.href = "/webui/powersuit/" + item.ItemId.$oid;
 | 
				
			||||||
 | 
					                            a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M278.5 215.6L23 471c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l57-57h68c49.7 0 97.9-14.4 139-41c11.1-7.2 5.5-23-7.8-23c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l81-24.3c2.5-.8 4.8-2.1 6.7-4l22.4-22.4c10.1-10.1 2.9-27.3-11.3-27.3l-32.2 0c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l112-33.6c4-1.2 7.4-3.9 9.3-7.7C506.4 207.6 512 184.1 512 160c0-41-16.3-80.3-45.3-109.3l-5.5-5.5C432.3 16.3 393 0 352 0s-80.3 16.3-109.3 45.3L139 149C91 197 64 262.1 64 330v55.3L253.6 195.8c6.2-6.2 16.4-6.2 22.6 0c5.4 5.4 6.1 13.6 2.2 19.8z"/></svg>`;
 | 
				
			||||||
 | 
					                            td.appendChild(a);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            const a = document.createElement("a");
 | 
					                            const a = document.createElement("a");
 | 
				
			||||||
                            a.href = "#";
 | 
					                            a.href = "#";
 | 
				
			||||||
@ -524,35 +502,7 @@ function getKey(input) {
 | 
				
			|||||||
        ?.getAttribute("data-key");
 | 
					        ?.getAttribute("data-key");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function doAcquireWarframe() {
 | 
					function doAcquireEquipment(category) {
 | 
				
			||||||
    const uniqueName = getKey(document.getElementById("warframe-to-acquire"));
 | 
					 | 
				
			||||||
    if (!uniqueName) {
 | 
					 | 
				
			||||||
        $("#warframe-to-acquire").addClass("is-invalid").focus();
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    revalidateAuthz(() => {
 | 
					 | 
				
			||||||
        const req = $.post({
 | 
					 | 
				
			||||||
            url: "/custom/addItems?" + window.authz,
 | 
					 | 
				
			||||||
            contentType: "application/json",
 | 
					 | 
				
			||||||
            data: JSON.stringify([
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    type: "Powersuit",
 | 
					 | 
				
			||||||
                    internalName: uniqueName
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            ])
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        req.done(() => {
 | 
					 | 
				
			||||||
            document.getElementById("warframe-to-acquire").value = "";
 | 
					 | 
				
			||||||
            updateInventory();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$("input[list]").on("input", function () {
 | 
					 | 
				
			||||||
    $(this).removeClass("is-invalid");
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function doAcquireWeapon(category) {
 | 
					 | 
				
			||||||
    const uniqueName = getKey(document.getElementById("acquire-type-" + category));
 | 
					    const uniqueName = getKey(document.getElementById("acquire-type-" + category));
 | 
				
			||||||
    if (!uniqueName) {
 | 
					    if (!uniqueName) {
 | 
				
			||||||
        $("#acquire-type-" + category)
 | 
					        $("#acquire-type-" + category)
 | 
				
			||||||
@ -566,7 +516,7 @@ function doAcquireWeapon(category) {
 | 
				
			|||||||
            contentType: "application/json",
 | 
					            contentType: "application/json",
 | 
				
			||||||
            data: JSON.stringify([
 | 
					            data: JSON.stringify([
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    type: "Weapon",
 | 
					                    type: category,
 | 
				
			||||||
                    internalName: uniqueName
 | 
					                    internalName: uniqueName
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ])
 | 
					            ])
 | 
				
			||||||
@ -578,6 +528,10 @@ function doAcquireWeapon(category) {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$("input[list]").on("input", function () {
 | 
				
			||||||
 | 
					    $(this).removeClass("is-invalid");
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function dispatchAddItemsRequestsBatch(requests) {
 | 
					function dispatchAddItemsRequestsBatch(requests) {
 | 
				
			||||||
    revalidateAuthz(() => {
 | 
					    revalidateAuthz(() => {
 | 
				
			||||||
        const req = $.post({
 | 
					        const req = $.post({
 | 
				
			||||||
@ -591,12 +545,18 @@ function dispatchAddItemsRequestsBatch(requests) {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function addMissingWarframes() {
 | 
					function addMissingEquipment(categories) {
 | 
				
			||||||
    const requests = [];
 | 
					    const requests = [];
 | 
				
			||||||
    document.querySelectorAll("#datalist-warframes option").forEach(elm => {
 | 
					    categories.forEach(category => {
 | 
				
			||||||
        if (!document.querySelector("#warframe-list [data-item-type='" + elm.getAttribute("data-key") + "']")) {
 | 
					        document.querySelectorAll("#datalist-" + category + " option").forEach(elm => {
 | 
				
			||||||
            requests.push({ type: "Powersuit", internalName: elm.getAttribute("data-key") });
 | 
					            if (
 | 
				
			||||||
        }
 | 
					                !document.querySelector(
 | 
				
			||||||
 | 
					                    "#" + category + "-list [data-item-type='" + elm.getAttribute("data-key") + "']"
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					                requests.push({ type: category, internalName: elm.getAttribute("data-key") });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    if (
 | 
					    if (
 | 
				
			||||||
        requests.length != 0 &&
 | 
					        requests.length != 0 &&
 | 
				
			||||||
@ -606,91 +566,60 @@ function addMissingWarframes() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function maxRankAllWarframes() {
 | 
					function maxRankAllEquipment(categories) {
 | 
				
			||||||
    const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
 | 
					    const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    req.done(data => {
 | 
					    req.done(data => {
 | 
				
			||||||
        window.itemListPromise.then(itemMap => {
 | 
					        window.itemListPromise.then(itemMap => {
 | 
				
			||||||
            const batchData = { Suits: [], SpecialItems: [] };
 | 
					            const batchData = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            data.Suits.forEach(item => {
 | 
					            categories.forEach(category => {
 | 
				
			||||||
                if (item.XP < 1_600_000) {
 | 
					                data[category].forEach(item => {
 | 
				
			||||||
                    batchData.Suits.push({
 | 
					                    const maxXP =
 | 
				
			||||||
                        ItemId: { $oid: item.ItemId.$oid },
 | 
					                        category === "Suits" ||
 | 
				
			||||||
                        XP: 1_600_000 - item.XP
 | 
					                        category === "SpaceSuits" ||
 | 
				
			||||||
                    });
 | 
					                        category === "Sentinels" ||
 | 
				
			||||||
                }
 | 
					                        category === "Hoverboards"
 | 
				
			||||||
 | 
					                            ? 1_600_000
 | 
				
			||||||
 | 
					                            : 800_000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if ("exalted" in itemMap[item.ItemType]) {
 | 
					                    if (item.XP < maxXP) {
 | 
				
			||||||
                    for (const exaltedType of itemMap[item.ItemType].exalted) {
 | 
					                        if (!batchData[category]) {
 | 
				
			||||||
                        const exaltedItem = data.SpecialItems.find(x => x.ItemType == exaltedType);
 | 
					                            batchData[category] = [];
 | 
				
			||||||
                        if (exaltedItem) {
 | 
					                        }
 | 
				
			||||||
                            const exaltedCap = itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000;
 | 
					                        batchData[category].push({
 | 
				
			||||||
                            if (exaltedItem.XP < exaltedCap) {
 | 
					                            ItemId: { $oid: item.ItemId.$oid },
 | 
				
			||||||
                                batchData.SpecialItems.push({
 | 
					                            XP: maxXP
 | 
				
			||||||
                                    ItemId: { $oid: exaltedItem.ItemId.$oid },
 | 
					                        });
 | 
				
			||||||
                                    XP: exaltedCap
 | 
					                    }
 | 
				
			||||||
                                });
 | 
					                    if (category === "Suits") {
 | 
				
			||||||
 | 
					                        if ("exalted" in itemMap[item.ItemType]) {
 | 
				
			||||||
 | 
					                            for (const exaltedType of itemMap[item.ItemType].exalted) {
 | 
				
			||||||
 | 
					                                const exaltedItem = data["SpecialItems"].find(x => x.ItemType == exaltedType);
 | 
				
			||||||
 | 
					                                if (exaltedItem) {
 | 
				
			||||||
 | 
					                                    const exaltedCap = itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000;
 | 
				
			||||||
 | 
					                                    if (exaltedItem.XP < exaltedCap) {
 | 
				
			||||||
 | 
					                                        batchData["SpecialItems"].push({
 | 
				
			||||||
 | 
					                                            ItemId: { $oid: exaltedItem.ItemId.$oid },
 | 
				
			||||||
 | 
					                                            XP: exaltedCap
 | 
				
			||||||
 | 
					                                        });
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                });
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (batchData.Suits.length > 0 || batchData.SpecialItems.length > 0) {
 | 
					            if (Object.keys(batchData).length > 0) {
 | 
				
			||||||
                return sendBatchGearExp(batchData);
 | 
					                return sendBatchGearExp(batchData);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            alert("No Warframes to rank up.");
 | 
					            alert("No equipment to rank up.");
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function addMissingWeapons() {
 | 
					 | 
				
			||||||
    const requests = [];
 | 
					 | 
				
			||||||
    document
 | 
					 | 
				
			||||||
        .querySelectorAll("#datalist-LongGuns option, #datalist-Pistols option, #datalist-Melee option")
 | 
					 | 
				
			||||||
        .forEach(elm => {
 | 
					 | 
				
			||||||
            if (!document.querySelector("#weapon-list [data-item-type='" + elm.getAttribute("data-key") + "']")) {
 | 
					 | 
				
			||||||
                requests.push({ type: "Weapon", internalName: elm.getAttribute("data-key") });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    if (
 | 
					 | 
				
			||||||
        requests.length != 0 &&
 | 
					 | 
				
			||||||
        window.confirm("Are you sure you want to add " + requests.length + " items to your account?")
 | 
					 | 
				
			||||||
    ) {
 | 
					 | 
				
			||||||
        dispatchAddItemsRequestsBatch(requests);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function maxRankAllWeapons() {
 | 
					 | 
				
			||||||
    const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    req.done(data => {
 | 
					 | 
				
			||||||
        const batchData = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ["LongGuns", "Pistols", "Melee"].forEach(category => {
 | 
					 | 
				
			||||||
            data[category].forEach(item => {
 | 
					 | 
				
			||||||
                if (item.XP < 800_000) {
 | 
					 | 
				
			||||||
                    if (!batchData[category]) {
 | 
					 | 
				
			||||||
                        batchData[category] = [];
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    batchData[category].push({
 | 
					 | 
				
			||||||
                        ItemId: { $oid: item.ItemId.$oid },
 | 
					 | 
				
			||||||
                        XP: 800_000 - item.XP
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (Object.keys(batchData).length > 0) {
 | 
					 | 
				
			||||||
            return sendBatchGearExp(batchData);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        alert("No weapons to rank up.");
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function addGearExp(category, oid, xp) {
 | 
					function addGearExp(category, oid, xp) {
 | 
				
			||||||
    const data = {};
 | 
					    const data = {};
 | 
				
			||||||
    data[category] = [
 | 
					    data[category] = [
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user