From 1184d182444329192cda6646fb9e8a84306edcc4 Mon Sep 17 00:00:00 2001 From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Date: Sat, 28 Dec 2024 10:13:46 +0100 Subject: [PATCH 1/8] feat: exalted weapons on webui --- src/controllers/api/sellController.ts | 5 + src/controllers/custom/addItemController.ts | 6 +- .../custom/getItemListsController.ts | 34 +++-- src/helpers/customHelpers/addItemHelpers.ts | 3 +- src/services/inventoryService.ts | 24 ++-- src/types/sellTypes.ts | 1 + static/webui/index.html | 12 ++ static/webui/script.js | 118 ++++++++++++++++++ 8 files changed, 182 insertions(+), 21 deletions(-) diff --git a/src/controllers/api/sellController.ts b/src/controllers/api/sellController.ts index 530d37cc..d2959e6d 100644 --- a/src/controllers/api/sellController.ts +++ b/src/controllers/api/sellController.ts @@ -45,6 +45,11 @@ export const sellController: RequestHandler = async (req, res) => { inventory.Melee.pull({ _id: sellItem.String }); }); } + if (payload.Items.SpecialItems) { + payload.Items.SpecialItems.forEach(sellItem => { + inventory.SpecialItems.pull({ _id: sellItem.String }); + }); + } if (payload.Items.Consumables) { const consumablesChanges = []; for (const sellItem of payload.Items.Consumables) { diff --git a/src/controllers/custom/addItemController.ts b/src/controllers/custom/addItemController.ts index ea5fd535..d9976632 100644 --- a/src/controllers/custom/addItemController.ts +++ b/src/controllers/custom/addItemController.ts @@ -1,7 +1,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService"; import { ItemType, toAddItemRequest } from "@/src/helpers/customHelpers/addItemHelpers"; import { getWeaponType } from "@/src/services/itemDataService"; -import { addPowerSuit, addEquipment } from "@/src/services/inventoryService"; +import { addPowerSuit, addEquipment, addSpecialItem } from "@/src/services/inventoryService"; import { RequestHandler } from "express"; const addItemController: RequestHandler = async (req, res) => { @@ -18,6 +18,10 @@ const addItemController: RequestHandler = async (req, res) => { const weapon = await addEquipment(weaponType, request.InternalName, accountId); res.json(weapon); break; + case ItemType.SpecialItem: + const specialItem = await addSpecialItem(request.InternalName, accountId); + res.json(specialItem); + break; default: res.status(400).json({ error: "something went wrong" }); break; diff --git a/src/controllers/custom/getItemListsController.ts b/src/controllers/custom/getItemListsController.ts index e3fa95a1..5db843f2 100644 --- a/src/controllers/custom/getItemListsController.ts +++ b/src/controllers/custom/getItemListsController.ts @@ -1,10 +1,11 @@ import { RequestHandler } from "express"; -import { getDict, getItemName, getString } from "@/src/services/itemDataService"; +import { getDict, getExalted, getItemName, getString } from "@/src/services/itemDataService"; import { ExportArcanes, ExportGear, ExportRecipes, ExportResources, + ExportSentinels, ExportUpgrades, ExportWarframes, ExportWeapons @@ -15,12 +16,34 @@ interface ListedItem { uniqueName: string; name: string; fusionLimit?: number; + exalted?: { uniqueName: string; name: string }[]; } const getItemListsController: RequestHandler = (req, res) => { const lang = getDict(typeof req.query.lang == "string" ? req.query.lang : "en"); const weapons = []; const miscitems = []; + const warframes = []; + for (const [uniqueName, item] of Object.entries(ExportWarframes)) { + if (item.productCategory == "Suits") { + const warframe: ListedItem = { + uniqueName, + name: getString(item.name, lang) + }; + const exalted = getExalted(uniqueName); + if (exalted) { + warframe.exalted = []; + exalted.forEach(element => { + const exalted = ExportWeapons[element] || ExportSentinels[element]; + warframe.exalted?.push({ + uniqueName: element, + name: getString(exalted.name, lang) + }); + }); + } + warframes.push(warframe); + } + } for (const [uniqueName, item] of Object.entries(ExportWeapons)) { if (item.productCategory !== "OperatorAmps") { if (item.totalDamage !== 0) { @@ -84,14 +107,7 @@ const getItemListsController: RequestHandler = (req, res) => { } res.json({ - warframes: Object.entries(ExportWarframes) - .filter(([_uniqueName, warframe]) => warframe.productCategory == "Suits") - .map(([uniqueName, warframe]) => { - return { - uniqueName, - name: getString(warframe.name, lang) - }; - }), + warframes, weapons, miscitems, mods, diff --git a/src/helpers/customHelpers/addItemHelpers.ts b/src/helpers/customHelpers/addItemHelpers.ts index 5ce2378f..112fd2e6 100644 --- a/src/helpers/customHelpers/addItemHelpers.ts +++ b/src/helpers/customHelpers/addItemHelpers.ts @@ -2,7 +2,8 @@ import { isString } from "@/src/helpers/general"; export enum ItemType { Powersuit = "Powersuit", - Weapon = "Weapon" + Weapon = "Weapon", + SpecialItem = "SpecialItem" } export const isItemType = (itemType: string): itemType is ItemType => { diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index 73acd669..a901b5e4 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -29,7 +29,7 @@ import { import { logger } from "@/src/utils/logger"; import { getWeaponType, getExalted } from "@/src/services/itemDataService"; import { ISyndicateSacrifice, ISyndicateSacrificeResponse } from "../types/syndicateTypes"; -import { IEquipmentClient, IItemConfig } from "../types/inventoryTypes/commonInventoryTypes"; +import { EquipmentFeatures, IEquipmentClient, IItemConfig } from "../types/inventoryTypes/commonInventoryTypes"; import { ExportArcanes, ExportCustoms, @@ -433,15 +433,19 @@ export const addMechSuit = async (mechsuitName: string, accountId: string) => { export const addSpecialItem = async (itemName: string, accountId: string) => { const inventory = await getInventory(accountId); - const specialItemIndex = inventory.SpecialItems.push({ - ItemType: itemName, - Configs: [], - Features: 1, - UpgradeVer: 101, - XP: 0 - }); - const changedInventory = await inventory.save(); - return changedInventory.SpecialItems[specialItemIndex - 1].toJSON(); + // According to wiki there is one exalted item per suit type, so we check if we don't already have that item + if (!inventory.SpecialItems.length || inventory.SpecialItems.some(obj => obj.ItemType !== itemName)) { + const specialItemIndex = inventory.SpecialItems.push({ + ItemType: itemName, + Configs: [], + Features: EquipmentFeatures.DOUBLE_CAPACITY, + UpgradeVer: 101, + XP: 0 + }); + const changedInventory = await inventory.save(); + return changedInventory.SpecialItems[specialItemIndex - 1].toJSON(); + } + return; }; export const addSpaceSuit = async (spacesuitName: string, accountId: string) => { diff --git a/src/types/sellTypes.ts b/src/types/sellTypes.ts index cd9fb2dd..fe0174f5 100644 --- a/src/types/sellTypes.ts +++ b/src/types/sellTypes.ts @@ -7,6 +7,7 @@ export interface ISellRequest { Consumables?: ISellItem[]; Recipes?: ISellItem[]; Upgrades?: ISellItem[]; + SpecialItems?: ISellItem[]; }; SellPrice: number; SellCurrency: diff --git a/static/webui/index.html b/static/webui/index.html index 416d1978..b99c3aae 100644 --- a/static/webui/index.html +++ b/static/webui/index.html @@ -126,6 +126,10 @@
+ Note: Changes made here will only be reflected in-game when the game re-downloads your + inventory. Visiting the navigation should be the easiest way to trigger that. +
diff --git a/static/webui/script.js b/static/webui/script.js
index 56736c38..c1e7b922 100644
--- a/static/webui/script.js
+++ b/static/webui/script.js
@@ -449,6 +449,124 @@ function updateInventory() {
$("#powersuit-route .text-body-secondary").text("");
}
+ document.getElementById("exalted-list").innerHTML = "";
+ document.getElementById("exalted-list").closest(".card").style = "";
+
+ const exaltedWeapons = itemMap[item.ItemType].exalted;
+ if (exaltedWeapons) {
+ const specialItems = exaltedWeapons
+ .map(element => {
+ const specialItem = data.SpecialItems.find(x => x.ItemType == element.uniqueName);
+ if (specialItem) {
+ return {
+ ...specialItem,
+ name: element.name
+ };
+ }
+ return undefined;
+ })
+ .filter(item => item !== undefined);
+
+ specialItems.forEach(item => {
+ const tr = document.createElement("tr");
+ {
+ const td = document.createElement("td");
+ td.textContent = item?.name ?? item.ItemType;
+ if (item.ItemName) {
+ td.textContent = item.ItemName + " (" + td.textContent + ")";
+ }
+ tr.appendChild(td);
+ }
+ {
+ 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("SpecialItems", item.ItemId.$oid, 1_600_000 - item.XP);
+ };
+ a.title = "Make Rank 30";
+ a.innerHTML = ``;
+ 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("SpecialItems", item.ItemId.$oid, name);
+ }
+ };
+ a.title = "Rename";
+ a.innerHTML = ``;
+ td.appendChild(a);
+ }
+ {
+ const a = document.createElement("a");
+ a.href = "#";
+ a.onclick = function (event) {
+ event.preventDefault();
+ disposeOfGear("SpecialItems", item.ItemId.$oid);
+ };
+ a.title = "Remove";
+ a.innerHTML = ``;
+ td.appendChild(a);
+ }
+ tr.appendChild(td);
+ }
+ document.getElementById("exalted-list").appendChild(tr);
+ });
+
+ const missingItems = exaltedWeapons.filter(
+ element => !data.SpecialItems.some(x => x.ItemType === element.uniqueName)
+ );
+ if (missingItems) {
+ missingItems.forEach(item => {
+ const tr = document.createElement("tr");
+ {
+ const td = document.createElement("td");
+ td.textContent = item?.name ?? item.uniqueName;
+ tr.appendChild(td);
+ }
+ {
+ const td = document.createElement("td");
+ td.classList = "text-end";
+ {
+ const a = document.createElement("a");
+ a.href = "#";
+ a.onclick = function (event) {
+ event.preventDefault();
+ revalidateAuthz(() => {
+ const req = $.post({
+ url: "/custom/addItem?" + window.authz,
+ contentType: "application/json",
+ data: JSON.stringify({
+ type: "SpecialItem",
+ internalName: item.uniqueName
+ })
+ });
+ req.done(() => {
+ updateInventory();
+ });
+ });
+ };
+ a.title = "Add";
+ a.innerHTML = ``;
+ td.appendChild(a);
+ }
+ tr.appendChild(td);
+ }
+ document.getElementById("exalted-list").appendChild(tr);
+ });
+ }
+ } else {
+ document.getElementById("exalted-list").closest(".card").style.display = "none";
+ }
+
const uniqueUpgrades = {};
(item.ArchonCrystalUpgrades ?? []).forEach(upgrade => {
uniqueUpgrades[upgrade.UpgradeType] ??= 0;
--
2.47.2
From 603c98e348062b0db9b4e8dd6c2a3d153a6d63d5 Mon Sep 17 00:00:00 2001
From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Date: Sat, 28 Dec 2024 10:39:06 +0100
Subject: [PATCH 2/8] Update inventoryService.ts
---
src/services/inventoryService.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts
index a901b5e4..8ed90575 100644
--- a/src/services/inventoryService.ts
+++ b/src/services/inventoryService.ts
@@ -434,7 +434,7 @@ export const addMechSuit = async (mechsuitName: string, accountId: string) => {
export const addSpecialItem = async (itemName: string, accountId: string) => {
const inventory = await getInventory(accountId);
// According to wiki there is one exalted item per suit type, so we check if we don't already have that item
- if (!inventory.SpecialItems.length || inventory.SpecialItems.some(obj => obj.ItemType !== itemName)) {
+ if (inventory.SpecialItems.length && inventory.SpecialItems.some(obj => obj.ItemType !== itemName)) {
const specialItemIndex = inventory.SpecialItems.push({
ItemType: itemName,
Configs: [],
--
2.47.2
From c3e10a3e0e77d3178ad8a4ed413d418f1c5bf7ef Mon Sep 17 00:00:00 2001
From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Date: Sun, 29 Dec 2024 01:16:36 +0100
Subject: [PATCH 3/8] clarify comment
---
src/services/inventoryService.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts
index 8ed90575..526f96ad 100644
--- a/src/services/inventoryService.ts
+++ b/src/services/inventoryService.ts
@@ -433,8 +433,8 @@ export const addMechSuit = async (mechsuitName: string, accountId: string) => {
export const addSpecialItem = async (itemName: string, accountId: string) => {
const inventory = await getInventory(accountId);
- // According to wiki there is one exalted item per suit type, so we check if we don't already have that item
- if (inventory.SpecialItems.length && inventory.SpecialItems.some(obj => obj.ItemType !== itemName)) {
+ // According to wiki exalted items unique for suit type, so we check if we don't already have that item
+ if (!inventory.SpecialItems.some(obj => obj.ItemType === itemName)) {
const specialItemIndex = inventory.SpecialItems.push({
ItemType: itemName,
Configs: [],
--
2.47.2
From b2ecd93bd697aeeac0e4f7a84d0a5d1daa01f748 Mon Sep 17 00:00:00 2001
From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Date: Sun, 29 Dec 2024 04:02:04 +0100
Subject: [PATCH 4/8] remove ability to sell/add missing exalted items
---
src/controllers/api/sellController.ts | 5 ---
src/types/sellTypes.ts | 1 -
static/webui/script.js | 62 +++------------------------
3 files changed, 6 insertions(+), 62 deletions(-)
diff --git a/src/controllers/api/sellController.ts b/src/controllers/api/sellController.ts
index d2959e6d..530d37cc 100644
--- a/src/controllers/api/sellController.ts
+++ b/src/controllers/api/sellController.ts
@@ -45,11 +45,6 @@ export const sellController: RequestHandler = async (req, res) => {
inventory.Melee.pull({ _id: sellItem.String });
});
}
- if (payload.Items.SpecialItems) {
- payload.Items.SpecialItems.forEach(sellItem => {
- inventory.SpecialItems.pull({ _id: sellItem.String });
- });
- }
if (payload.Items.Consumables) {
const consumablesChanges = [];
for (const sellItem of payload.Items.Consumables) {
diff --git a/src/types/sellTypes.ts b/src/types/sellTypes.ts
index fe0174f5..cd9fb2dd 100644
--- a/src/types/sellTypes.ts
+++ b/src/types/sellTypes.ts
@@ -7,7 +7,6 @@ export interface ISellRequest {
Consumables?: ISellItem[];
Recipes?: ISellItem[];
Upgrades?: ISellItem[];
- SpecialItems?: ISellItem[];
};
SellPrice: number;
SellCurrency:
diff --git a/static/webui/script.js b/static/webui/script.js
index c1e7b922..68ed9724 100644
--- a/static/webui/script.js
+++ b/static/webui/script.js
@@ -480,12 +480,16 @@ function updateInventory() {
{
const td = document.createElement("td");
td.classList = "text-end";
- if (item.XP < 1_600_000) {
+
+ const targetXP = item.ItemType.startsWith("/Lotus/Powersuits/Khora/Kavat/")
+ ? 900_000
+ : 450_000;
+ if (item.XP < targetXP) {
const a = document.createElement("a");
a.href = "#";
a.onclick = function (event) {
event.preventDefault();
- addGearExp("SpecialItems", item.ItemId.$oid, 1_600_000 - item.XP);
+ addGearExp("SpecialItems", item.ItemId.$oid, targetXP - item.XP);
};
a.title = "Make Rank 30";
a.innerHTML = ``;
@@ -505,64 +509,10 @@ function updateInventory() {
a.innerHTML = ``;
td.appendChild(a);
}
- {
- const a = document.createElement("a");
- a.href = "#";
- a.onclick = function (event) {
- event.preventDefault();
- disposeOfGear("SpecialItems", item.ItemId.$oid);
- };
- a.title = "Remove";
- a.innerHTML = ``;
- td.appendChild(a);
- }
tr.appendChild(td);
}
document.getElementById("exalted-list").appendChild(tr);
});
-
- const missingItems = exaltedWeapons.filter(
- element => !data.SpecialItems.some(x => x.ItemType === element.uniqueName)
- );
- if (missingItems) {
- missingItems.forEach(item => {
- const tr = document.createElement("tr");
- {
- const td = document.createElement("td");
- td.textContent = item?.name ?? item.uniqueName;
- tr.appendChild(td);
- }
- {
- const td = document.createElement("td");
- td.classList = "text-end";
- {
- const a = document.createElement("a");
- a.href = "#";
- a.onclick = function (event) {
- event.preventDefault();
- revalidateAuthz(() => {
- const req = $.post({
- url: "/custom/addItem?" + window.authz,
- contentType: "application/json",
- data: JSON.stringify({
- type: "SpecialItem",
- internalName: item.uniqueName
- })
- });
- req.done(() => {
- updateInventory();
- });
- });
- };
- a.title = "Add";
- a.innerHTML = ``;
- td.appendChild(a);
- }
- tr.appendChild(td);
- }
- document.getElementById("exalted-list").appendChild(tr);
- });
- }
} else {
document.getElementById("exalted-list").closest(".card").style.display = "none";
}
--
2.47.2
From d8e4b0f2f467f6b04703972690e4e680fa14ea94 Mon Sep 17 00:00:00 2001
From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Date: Sun, 29 Dec 2024 04:11:58 +0100
Subject: [PATCH 5/8] Update addItemController.ts
---
src/controllers/custom/addItemController.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/controllers/custom/addItemController.ts b/src/controllers/custom/addItemController.ts
index d9976632..ac9a2a92 100644
--- a/src/controllers/custom/addItemController.ts
+++ b/src/controllers/custom/addItemController.ts
@@ -19,7 +19,7 @@ const addItemController: RequestHandler = async (req, res) => {
res.json(weapon);
break;
case ItemType.SpecialItem:
- const specialItem = await addSpecialItem(request.InternalName, accountId);
+ const specialItem = await addSpecialItem(request.InternalName, accountId, {});
res.json(specialItem);
break;
default:
--
2.47.2
From 3e831aafb0f70a404778024c4191668af4d34f2b Mon Sep 17 00:00:00 2001
From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Date: Sun, 29 Dec 2024 04:14:09 +0100
Subject: [PATCH 6/8] Update addItemController.ts
---
src/controllers/custom/addItemController.ts | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/controllers/custom/addItemController.ts b/src/controllers/custom/addItemController.ts
index ac9a2a92..8a1a2d49 100644
--- a/src/controllers/custom/addItemController.ts
+++ b/src/controllers/custom/addItemController.ts
@@ -18,10 +18,6 @@ const addItemController: RequestHandler = async (req, res) => {
const weapon = await addEquipment(weaponType, request.InternalName, accountId);
res.json(weapon);
break;
- case ItemType.SpecialItem:
- const specialItem = await addSpecialItem(request.InternalName, accountId, {});
- res.json(specialItem);
- break;
default:
res.status(400).json({ error: "something went wrong" });
break;
--
2.47.2
From 9e0e84cac66e7c3279ef0144270475c6e43a9d0d Mon Sep 17 00:00:00 2001
From: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Date: Sun, 29 Dec 2024 04:16:19 +0100
Subject: [PATCH 7/8] lint fix
---
src/controllers/custom/addItemController.ts | 2 +-
src/services/inventoryService.ts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/controllers/custom/addItemController.ts b/src/controllers/custom/addItemController.ts
index 8a1a2d49..ea5fd535 100644
--- a/src/controllers/custom/addItemController.ts
+++ b/src/controllers/custom/addItemController.ts
@@ -1,7 +1,7 @@
import { getAccountIdForRequest } from "@/src/services/loginService";
import { ItemType, toAddItemRequest } from "@/src/helpers/customHelpers/addItemHelpers";
import { getWeaponType } from "@/src/services/itemDataService";
-import { addPowerSuit, addEquipment, addSpecialItem } from "@/src/services/inventoryService";
+import { addPowerSuit, addEquipment } from "@/src/services/inventoryService";
import { RequestHandler } from "express";
const addItemController: RequestHandler = async (req, res) => {
diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts
index 5f18f4f2..423be170 100644
--- a/src/services/inventoryService.ts
+++ b/src/services/inventoryService.ts
@@ -29,7 +29,7 @@ import {
import { logger } from "@/src/utils/logger";
import { getWeaponType, getExalted } from "@/src/services/itemDataService";
import { ISyndicateSacrifice, ISyndicateSacrificeResponse } from "../types/syndicateTypes";
-import { EquipmentFeatures, IEquipmentClient, IItemConfig } from "../types/inventoryTypes/commonInventoryTypes";
+import { IEquipmentClient, IItemConfig } from "../types/inventoryTypes/commonInventoryTypes";
import {
ExportArcanes,
ExportCustoms,
--
2.47.2
From b0c3e725f86b93eaeb05b64ab081c309ffa8276c Mon Sep 17 00:00:00 2001
From: Sainan