返回提交历史
Added
src/controllers/custom/abilityOverrideController.ts
+33
-0
Modified
src/controllers/custom/getItemListsController.ts
+17
-1
Modified
src/routes/custom.ts
+2
-0
Modified
static/webui/index.html
+8
-0
Modified
static/webui/script.js
+138
-0
Modified
static/webui/translations/de.js
+4
-0
Modified
static/webui/translations/en.js
+4
-0
Modified
static/webui/translations/es.js
+4
-0
Modified
static/webui/translations/fr.js
+4
-0
Modified
static/webui/translations/ru.js
+4
-0
Modified
static/webui/translations/zh.js
+4
-0
XFEstudio/XFESpaceNinjaServer
feat(webui): ability overrides (#2558)
Closes #851 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2558 Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com> Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
b62e3269
代码差异
11 个文件
+222
-1
@@ -0,0 +1,33 @@
1
import { getInventory } from "@/src/services/inventoryService";
2
import { getAccountIdForRequest } from "@/src/services/loginService";
3
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
4
import { RequestHandler } from "express";
5
6
export const abilityOverrideController: RequestHandler = async (req, res) => {
7
const accountId = await getAccountIdForRequest(req);
8
const request = req.body as IAbilityOverrideRequest;
9
if (request.category === "Suits") {
10
const inventory = await getInventory(accountId, request.category);
11
const item = inventory[request.category].id(request.oid);
12
if (item) {
13
if (request.action == "set") {
14
item.Configs[request.configIndex].AbilityOverride = request.AbilityOverride;
15
} else {
16
item.Configs[request.configIndex].AbilityOverride = undefined;
17
}
18
await inventory.save();
19
}
20
}
21
res.end();
22
};
23
24
interface IAbilityOverrideRequest {
25
category: TEquipmentKey;
26
oid: string;
27
action: "set" | "remove";
28
configIndex: number;
29
AbilityOverride: {
30
Ability: string;
31
Index: number;
32
};
33
}
@@ -1,6 +1,7 @@
1
1
import { RequestHandler } from "express";
2
2
import { getDict, getItemName, getString } from "@/src/services/itemDataService";
3
3
import {
4
ExportAbilities,
4
5
ExportArcanes,
5
6
ExportAvionics,
6
7
ExportBoosters,
@@ -57,6 +58,7 @@ interface ItemLists {
57
58
mods: ListedItem[];
58
59
Boosters: ListedItem[];
59
60
VarziaOffers: ListedItem[];
61
Abilities: ListedItem[];
60
62
//circuitGameModes: ListedItem[];
61
63
}
62
64
@@ -94,7 +96,8 @@ const getItemListsController: RequestHandler = (req, response) => {
94
96
EvolutionProgress: [],
95
97
mods: [],
96
98
Boosters: [],
97
VarziaOffers: []
99
VarziaOffers: [],
100
Abilities: []
98
101
/*circuitGameModes: [
99
102
{
100
103
uniqueName: "Survival",
@@ -132,6 +135,12 @@ const getItemListsController: RequestHandler = (req, response) => {
132
135
name: getString(item.name, lang),
133
136
exalted: item.exalted
134
137
});
138
item.abilities.forEach(ability => {
139
res.Abilities.push({
140
uniqueName: ability.uniqueName,
141
name: getString(ability.name || uniqueName, lang)
142
});
143
});
135
144
}
136
145
for (const [uniqueName, item] of Object.entries(ExportSentinels)) {
137
146
if (item.productCategory == "Sentinels" || item.productCategory == "KubrowPets") {
@@ -348,6 +357,13 @@ const getItemListsController: RequestHandler = (req, response) => {
348
357
});
349
358
}
350
359
360
for (const [uniqueName, ability] of Object.entries(ExportAbilities)) {
361
res.Abilities.push({
362
uniqueName,
363
name: getString(ability.name || uniqueName, lang)
364
});
365
}
366
351
367
response.json(res);
352
368
};
353
369
@@ -15,6 +15,7 @@ import { webuiFileChangeDetectedController } from "@/src/controllers/custom/webu
15
15
import { completeAllMissionsController } from "@/src/controllers/custom/completeAllMissionsController";
16
16
import { addMissingHelminthBlueprintsController } from "@/src/controllers/custom/addMissingHelminthBlueprintsController";
17
17
18
import { abilityOverrideController } from "@/src/controllers/custom/abilityOverrideController";
18
19
import { createAccountController } from "@/src/controllers/custom/createAccountController";
19
20
import { createMessageController } from "@/src/controllers/custom/createMessageController";
20
21
import { addCurrencyController } from "@/src/controllers/custom/addCurrencyController";
@@ -47,6 +48,7 @@ customRouter.get("/webuiFileChangeDetected", webuiFileChangeDetectedController);
47
48
customRouter.get("/completeAllMissions", completeAllMissionsController);
48
49
customRouter.get("/addMissingHelminthBlueprints", addMissingHelminthBlueprintsController);
49
50
51
customRouter.post("/abilityOverride", abilityOverrideController);
50
52
customRouter.post("/createAccount", createAccountController);
51
53
customRouter.post("/createMessage", createMessageController);
52
54
customRouter.post("/addCurrency", addCurrencyController);
@@ -460,6 +460,13 @@
460
460
<h3 id="detailedView-loading" class="mb-0" data-loc="general_loading"></h3>
461
461
<h3 id="detailedView-title" class="mb-0"></h3>
462
462
<p class="text-body-secondary"></p>
463
<div id="loadout-card" class="card mb-3 d-none">
464
<h5 class="card-header" data-loc="detailedView_loadoutLabel"></h5>
465
<div class="card-body">
466
<ul class="nav nav-tabs" id="loadoutTabs"></ul>
467
<div class="tab-content mt-3" id="loadoutTabsContent"></div>
468
</div>
469
</div>
463
470
<div id="archonShards-card" class="card mb-3 d-none">
464
471
<h5 class="card-header" data-loc="detailedView_archonShardsLabel"></h5>
465
472
<div class="card-body">
@@ -1073,6 +1080,7 @@
1073
1080
<datalist id="datalist-ModularParts-KUBROW_ANTIGEN"></datalist>
1074
1081
<datalist id="datalist-ModularParts-KUBROW_MUTAGEN"></datalist>
1075
1082
<datalist id="datalist-Boosters"></datalist>
1083
<datalist id="datalist-Abilities"></datalist>
1076
1084
<datalist id="datalist-circuitGameModes">
1077
1085
<option>Survival</option>
1078
1086
<option>VoidFlood</option>
@@ -1241,6 +1241,117 @@ function updateInventory() {
1241
1241
document.getElementById("dv-invigoration-offensive").value = OffensiveUpgrade;
1242
1242
document.getElementById("dv-invigoration-defensive").value = DefensiveUpgrade;
1243
1243
document.getElementById("dv-invigoration-expiry").value = UpgradesExpiry;
1244
1245
{
1246
document.getElementById("loadout-card").classList.remove("d-none");
1247
const maxModConfigNum = Math.min(2 + (item.ModSlotPurchases ?? 0), 5);
1248
1249
const configs = item.Configs ?? [];
1250
1251
const loadoutTabs = document.getElementById("loadoutTabs");
1252
const loadoutTabsContent = document.getElementById("loadoutTabsContent");
1253
loadoutTabs.innerHTML = "";
1254
loadoutTabsContent.innerHTML = "";
1255
for (let i = 0; i <= maxModConfigNum; i++) {
1256
const config = configs[i] ?? {};
1257
1258
{
1259
const li = document.createElement("li");
1260
li.classList.add("nav-item");
1261
1262
const button = document.createElement("button");
1263
button.classList.add("nav-link");
1264
if (i === 0) button.classList.add("active");
1265
button.id = `config${i}-tab`;
1266
button.setAttribute("data-bs-toggle", "tab");
1267
button.setAttribute("data-bs-target", `#config${i}`);
1268
button.innerHTML = config.Name?.trim() || String.fromCharCode(65 + i);
1269
1270
li.appendChild(button);
1271
loadoutTabs.appendChild(li);
1272
}
1273
1274
{
1275
const tabDiv = document.createElement("div");
1276
tabDiv.classList = "tab-pane";
1277
if (i === 0) tabDiv.classList.add("show", "active");
1278
1279
tabDiv.id = `config${i}`;
1280
1281
{
1282
const abilityOverrideForm = document.createElement("form");
1283
abilityOverrideForm.classList = "form-group mt-2";
1284
abilityOverrideForm.setAttribute(
1285
"onsubmit",
1286
`handleAbilityOverride(event, ${i});return false;`
1287
);
1288
1289
const abilityOverrideFormLabel = document.createElement("label");
1290
abilityOverrideFormLabel.setAttribute("data-loc", "abilityOverride_label");
1291
abilityOverrideFormLabel.innerHTML = loc("abilityOverride_label");
1292
abilityOverrideFormLabel.classList = "form-label";
1293
abilityOverrideFormLabel.setAttribute("for", "abilityOverride-ability");
1294
abilityOverrideForm.appendChild(abilityOverrideFormLabel);
1295
1296
const abilityOverrideInputGroup = document.createElement("div");
1297
abilityOverrideInputGroup.classList = "input-group";
1298
abilityOverrideForm.appendChild(abilityOverrideInputGroup);
1299
1300
const abilityOverrideInput = document.createElement("input");
1301
abilityOverrideInput.id = "abilityOverride-ability";
1302
abilityOverrideInput.classList = "form-control";
1303
abilityOverrideInput.setAttribute("list", "datalist-Abilities");
1304
if (config.AbilityOverride) {
1305
const datalist = document.getElementById("datalist-Abilities");
1306
const options = Array.from(datalist.options);
1307
abilityOverrideInput.value = options.find(
1308
option =>
1309
config.AbilityOverride.Ability == option.getAttribute("data-key")
1310
).value;
1311
}
1312
abilityOverrideInputGroup.appendChild(abilityOverrideInput);
1313
1314
const abilityOverrideOnSlot = document.createElement("span");
1315
abilityOverrideOnSlot.classList = "input-group-text";
1316
abilityOverrideOnSlot.setAttribute("data-loc", "abilityOverride_onSlot");
1317
abilityOverrideOnSlot.innerHTML = loc("abilityOverride_onSlot");
1318
abilityOverrideInputGroup.appendChild(abilityOverrideOnSlot);
1319
1320
const abilityOverrideSecondInput = document.createElement("input");
1321
abilityOverrideSecondInput.id = "abilityOverride-ability-index";
1322
abilityOverrideSecondInput.classList = "form-control";
1323
abilityOverrideSecondInput.setAttribute("type", "number");
1324
abilityOverrideSecondInput.setAttribute("min", "0");
1325
abilityOverrideSecondInput.setAttribute("max", "3");
1326
if (config.AbilityOverride)
1327
abilityOverrideSecondInput.value = config.AbilityOverride.Index;
1328
abilityOverrideInputGroup.appendChild(abilityOverrideSecondInput);
1329
1330
const abilityOverrideSetButton = document.createElement("button");
1331
abilityOverrideSetButton.classList = "btn btn-primary";
1332
abilityOverrideSetButton.setAttribute("type", "submit");
1333
abilityOverrideSetButton.setAttribute("value", "set");
1334
abilityOverrideSetButton.setAttribute("data-loc", "general_setButton");
1335
abilityOverrideSetButton.innerHTML = loc("general_setButton");
1336
abilityOverrideInputGroup.appendChild(abilityOverrideSetButton);
1337
1338
const abilityOverrideRemoveButton = document.createElement("button");
1339
abilityOverrideRemoveButton.classList = "btn btn-danger";
1340
abilityOverrideRemoveButton.setAttribute("type", "submit");
1341
abilityOverrideRemoveButton.setAttribute("value", "remove");
1342
abilityOverrideRemoveButton.setAttribute("data-loc", "code_remove");
1343
abilityOverrideRemoveButton.innerHTML = loc("code_remove");
1344
abilityOverrideInputGroup.appendChild(abilityOverrideRemoveButton);
1345
1346
abilityOverrideForm.appendChild(abilityOverrideInputGroup);
1347
1348
tabDiv.appendChild(abilityOverrideForm);
1349
}
1350
1351
loadoutTabsContent.appendChild(tabDiv);
1352
}
1353
}
1354
}
1244
1355
} else if (["LongGuns", "Pistols", "Melee", "SpaceGuns", "SpaceMelee"].includes(category)) {
1245
1356
document.getElementById("valenceBonus-card").classList.remove("d-none");
1246
1357
document.getElementById("valenceBonus-innateDamage").value = "";
@@ -2248,6 +2359,7 @@ single.getRoute("#detailedView-route").on("beforeload", function () {
2248
2359
document.getElementById("detailedView-loading").classList.remove("d-none");
2249
2360
document.getElementById("detailedView-title").textContent = "";
2250
2361
document.querySelector("#detailedView-route .text-body-secondary").textContent = "";
2362
document.getElementById("loadout-card").classList.add("d-none");
2251
2363
document.getElementById("archonShards-card").classList.add("d-none");
2252
2364
document.getElementById("edit-suit-invigorations-card").classList.add("d-none");
2253
2365
document.getElementById("modularParts-card").classList.add("d-none");
@@ -2963,3 +3075,29 @@ async function editSuitInvigorationUpgrade(oid, data) {
2963
3075
updateInventory();
2964
3076
});
2965
3077
}
3078
3079
function handleAbilityOverride(event, configIndex) {
3080
event.preventDefault();
3081
const urlParams = new URLSearchParams(window.location.search);
3082
const action = event.submitter.value;
3083
const Ability = getKey(document.getElementById("abilityOverride-ability"));
3084
const Index = document.getElementById("abilityOverride-ability-index").value;
3085
revalidateAuthz().then(() => {
3086
$.post({
3087
url: "/custom/abilityOverride?" + window.authz,
3088
contentType: "application/json",
3089
data: JSON.stringify({
3090
category: urlParams.get("productCategory"),
3091
oid: urlParams.get("itemId"),
3092
configIndex,
3093
action,
3094
AbilityOverride: {
3095
Ability,
3096
Index
3097
}
3098
})
3099
}).done(function () {
3100
updateInventory();
3101
});
3102
});
3103
}
@@ -128,6 +128,7 @@ dict = {
128
128
detailedView_valenceBonusDescription: `Du kannst den Valenz-Bonus deiner Waffe festlegen oder entfernen.`,
129
129
detailedView_modularPartsLabel: `Modulare Teile ändern`,
130
130
detailedView_suitInvigorationLabel: `Warframe-Kräftigung`,
131
detailedView_loadoutLabel: `Loadouts`,
131
132
132
133
invigorations_offensive_AbilityStrength: `+200% Fähigkeitsstärke`,
133
134
invigorations_offensive_AbilityRange: `+100% Fähigkeitsreichweite`,
@@ -155,6 +156,9 @@ dict = {
155
156
invigorations_defensiveLabel: `Defensives Upgrade`,
156
157
invigorations_expiryLabel: `Upgrades Ablaufdatum (optional)`,
157
158
159
abilityOverride_label: `[UNTRANSLATED] Ability Override`,
160
abilityOverride_onSlot: `[UNTRANSLATED] on slot`,
161
158
162
mods_addRiven: `Riven hinzufügen`,
159
163
mods_fingerprint: `Fingerabdruck`,
160
164
mods_fingerprintHelp: `Benötigst du Hilfe mit dem Fingerabdruck?`,
@@ -127,6 +127,7 @@ dict = {
127
127
detailedView_valenceBonusDescription: `You can set or remove the Valence Bonus from your weapon.`,
128
128
detailedView_modularPartsLabel: `Change Modular Parts`,
129
129
detailedView_suitInvigorationLabel: `Warframe Invigoration`,
130
detailedView_loadoutLabel: `Loadouts`,
130
131
131
132
invigorations_offensive_AbilityStrength: `+200% Ability Strength`,
132
133
invigorations_offensive_AbilityRange: `+100% Ability Range`,
@@ -154,6 +155,9 @@ dict = {
154
155
invigorations_defensiveLabel: `Defensive Upgrade`,
155
156
invigorations_expiryLabel: `Upgrades Expiry (optional)`,
156
157
158
abilityOverride_label: `Ability Override`,
159
abilityOverride_onSlot: `on slot`,
160
157
161
mods_addRiven: `Add Riven`,
158
162
mods_fingerprint: `Fingerprint`,
159
163
mods_fingerprintHelp: `Need help with the fingerprint?`,
@@ -128,6 +128,7 @@ dict = {
128
128
detailedView_valenceBonusDescription: `Puedes establecer o quitar el bono de valencia de tu arma.`,
129
129
detailedView_modularPartsLabel: `Cambiar partes modulares`,
130
130
detailedView_suitInvigorationLabel: `Vigorización de Warframe`,
131
detailedView_loadoutLabel: `Equipamientos`,
131
132
132
133
invigorations_offensive_AbilityStrength: `+200% Fuerza de Habilidad`,
133
134
invigorations_offensive_AbilityRange: `+100% Alcance de Habilidad`,
@@ -155,6 +156,9 @@ dict = {
155
156
invigorations_defensiveLabel: `Mejora Defensiva`,
156
157
invigorations_expiryLabel: `Caducidad de Mejoras (opcional)`,
157
158
159
abilityOverride_label: `[UNTRANSLATED] Ability Override`,
160
abilityOverride_onSlot: `[UNTRANSLATED] on slot`,
161
158
162
mods_addRiven: `Agregar Agrietado`,
159
163
mods_fingerprint: `Huella digital`,
160
164
mods_fingerprintHelp: `¿Necesitas ayuda con la huella digital?`,
@@ -128,6 +128,7 @@ dict = {
128
128
detailedView_valenceBonusDescription: `Définir le Bonus Valence de l'arme.`,
129
129
detailedView_modularPartsLabel: `Changer l'équipement modulaire`,
130
130
detailedView_suitInvigorationLabel: `Invigoration de Warframe`,
131
detailedView_loadoutLabel: `Équipements`,
131
132
132
133
invigorations_offensive_AbilityStrength: `+200% de puissance de pouvoir`,
133
134
invigorations_offensive_AbilityRange: `+100% de portée de pouvoir`,
@@ -155,6 +156,9 @@ dict = {
155
156
invigorations_defensiveLabel: `Amélioration défensive`,
156
157
invigorations_expiryLabel: `Expiration de l'invigoration (optionnel)`,
157
158
159
abilityOverride_label: `[UNTRANSLATED] Ability Override`,
160
abilityOverride_onSlot: `[UNTRANSLATED] on slot`,
161
158
162
mods_addRiven: `Ajouter un riven`,
159
163
mods_fingerprint: `Empreinte`,
160
164
mods_fingerprintHelp: `Besoin d'aide pour l'empreinte ?`,
@@ -128,6 +128,7 @@ dict = {
128
128
detailedView_valenceBonusDescription: `Вы можете установить или убрать бонус валентности с вашего оружия.`,
129
129
detailedView_modularPartsLabel: `Изменить Модульные Части`,
130
130
detailedView_suitInvigorationLabel: `[UNTRANSLATED] Warframe Invigoration`,
131
detailedView_loadoutLabel: `Конфигурации`,
131
132
132
133
invigorations_offensive_AbilityStrength: `[UNTRANSLATED] +200% Ability Strength`,
133
134
invigorations_offensive_AbilityRange: `[UNTRANSLATED] +100% Ability Range`,
@@ -155,6 +156,9 @@ dict = {
155
156
invigorations_defensiveLabel: `[UNTRANSLATED] Defensive Upgrade`,
156
157
invigorations_expiryLabel: `[UNTRANSLATED] Upgrades Expiry (optional)`,
157
158
159
abilityOverride_label: `Переопределение способности`,
160
abilityOverride_onSlot: `в ячейке`,
161
158
162
mods_addRiven: `Добавить Мод Разлома`,
159
163
mods_fingerprint: `Отпечаток`,
160
164
mods_fingerprintHelp: `Нужна помощь с отпечатком?`,
@@ -128,6 +128,7 @@ dict = {
128
128
detailedView_valenceBonusDescription: `您可以设置或移除武器上的效价加成.`,
129
129
detailedView_modularPartsLabel: `更换部件`,
130
130
detailedView_suitInvigorationLabel: `编辑战甲活化属性`,
131
detailedView_loadoutLabel: `配置`,
131
132
132
133
invigorations_offensive_AbilityStrength: `+200%技能强度`,
133
134
invigorations_offensive_AbilityRange: `+100%技能范围`,
@@ -155,6 +156,9 @@ dict = {
155
156
invigorations_defensiveLabel: `功能型属性`,
156
157
invigorations_expiryLabel: `活化时效(可选)`,
157
158
159
abilityOverride_label: `[UNTRANSLATED] Ability Override`,
160
abilityOverride_onSlot: `[UNTRANSLATED] on slot`,
161
158
162
mods_addRiven: `添加裂罅MOD`,
159
163
mods_fingerprint: `印记`,
160
164
mods_fingerprintHelp: `需要印记相关的帮助?`,