diff --git a/src/controllers/api/nameWeaponController.ts b/src/controllers/api/nameWeaponController.ts
new file mode 100644
index 00000000..7543cbc4
--- /dev/null
+++ b/src/controllers/api/nameWeaponController.ts
@@ -0,0 +1,27 @@
+import { RequestHandler } from "express";
+import { getAccountIdForRequest } from "@/src/services/loginService";
+import { getInventory, updateCurrency } from "@/src/services/inventoryService";
+import { getJSONfromString } from "@/src/helpers/stringHelpers";
+import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
+
+interface INameWeaponRequest {
+ ItemName: string;
+}
+
+export const nameWeaponController: RequestHandler = async (req, res) => {
+ const accountId = await getAccountIdForRequest(req);
+ const inventory = await getInventory(accountId);
+ const body = getJSONfromString(req.body.toString()) as INameWeaponRequest;
+ const item = inventory[req.query.Category as string as TEquipmentKey].find(
+ item => item._id.toString() == (req.query.ItemId as string)
+ )!;
+ if (body.ItemName != "") {
+ item.ItemName = body.ItemName;
+ } else {
+ item.ItemName = undefined;
+ }
+ await inventory.save();
+ res.json({
+ InventoryChanges: await updateCurrency("webui" in req.query ? 0 : 15, true, accountId)
+ });
+};
diff --git a/src/controllers/api/upgradesController.ts b/src/controllers/api/upgradesController.ts
index 88c01dc7..25b548e6 100644
--- a/src/controllers/api/upgradesController.ts
+++ b/src/controllers/api/upgradesController.ts
@@ -1,7 +1,7 @@
import { RequestHandler } from "express";
import { IUpgradesRequest } from "@/src/types/requestTypes";
import { FocusSchool, IEquipmentDatabase } from "@/src/types/inventoryTypes/commonInventoryTypes";
-import { IMiscItem, IEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
+import { IMiscItem, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService";
@@ -28,7 +28,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
switch (operation.UpgradeRequirement) {
case "/Lotus/Types/Items/MiscItems/OrokinReactor":
case "/Lotus/Types/Items/MiscItems/OrokinCatalyst":
- for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) {
+ for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) {
if (item._id.toString() == payload.ItemId.$oid) {
item.Features ??= 0;
item.Features |= 1;
@@ -38,7 +38,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
break;
case "/Lotus/Types/Items/MiscItems/UtilityUnlocker":
case "/Lotus/Types/Items/MiscItems/WeaponUtilityUnlocker":
- for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) {
+ for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) {
if (item._id.toString() == payload.ItemId.$oid) {
item.Features ??= 0;
item.Features |= 2;
@@ -49,7 +49,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
case "/Lotus/Types/Items/MiscItems/WeaponPrimaryArcaneUnlocker":
case "/Lotus/Types/Items/MiscItems/WeaponSecondaryArcaneUnlocker":
case "/Lotus/Types/Items/MiscItems/WeaponMeleeArcaneUnlocker":
- for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) {
+ for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) {
if (item._id.toString() == payload.ItemId.$oid) {
item.Features ??= 0;
item.Features |= 32;
@@ -61,7 +61,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
case "/Lotus/Types/Items/MiscItems/FormaUmbra":
case "/Lotus/Types/Items/MiscItems/FormaAura":
case "/Lotus/Types/Items/MiscItems/FormaStance":
- for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) {
+ for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) {
if (item._id.toString() == payload.ItemId.$oid) {
item.XP = 0;
setSlotPolarity(item, operation.PolarizeSlot, operation.PolarizeValue);
@@ -72,7 +72,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
}
break;
case "/Lotus/Types/Items/MiscItems/ModSlotUnlocker":
- for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) {
+ for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) {
if (item._id.toString() == payload.ItemId.$oid) {
item.ModSlotPurchases ??= 0;
item.ModSlotPurchases += 1;
@@ -87,7 +87,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
}
break;
case "/Lotus/Types/Items/MiscItems/CustomizationSlotUnlocker":
- for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) {
+ for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) {
if (item._id.toString() == payload.ItemId.$oid) {
item.CustomizationSlotPurchases ??= 0;
item.CustomizationSlotPurchases += 1;
@@ -103,7 +103,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
break;
case "":
console.assert(operation.OperationType == "UOT_SWAP_POLARITY");
- for (const item of inventory[payload.ItemCategory as IEquipmentKey] as IEquipmentDatabase[]) {
+ for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) {
if (item._id.toString() == payload.ItemId.$oid) {
for (let i = 0; i != operation.PolarityRemap.length; ++i) {
if (operation.PolarityRemap[i].Slot != i) {
diff --git a/src/routes/api.ts b/src/routes/api.ts
index 2ed9bdcb..8a059bfe 100644
--- a/src/routes/api.ts
+++ b/src/routes/api.ts
@@ -55,6 +55,7 @@ import { getGuildDojoController } from "@/src/controllers/api/getGuildDojoContro
import { syndicateSacrificeController } from "../controllers/api/syndicateSacrificeController";
import { startDojoRecipeController } from "@/src/controllers/api/startDojoRecipeController";
import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController";
+import { nameWeaponController } from "@/src/controllers/api/nameWeaponController";
const apiRouter = express.Router();
@@ -120,5 +121,6 @@ apiRouter.post("/upgrades.php", upgradesController);
apiRouter.post("/guildTech.php", guildTechController);
apiRouter.post("/syndicateSacrifice.php", syndicateSacrificeController);
apiRouter.post("/startDojoRecipe.php", startDojoRecipeController);
+apiRouter.post("/nameWeapon.php", nameWeaponController);
export { apiRouter };
diff --git a/src/types/inventoryTypes/inventoryTypes.ts b/src/types/inventoryTypes/inventoryTypes.ts
index 4b4f589a..ec492353 100644
--- a/src/types/inventoryTypes/inventoryTypes.ts
+++ b/src/types/inventoryTypes/inventoryTypes.ts
@@ -59,7 +59,7 @@ export interface ITypeCount {
ItemCount: number;
}
-export type IEquipmentKey =
+export type TEquipmentKey =
| "Suits"
| "LongGuns"
| "Pistols"
diff --git a/static/webui/script.js b/static/webui/script.js
index 0475a730..6a9d525d 100644
--- a/static/webui/script.js
+++ b/static/webui/script.js
@@ -132,6 +132,9 @@ function updateInventory() {
{
const td = document.createElement("td");
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
+ if (item.ItemName) {
+ td.textContent = item.ItemName + " (" + td.textContent + ")";
+ }
tr.appendChild(td);
}
{
@@ -144,12 +147,21 @@ function updateInventory() {
event.preventDefault();
addGearExp("Suits", item.ItemId.$oid, 1_600_000 - item.XP);
};
- a.textContent = "Make Rank 30";
+ 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:");
+ renameGear("Suits", item.ItemId.$oid, name);
+ };
+ a.title = "Rename";
+ a.innerHTML = ``;
td.appendChild(a);
-
- const span = document.createElement("span");
- span.innerHTML = " · ";
- td.appendChild(span);
}
{
const a = document.createElement("a");
@@ -158,7 +170,8 @@ function updateInventory() {
event.preventDefault();
disposeOfGear("Suits", item.ItemId.$oid);
};
- a.textContent = "Remove";
+ a.title = "Remove";
+ a.innerHTML = ``;
td.appendChild(a);
}
tr.appendChild(td);
@@ -173,6 +186,9 @@ function updateInventory() {
{
const td = document.createElement("td");
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
+ if (item.ItemName) {
+ td.textContent = item.ItemName + " (" + td.textContent + ")";
+ }
tr.appendChild(td);
}
{
@@ -185,12 +201,21 @@ function updateInventory() {
event.preventDefault();
addGearExp(category, item.ItemId.$oid, 800_000 - item.XP);
};
- a.textContent = "Make Rank 30";
+ 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:");
+ renameGear(category, item.ItemId.$oid, name);
+ };
+ a.title = "Rename";
+ a.innerHTML = ``;
td.appendChild(a);
-
- const span = document.createElement("span");
- span.innerHTML = " · ";
- td.appendChild(span);
}
{
const a = document.createElement("a");
@@ -199,7 +224,8 @@ function updateInventory() {
event.preventDefault();
disposeOfGear(category, item.ItemId.$oid);
};
- a.textContent = "Remove";
+ a.title = "Remove";
+ a.innerHTML = ``;
td.appendChild(a);
}
tr.appendChild(td);
@@ -241,14 +267,10 @@ function updateInventory() {
})
);
a.target = "_blank";
- a.textContent = "View Stats";
+ a.title = "View Stats";
+ a.innerHTML = ``;
td.appendChild(a);
}
- {
- const span = document.createElement("span");
- span.innerHTML = " · ";
- td.appendChild(span);
- }
{
const a = document.createElement("a");
a.href = "#";
@@ -256,7 +278,8 @@ function updateInventory() {
event.preventDefault();
disposeOfGear("Upgrades", item.ItemId.$oid);
};
- a.textContent = "Remove";
+ a.title = "Remove";
+ a.innerHTML = ``;
td.appendChild(a);
}
tr.appendChild(td);
@@ -282,12 +305,9 @@ function updateInventory() {
event.preventDefault();
setFingerprint(item.ItemType, item.ItemId, { lvl: maxRank });
};
- a.textContent = "Max Rank";
+ a.title = "Max Rank";
+ a.innerHTML = ``;
td.appendChild(a);
-
- const span = document.createElement("span");
- span.innerHTML = " · ";
- td.appendChild(span);
}
{
const a = document.createElement("a");
@@ -296,7 +316,8 @@ function updateInventory() {
event.preventDefault();
disposeOfGear("Upgrades", item.ItemId.$oid);
};
- a.textContent = "Remove";
+ a.title = "Remove";
+ a.innerHTML = ``;
td.appendChild(a);
}
tr.appendChild(td);
@@ -327,14 +348,10 @@ function updateInventory() {
event.preventDefault();
setFingerprint(item.ItemType, item.LastAdded, { lvl: maxRank });
};
- a.textContent = "Max Rank";
+ a.title = "Max Rank";
+ a.innerHTML = ``;
td.appendChild(a);
}
- {
- const span = document.createElement("span");
- span.innerHTML = " · ";
- td.appendChild(span);
- }
{
const a = document.createElement("a");
a.href = "#";
@@ -342,7 +359,8 @@ function updateInventory() {
event.preventDefault();
disposeOfItems("Upgrades", item.ItemType, item.ItemCount);
};
- a.textContent = "Remove";
+ a.title = "Remove";
+ a.innerHTML = ``;
td.appendChild(a);
}
tr.appendChild(td);
@@ -432,6 +450,20 @@ function addGearExp(category, oid, xp) {
});
}
+function renameGear(category, oid, name) {
+ revalidateAuthz(() => {
+ $.post({
+ url: "/api/nameWeapon.php?" + window.authz + "&Category=" + category + "&ItemId=" + oid + "&webui=1",
+ contentType: "text/plain",
+ data: JSON.stringify({
+ ItemName: name
+ })
+ }).done(function () {
+ updateInventory();
+ });
+ });
+}
+
function disposeOfGear(category, oid) {
const data = {
SellCurrency: "SC_RegularCredits",
diff --git a/static/webui/style.css b/static/webui/style.css
index 119d4fd2..341588cd 100644
--- a/static/webui/style.css
+++ b/static/webui/style.css
@@ -20,3 +20,10 @@ body:not(.logged-in) .nav-item.dropdown,
body:not(.logged-in) #refresh-note {
display: none;
}
+
+td.text-end > a > svg {
+ fill: currentColor;
+ height: 1em;
+ margin-left: 0.5em;
+ margin-bottom: 4px; /* to centre the icon */
+}