From 9ea061fdb3048ba8554ce6ff30a9dcde9207d79d Mon Sep 17 00:00:00 2001 From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Date: Sat, 29 Mar 2025 19:38:25 +0100 Subject: [PATCH 1/4] feat(webui): adding modular K-Drives and Amps --- .../custom/addModularEquipmentController.ts | 20 +++++ .../custom/getItemListsController.ts | 4 +- src/routes/custom.ts | 4 +- static/webui/index.html | 22 +++++- static/webui/script.js | 79 +++++++++++++++++++ 5 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 src/controllers/custom/addModularEquipmentController.ts diff --git a/src/controllers/custom/addModularEquipmentController.ts b/src/controllers/custom/addModularEquipmentController.ts new file mode 100644 index 00000000..39a12b24 --- /dev/null +++ b/src/controllers/custom/addModularEquipmentController.ts @@ -0,0 +1,20 @@ +import { getAccountIdForRequest } from "@/src/services/loginService"; +import { getInventory, addEquipment, occupySlot, productCategoryToInventoryBin } from "@/src/services/inventoryService"; +import { RequestHandler } from "express"; +import { modularWeaponTypes } from "@/src/helpers/modularWeaponHelper"; + +export const addModularEquipmentController: RequestHandler = async (req, res) => { + const accountId = await getAccountIdForRequest(req); + const request = req.body as IAddModularEquipmentRequest; + const inventory = await getInventory(accountId); + const category = modularWeaponTypes[request.ItemType]; + addEquipment(inventory, category, request.ItemType, request.ModularParts); + occupySlot(inventory, productCategoryToInventoryBin(category)!, true); + await inventory.save(); + res.end(); +}; + +interface IAddModularEquipmentRequest { + ItemType: string; + ModularParts: string[]; +} diff --git a/src/controllers/custom/getItemListsController.ts b/src/controllers/custom/getItemListsController.ts index accbac1c..dc81ef07 100644 --- a/src/controllers/custom/getItemListsController.ts +++ b/src/controllers/custom/getItemListsController.ts @@ -25,6 +25,7 @@ interface ListedItem { fusionLimit?: number; exalted?: string[]; badReason?: "starter" | "frivolous" | "notraw"; + partType?: string; } const relicQualitySuffixes: Record = { @@ -79,7 +80,8 @@ const getItemListsController: RequestHandler = (req, response) => { ) { res.ModularParts.push({ uniqueName, - name: getString(item.name, lang) + name: getString(item.name, lang), + partType: item.partType }); if (uniqueName.split("/")[5] != "SentTrainingAmplifier") { res.miscitems.push({ diff --git a/src/routes/custom.ts b/src/routes/custom.ts index 20f19a59..16359226 100644 --- a/src/routes/custom.ts +++ b/src/routes/custom.ts @@ -13,8 +13,9 @@ import { unlockAllIntrinsicsController } from "@/src/controllers/custom/unlockAl import { createAccountController } from "@/src/controllers/custom/createAccountController"; import { createMessageController } from "@/src/controllers/custom/createMessageController"; -import { addCurrencyController } from "../controllers/custom/addCurrencyController"; +import { addCurrencyController } from "@/src/controllers/custom/addCurrencyController"; import { addItemsController } from "@/src/controllers/custom/addItemsController"; +import { addModularEquipmentController } from "@/src/controllers/custom/addModularEquipmentController"; import { addXpController } from "@/src/controllers/custom/addXpController"; import { importController } from "@/src/controllers/custom/importController"; @@ -39,6 +40,7 @@ customRouter.post("/createAccount", createAccountController); customRouter.post("/createMessage", createMessageController); customRouter.post("/addCurrency", addCurrencyController); customRouter.post("/addItems", addItemsController); +customRouter.post("/addModularEquipment", addModularEquipmentController); customRouter.post("/addXp", addXpController); customRouter.post("/import", importController); customRouter.post("/manageQuests", manageQuestsController); diff --git a/static/webui/index.html b/static/webui/index.html index f88820e9..2183cdd6 100644 --- a/static/webui/index.html +++ b/static/webui/index.html @@ -299,6 +299,12 @@
+
+ + + + +
@@ -309,6 +315,13 @@
+
+ + + + + +
@@ -604,7 +617,6 @@ - @@ -613,6 +625,14 @@ + + + + + + + + diff --git a/static/webui/script.js b/static/webui/script.js index 8697414e..ec036756 100644 --- a/static/webui/script.js +++ b/static/webui/script.js @@ -233,6 +233,30 @@ function fetchItemList() { if (type == "Syndicates" && item.uniqueName.startsWith("RadioLegion")) { item.name += " (" + item.uniqueName + ")"; } + if (type == "ModularParts") { + const supportedModularParts = [ + "LWPT_HB_DECK", + "LWPT_HB_ENGINE", + "LWPT_HB_FRONT", + "LWPT_HB_JET", + "LWPT_AMP_OCULUS", + "LWPT_AMP_CORE", + "LWPT_AMP_BRACE" + ]; + if (supportedModularParts.includes(item.partType)) { + const option = document.createElement("option"); + option.setAttribute("data-key", item.uniqueName); + option.value = item.name; + document + .getElementById("datalist-" + type + "-" + item.partType.slice(5)) + .appendChild(option); + } else { + const option = document.createElement("option"); + option.setAttribute("data-key", item.uniqueName); + option.value = item.name; + document.getElementById("datalist-" + type).appendChild(option); + } + } if (item.badReason != "notraw") { const option = document.createElement("option"); option.setAttribute("data-key", item.uniqueName); @@ -622,6 +646,61 @@ function doAcquireEquipment(category) { }); } +function doAcquireModularEquipment(category) { + let ItemType; + let requiredParts; + let ModularParts = []; + switch (category) { + case "HoverBoards": + ItemType = "/Lotus/Types/Vehicles/Hoverboard/HoverboardSuit"; + requiredParts = ["HB_DECK", "HB_ENGINE", "HB_FRONT", "HB_JET"]; + break; + case "OperatorAmps": + ItemType = "/Lotus/Weapons/Sentients/OperatorAmplifiers/OperatorAmpWeapon"; + requiredParts = ["AMP_OCULUS", "AMP_CORE", "AMP_BRACE"]; + break; + } + requiredParts.forEach(part => { + const partName = getKey(document.getElementById("acquire-type-" + category + "-" + part)); + if (partName) { + ModularParts.push(partName); + } + }); + if (ModularParts.length != requiredParts.length) { + let isFirstPart = true; + requiredParts.forEach(part => { + const partSelector = document.getElementById("acquire-type-" + category + "-" + part); + if (!getKey(partSelector)) { + if (isFirstPart) { + isFirstPart = false; + $("#acquire-type-" + category + "-" + part) + .addClass("is-invalid") + .focus(); + } else { + $("#acquire-type-" + category + "-" + part).addClass("is-invalid"); + } + } + }); + } else { + revalidateAuthz(() => { + const req = $.post({ + url: "/custom/addModularEquipment?" + window.authz, + contentType: "application/json", + data: JSON.stringify({ + ItemType, + ModularParts + }) + }); + req.done(() => { + requiredParts.forEach(part => { + document.getElementById("acquire-type-" + category + "-" + part).value = ""; + }); + updateInventory(); + }); + }); + } +} + $("input[list]").on("input", function () { $(this).removeClass("is-invalid"); }); -- 2.47.2 From 62dd3c04b36970e371c22f534cea0de933617b45 Mon Sep 17 00:00:00 2001 From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Date: Sat, 29 Mar 2025 20:07:16 +0100 Subject: [PATCH 2/4] inventory projection for addModularEquipment --- src/controllers/custom/addModularEquipmentController.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/controllers/custom/addModularEquipmentController.ts b/src/controllers/custom/addModularEquipmentController.ts index 39a12b24..5e09902b 100644 --- a/src/controllers/custom/addModularEquipmentController.ts +++ b/src/controllers/custom/addModularEquipmentController.ts @@ -6,10 +6,11 @@ import { modularWeaponTypes } from "@/src/helpers/modularWeaponHelper"; export const addModularEquipmentController: RequestHandler = async (req, res) => { const accountId = await getAccountIdForRequest(req); const request = req.body as IAddModularEquipmentRequest; - const inventory = await getInventory(accountId); const category = modularWeaponTypes[request.ItemType]; + const inventoryBin = productCategoryToInventoryBin(category)!; + const inventory = await getInventory(accountId, `${category} ${inventoryBin}`); addEquipment(inventory, category, request.ItemType, request.ModularParts); - occupySlot(inventory, productCategoryToInventoryBin(category)!, true); + occupySlot(inventory, inventoryBin, true); await inventory.save(); res.end(); }; -- 2.47.2 From 93abfdddf512197b55290be16dff22cc35ebf6ff Mon Sep 17 00:00:00 2001 From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Date: Sun, 30 Mar 2025 00:19:43 +0100 Subject: [PATCH 3/4] sirocco and zaw support --- static/webui/index.html | 18 +++++++++-- static/webui/script.js | 68 +++++++++++++++++++++++++++++++++++------ 2 files changed, 74 insertions(+), 12 deletions(-) diff --git a/static/webui/index.html b/static/webui/index.html index 2183cdd6..dcb2539c 100644 --- a/static/webui/index.html +++ b/static/webui/index.html @@ -193,10 +193,15 @@
-
+
+
@@ -299,11 +304,14 @@
-
+ + + +
+ @@ -625,6 +633,7 @@ + @@ -633,6 +642,9 @@ + + + diff --git a/static/webui/script.js b/static/webui/script.js index ec036756..ebcb3ca2 100644 --- a/static/webui/script.js +++ b/static/webui/script.js @@ -185,6 +185,21 @@ function fetchItemList() { name: loc("code_traumaticPeculiar") }); + // Add modular weapons + data.OperatorAmps ??= []; + data.OperatorAmps.push({ + uniqueName: "/Lotus/Weapons/Operator/Pistols/DrifterPistol/DrifterPistolPlayerWeapon", + name: loc("code_sirocco") + }); + data.OperatorAmps.push({ + uniqueName: "/Lotus/Weapons/Sentients/OperatorAmplifiers/OperatorAmpWeapon", + name: loc("code_amp") + }); + data.Melee.push({ + uniqueName: "/Lotus/Weapons/Ostron/Melee/LotusModularWeapon", + name: loc("code_zaw") + }); + const itemMap = { // Generics for rivens "/Lotus/Weapons/Tenno/Archwing/Primary/ArchGun": { name: loc("code_archgun") }, @@ -201,14 +216,9 @@ function fetchItemList() { "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondary": { name: loc("code_kitgun") }, "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryBeam": { name: loc("code_kitgun") }, "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryShotgun": { name: loc("code_kitgun") }, - "/Lotus/Weapons/Ostron/Melee/LotusModularWeapon": { name: loc("code_zaw") }, "/Lotus/Weapons/Sentients/OperatorAmplifiers/SentTrainingAmplifier/OperatorTrainingAmpWeapon": { name: loc("code_moteAmp") }, - "/Lotus/Weapons/Sentients/OperatorAmplifiers/OperatorAmpWeapon": { name: loc("code_amp") }, - "/Lotus/Weapons/Operator/Pistols/DrifterPistol/DrifterPistolPlayerWeapon": { - name: loc("code_sirocco") - }, "/Lotus/Types/Vehicles/Hoverboard/HoverboardSuit": { name: loc("code_kDrive") } }; for (const [type, items] of Object.entries(data)) { @@ -241,7 +251,10 @@ function fetchItemList() { "LWPT_HB_JET", "LWPT_AMP_OCULUS", "LWPT_AMP_CORE", - "LWPT_AMP_BRACE" + "LWPT_AMP_BRACE", + "LWPT_BLADE", + "LWPT_HILT", + "LWPT_HILT_WEIGHT" ]; if (supportedModularParts.includes(item.partType)) { const option = document.createElement("option"); @@ -646,8 +659,7 @@ function doAcquireEquipment(category) { }); } -function doAcquireModularEquipment(category) { - let ItemType; +function doAcquireModularEquipment(category, ItemType) { let requiredParts; let ModularParts = []; switch (category) { @@ -656,9 +668,11 @@ function doAcquireModularEquipment(category) { requiredParts = ["HB_DECK", "HB_ENGINE", "HB_FRONT", "HB_JET"]; break; case "OperatorAmps": - ItemType = "/Lotus/Weapons/Sentients/OperatorAmplifiers/OperatorAmpWeapon"; requiredParts = ["AMP_OCULUS", "AMP_CORE", "AMP_BRACE"]; break; + case "Melee": + requiredParts = ["BLADE", "HILT", "HILT_WEIGHT"]; + break; } requiredParts.forEach(part => { const partName = getKey(document.getElementById("acquire-type-" + category + "-" + part)); @@ -692,6 +706,11 @@ function doAcquireModularEquipment(category) { }) }); req.done(() => { + const mainInput = document.getElementById("acquire-type-" + category); + if (mainInput) { + mainInput.value = ""; + document.getElementById("modular-" + category).style.display = "none"; + } requiredParts.forEach(part => { document.getElementById("acquire-type-" + category + "-" + part).value = ""; }); @@ -1299,3 +1318,34 @@ function toast(text) { toast.appendChild(div); new bootstrap.Toast(document.querySelector(".toast-container").appendChild(toast)).show(); } + +function handleModularSelection(category) { + const modularWeapons = [ + "/Lotus/Weapons/Sentients/OperatorAmplifiers/OperatorAmpWeapon", + "/Lotus/Weapons/Ostron/Melee/LotusModularWeapon" + ]; + const itemType = getKey(document.getElementById("acquire-type-" + category)); + + if (modularWeapons.includes(itemType)) { + doAcquireModularEquipment(category, itemType); + } else { + doAcquireEquipment(category); + } +} +{ + const modularWeapons = [ + "/Lotus/Weapons/Sentients/OperatorAmplifiers/OperatorAmpWeapon", + "/Lotus/Weapons/Ostron/Melee/LotusModularWeapon" + ]; + const supportedModularInventoryCategory = ["OperatorAmps", "Melee"]; + supportedModularInventoryCategory.forEach(inventoryCategory => { + document.getElementById("acquire-type-" + inventoryCategory).addEventListener("input", function () { + const modularFields = document.getElementById("modular-" + inventoryCategory); + if (modularWeapons.includes(getKey(this))) { + modularFields.style.display = ""; + } else { + modularFields.style.display = "none"; + } + }); + }); +} -- 2.47.2 From 9c0bf6146d7778485d515f4a04eb667259133062 Mon Sep 17 00:00:00 2001 From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Date: Sun, 30 Mar 2025 01:18:27 +0100 Subject: [PATCH 4/4] get sirocco from itemLists --- src/controllers/custom/getItemListsController.ts | 4 +++- static/webui/script.js | 5 ----- static/webui/translations/de.js | 1 - static/webui/translations/en.js | 1 - static/webui/translations/fr.js | 1 - static/webui/translations/ru.js | 1 - static/webui/translations/zh.js | 1 - 7 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/controllers/custom/getItemListsController.ts b/src/controllers/custom/getItemListsController.ts index dc81ef07..196f59ca 100644 --- a/src/controllers/custom/getItemListsController.ts +++ b/src/controllers/custom/getItemListsController.ts @@ -51,6 +51,7 @@ const getItemListsController: RequestHandler = (req, response) => { res.MechSuits = []; res.miscitems = []; res.Syndicates = []; + res.OperatorAmps = []; for (const [uniqueName, item] of Object.entries(ExportWarframes)) { res[item.productCategory].push({ uniqueName, @@ -96,7 +97,8 @@ const getItemListsController: RequestHandler = (req, response) => { item.productCategory == "Melee" || item.productCategory == "SpaceGuns" || item.productCategory == "SpaceMelee" || - item.productCategory == "SentinelWeapons" + item.productCategory == "SentinelWeapons" || + item.productCategory == "OperatorAmps" ) { res[item.productCategory].push({ uniqueName, diff --git a/static/webui/script.js b/static/webui/script.js index ebcb3ca2..4e9119fc 100644 --- a/static/webui/script.js +++ b/static/webui/script.js @@ -186,11 +186,6 @@ function fetchItemList() { }); // Add modular weapons - data.OperatorAmps ??= []; - data.OperatorAmps.push({ - uniqueName: "/Lotus/Weapons/Operator/Pistols/DrifterPistol/DrifterPistolPlayerWeapon", - name: loc("code_sirocco") - }); data.OperatorAmps.push({ uniqueName: "/Lotus/Weapons/Sentients/OperatorAmplifiers/OperatorAmpWeapon", name: loc("code_amp") diff --git a/static/webui/translations/de.js b/static/webui/translations/de.js index 4aa6d562..09040ddb 100644 --- a/static/webui/translations/de.js +++ b/static/webui/translations/de.js @@ -15,7 +15,6 @@ dict = { code_zaw: `Zaw`, code_moteAmp: `Anfangsverstärker`, code_amp: `Verstärker`, - code_sirocco: `Sirocco`, code_kDrive: `K-Drive`, code_legendaryCore: `Legendärer Kern`, code_traumaticPeculiar: `Kuriose Mod: Traumatisch`, diff --git a/static/webui/translations/en.js b/static/webui/translations/en.js index ee197c9e..750468db 100644 --- a/static/webui/translations/en.js +++ b/static/webui/translations/en.js @@ -14,7 +14,6 @@ dict = { code_zaw: `Zaw`, code_moteAmp: `Mote Amp`, code_amp: `Amp`, - code_sirocco: `Sirocco`, code_kDrive: `K-Drive`, code_legendaryCore: `Legendary Core`, code_traumaticPeculiar: `Traumatic Peculiar`, diff --git a/static/webui/translations/fr.js b/static/webui/translations/fr.js index c51695bd..c1d8830d 100644 --- a/static/webui/translations/fr.js +++ b/static/webui/translations/fr.js @@ -15,7 +15,6 @@ dict = { code_zaw: `Zaw`, code_moteAmp: `Amplificateur Faible`, code_amp: `Amplificateur`, - code_sirocco: `Sirocco`, code_kDrive: `K-Drive`, code_legendaryCore: `Coeur Légendaire`, code_traumaticPeculiar: `Traumatisme Atypique`, diff --git a/static/webui/translations/ru.js b/static/webui/translations/ru.js index 5af34072..7fda4ed1 100644 --- a/static/webui/translations/ru.js +++ b/static/webui/translations/ru.js @@ -15,7 +15,6 @@ dict = { code_zaw: `Зо`, code_moteAmp: `Пылинка`, code_amp: `Усилитель`, - code_sirocco: `Сирокко`, code_kDrive: `К-Драйв`, code_legendaryCore: `Легендарное ядро`, code_traumaticPeculiar: `Травмирующая Странность`, diff --git a/static/webui/translations/zh.js b/static/webui/translations/zh.js index dbcf45d0..de64de75 100644 --- a/static/webui/translations/zh.js +++ b/static/webui/translations/zh.js @@ -15,7 +15,6 @@ dict = { code_zaw: `自制近战`, code_moteAmp: `微尘增幅器`, code_amp: `增幅器`, - code_sirocco: `赤风`, code_kDrive: `K式悬浮板`, code_legendaryCore: `传奇核心`, code_traumaticPeculiar: `创伤怪奇`, -- 2.47.2