forked from OpenWF/SpaceNinjaServer
feat(webui): ability overrides (#2558)
Closes #851 Reviewed-on: OpenWF/SpaceNinjaServer#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>
This commit is contained in:
parent
8b4bc114f6
commit
b62e326920
33
src/controllers/custom/abilityOverrideController.ts
Normal file
33
src/controllers/custom/abilityOverrideController.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const abilityOverrideController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const request = req.body as IAbilityOverrideRequest;
|
||||
if (request.category === "Suits") {
|
||||
const inventory = await getInventory(accountId, request.category);
|
||||
const item = inventory[request.category].id(request.oid);
|
||||
if (item) {
|
||||
if (request.action == "set") {
|
||||
item.Configs[request.configIndex].AbilityOverride = request.AbilityOverride;
|
||||
} else {
|
||||
item.Configs[request.configIndex].AbilityOverride = undefined;
|
||||
}
|
||||
await inventory.save();
|
||||
}
|
||||
}
|
||||
res.end();
|
||||
};
|
||||
|
||||
interface IAbilityOverrideRequest {
|
||||
category: TEquipmentKey;
|
||||
oid: string;
|
||||
action: "set" | "remove";
|
||||
configIndex: number;
|
||||
AbilityOverride: {
|
||||
Ability: string;
|
||||
Index: number;
|
||||
};
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getDict, getItemName, getString } from "@/src/services/itemDataService";
|
||||
import {
|
||||
ExportAbilities,
|
||||
ExportArcanes,
|
||||
ExportAvionics,
|
||||
ExportBoosters,
|
||||
@ -57,6 +58,7 @@ interface ItemLists {
|
||||
mods: ListedItem[];
|
||||
Boosters: ListedItem[];
|
||||
VarziaOffers: ListedItem[];
|
||||
Abilities: ListedItem[];
|
||||
//circuitGameModes: ListedItem[];
|
||||
}
|
||||
|
||||
@ -94,7 +96,8 @@ const getItemListsController: RequestHandler = (req, response) => {
|
||||
EvolutionProgress: [],
|
||||
mods: [],
|
||||
Boosters: [],
|
||||
VarziaOffers: []
|
||||
VarziaOffers: [],
|
||||
Abilities: []
|
||||
/*circuitGameModes: [
|
||||
{
|
||||
uniqueName: "Survival",
|
||||
@ -132,6 +135,12 @@ const getItemListsController: RequestHandler = (req, response) => {
|
||||
name: getString(item.name, lang),
|
||||
exalted: item.exalted
|
||||
});
|
||||
item.abilities.forEach(ability => {
|
||||
res.Abilities.push({
|
||||
uniqueName: ability.uniqueName,
|
||||
name: getString(ability.name || uniqueName, lang)
|
||||
});
|
||||
});
|
||||
}
|
||||
for (const [uniqueName, item] of Object.entries(ExportSentinels)) {
|
||||
if (item.productCategory == "Sentinels" || item.productCategory == "KubrowPets") {
|
||||
@ -348,6 +357,13 @@ const getItemListsController: RequestHandler = (req, response) => {
|
||||
});
|
||||
}
|
||||
|
||||
for (const [uniqueName, ability] of Object.entries(ExportAbilities)) {
|
||||
res.Abilities.push({
|
||||
uniqueName,
|
||||
name: getString(ability.name || uniqueName, lang)
|
||||
});
|
||||
}
|
||||
|
||||
response.json(res);
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,7 @@ import { webuiFileChangeDetectedController } from "@/src/controllers/custom/webu
|
||||
import { completeAllMissionsController } from "@/src/controllers/custom/completeAllMissionsController";
|
||||
import { addMissingHelminthBlueprintsController } from "@/src/controllers/custom/addMissingHelminthBlueprintsController";
|
||||
|
||||
import { abilityOverrideController } from "@/src/controllers/custom/abilityOverrideController";
|
||||
import { createAccountController } from "@/src/controllers/custom/createAccountController";
|
||||
import { createMessageController } from "@/src/controllers/custom/createMessageController";
|
||||
import { addCurrencyController } from "@/src/controllers/custom/addCurrencyController";
|
||||
@ -47,6 +48,7 @@ customRouter.get("/webuiFileChangeDetected", webuiFileChangeDetectedController);
|
||||
customRouter.get("/completeAllMissions", completeAllMissionsController);
|
||||
customRouter.get("/addMissingHelminthBlueprints", addMissingHelminthBlueprintsController);
|
||||
|
||||
customRouter.post("/abilityOverride", abilityOverrideController);
|
||||
customRouter.post("/createAccount", createAccountController);
|
||||
customRouter.post("/createMessage", createMessageController);
|
||||
customRouter.post("/addCurrency", addCurrencyController);
|
||||
|
@ -460,6 +460,13 @@
|
||||
<h3 id="detailedView-loading" class="mb-0" data-loc="general_loading"></h3>
|
||||
<h3 id="detailedView-title" class="mb-0"></h3>
|
||||
<p class="text-body-secondary"></p>
|
||||
<div id="loadout-card" class="card mb-3 d-none">
|
||||
<h5 class="card-header" data-loc="detailedView_loadoutLabel"></h5>
|
||||
<div class="card-body">
|
||||
<ul class="nav nav-tabs" id="loadoutTabs"></ul>
|
||||
<div class="tab-content mt-3" id="loadoutTabsContent"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="archonShards-card" class="card mb-3 d-none">
|
||||
<h5 class="card-header" data-loc="detailedView_archonShardsLabel"></h5>
|
||||
<div class="card-body">
|
||||
@ -1073,6 +1080,7 @@
|
||||
<datalist id="datalist-ModularParts-KUBROW_ANTIGEN"></datalist>
|
||||
<datalist id="datalist-ModularParts-KUBROW_MUTAGEN"></datalist>
|
||||
<datalist id="datalist-Boosters"></datalist>
|
||||
<datalist id="datalist-Abilities"></datalist>
|
||||
<datalist id="datalist-circuitGameModes">
|
||||
<option>Survival</option>
|
||||
<option>VoidFlood</option>
|
||||
|
@ -1241,6 +1241,117 @@ function updateInventory() {
|
||||
document.getElementById("dv-invigoration-offensive").value = OffensiveUpgrade;
|
||||
document.getElementById("dv-invigoration-defensive").value = DefensiveUpgrade;
|
||||
document.getElementById("dv-invigoration-expiry").value = UpgradesExpiry;
|
||||
|
||||
{
|
||||
document.getElementById("loadout-card").classList.remove("d-none");
|
||||
const maxModConfigNum = Math.min(2 + (item.ModSlotPurchases ?? 0), 5);
|
||||
|
||||
const configs = item.Configs ?? [];
|
||||
|
||||
const loadoutTabs = document.getElementById("loadoutTabs");
|
||||
const loadoutTabsContent = document.getElementById("loadoutTabsContent");
|
||||
loadoutTabs.innerHTML = "";
|
||||
loadoutTabsContent.innerHTML = "";
|
||||
for (let i = 0; i <= maxModConfigNum; i++) {
|
||||
const config = configs[i] ?? {};
|
||||
|
||||
{
|
||||
const li = document.createElement("li");
|
||||
li.classList.add("nav-item");
|
||||
|
||||
const button = document.createElement("button");
|
||||
button.classList.add("nav-link");
|
||||
if (i === 0) button.classList.add("active");
|
||||
button.id = `config${i}-tab`;
|
||||
button.setAttribute("data-bs-toggle", "tab");
|
||||
button.setAttribute("data-bs-target", `#config${i}`);
|
||||
button.innerHTML = config.Name?.trim() || String.fromCharCode(65 + i);
|
||||
|
||||
li.appendChild(button);
|
||||
loadoutTabs.appendChild(li);
|
||||
}
|
||||
|
||||
{
|
||||
const tabDiv = document.createElement("div");
|
||||
tabDiv.classList = "tab-pane";
|
||||
if (i === 0) tabDiv.classList.add("show", "active");
|
||||
|
||||
tabDiv.id = `config${i}`;
|
||||
|
||||
{
|
||||
const abilityOverrideForm = document.createElement("form");
|
||||
abilityOverrideForm.classList = "form-group mt-2";
|
||||
abilityOverrideForm.setAttribute(
|
||||
"onsubmit",
|
||||
`handleAbilityOverride(event, ${i});return false;`
|
||||
);
|
||||
|
||||
const abilityOverrideFormLabel = document.createElement("label");
|
||||
abilityOverrideFormLabel.setAttribute("data-loc", "abilityOverride_label");
|
||||
abilityOverrideFormLabel.innerHTML = loc("abilityOverride_label");
|
||||
abilityOverrideFormLabel.classList = "form-label";
|
||||
abilityOverrideFormLabel.setAttribute("for", "abilityOverride-ability");
|
||||
abilityOverrideForm.appendChild(abilityOverrideFormLabel);
|
||||
|
||||
const abilityOverrideInputGroup = document.createElement("div");
|
||||
abilityOverrideInputGroup.classList = "input-group";
|
||||
abilityOverrideForm.appendChild(abilityOverrideInputGroup);
|
||||
|
||||
const abilityOverrideInput = document.createElement("input");
|
||||
abilityOverrideInput.id = "abilityOverride-ability";
|
||||
abilityOverrideInput.classList = "form-control";
|
||||
abilityOverrideInput.setAttribute("list", "datalist-Abilities");
|
||||
if (config.AbilityOverride) {
|
||||
const datalist = document.getElementById("datalist-Abilities");
|
||||
const options = Array.from(datalist.options);
|
||||
abilityOverrideInput.value = options.find(
|
||||
option =>
|
||||
config.AbilityOverride.Ability == option.getAttribute("data-key")
|
||||
).value;
|
||||
}
|
||||
abilityOverrideInputGroup.appendChild(abilityOverrideInput);
|
||||
|
||||
const abilityOverrideOnSlot = document.createElement("span");
|
||||
abilityOverrideOnSlot.classList = "input-group-text";
|
||||
abilityOverrideOnSlot.setAttribute("data-loc", "abilityOverride_onSlot");
|
||||
abilityOverrideOnSlot.innerHTML = loc("abilityOverride_onSlot");
|
||||
abilityOverrideInputGroup.appendChild(abilityOverrideOnSlot);
|
||||
|
||||
const abilityOverrideSecondInput = document.createElement("input");
|
||||
abilityOverrideSecondInput.id = "abilityOverride-ability-index";
|
||||
abilityOverrideSecondInput.classList = "form-control";
|
||||
abilityOverrideSecondInput.setAttribute("type", "number");
|
||||
abilityOverrideSecondInput.setAttribute("min", "0");
|
||||
abilityOverrideSecondInput.setAttribute("max", "3");
|
||||
if (config.AbilityOverride)
|
||||
abilityOverrideSecondInput.value = config.AbilityOverride.Index;
|
||||
abilityOverrideInputGroup.appendChild(abilityOverrideSecondInput);
|
||||
|
||||
const abilityOverrideSetButton = document.createElement("button");
|
||||
abilityOverrideSetButton.classList = "btn btn-primary";
|
||||
abilityOverrideSetButton.setAttribute("type", "submit");
|
||||
abilityOverrideSetButton.setAttribute("value", "set");
|
||||
abilityOverrideSetButton.setAttribute("data-loc", "general_setButton");
|
||||
abilityOverrideSetButton.innerHTML = loc("general_setButton");
|
||||
abilityOverrideInputGroup.appendChild(abilityOverrideSetButton);
|
||||
|
||||
const abilityOverrideRemoveButton = document.createElement("button");
|
||||
abilityOverrideRemoveButton.classList = "btn btn-danger";
|
||||
abilityOverrideRemoveButton.setAttribute("type", "submit");
|
||||
abilityOverrideRemoveButton.setAttribute("value", "remove");
|
||||
abilityOverrideRemoveButton.setAttribute("data-loc", "code_remove");
|
||||
abilityOverrideRemoveButton.innerHTML = loc("code_remove");
|
||||
abilityOverrideInputGroup.appendChild(abilityOverrideRemoveButton);
|
||||
|
||||
abilityOverrideForm.appendChild(abilityOverrideInputGroup);
|
||||
|
||||
tabDiv.appendChild(abilityOverrideForm);
|
||||
}
|
||||
|
||||
loadoutTabsContent.appendChild(tabDiv);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (["LongGuns", "Pistols", "Melee", "SpaceGuns", "SpaceMelee"].includes(category)) {
|
||||
document.getElementById("valenceBonus-card").classList.remove("d-none");
|
||||
document.getElementById("valenceBonus-innateDamage").value = "";
|
||||
@ -2248,6 +2359,7 @@ single.getRoute("#detailedView-route").on("beforeload", function () {
|
||||
document.getElementById("detailedView-loading").classList.remove("d-none");
|
||||
document.getElementById("detailedView-title").textContent = "";
|
||||
document.querySelector("#detailedView-route .text-body-secondary").textContent = "";
|
||||
document.getElementById("loadout-card").classList.add("d-none");
|
||||
document.getElementById("archonShards-card").classList.add("d-none");
|
||||
document.getElementById("edit-suit-invigorations-card").classList.add("d-none");
|
||||
document.getElementById("modularParts-card").classList.add("d-none");
|
||||
@ -2963,3 +3075,29 @@ async function editSuitInvigorationUpgrade(oid, data) {
|
||||
updateInventory();
|
||||
});
|
||||
}
|
||||
|
||||
function handleAbilityOverride(event, configIndex) {
|
||||
event.preventDefault();
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const action = event.submitter.value;
|
||||
const Ability = getKey(document.getElementById("abilityOverride-ability"));
|
||||
const Index = document.getElementById("abilityOverride-ability-index").value;
|
||||
revalidateAuthz().then(() => {
|
||||
$.post({
|
||||
url: "/custom/abilityOverride?" + window.authz,
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({
|
||||
category: urlParams.get("productCategory"),
|
||||
oid: urlParams.get("itemId"),
|
||||
configIndex,
|
||||
action,
|
||||
AbilityOverride: {
|
||||
Ability,
|
||||
Index
|
||||
}
|
||||
})
|
||||
}).done(function () {
|
||||
updateInventory();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -128,6 +128,7 @@ dict = {
|
||||
detailedView_valenceBonusDescription: `Du kannst den Valenz-Bonus deiner Waffe festlegen oder entfernen.`,
|
||||
detailedView_modularPartsLabel: `Modulare Teile ändern`,
|
||||
detailedView_suitInvigorationLabel: `Warframe-Kräftigung`,
|
||||
detailedView_loadoutLabel: `Loadouts`,
|
||||
|
||||
invigorations_offensive_AbilityStrength: `+200% Fähigkeitsstärke`,
|
||||
invigorations_offensive_AbilityRange: `+100% Fähigkeitsreichweite`,
|
||||
@ -155,6 +156,9 @@ dict = {
|
||||
invigorations_defensiveLabel: `Defensives Upgrade`,
|
||||
invigorations_expiryLabel: `Upgrades Ablaufdatum (optional)`,
|
||||
|
||||
abilityOverride_label: `[UNTRANSLATED] Ability Override`,
|
||||
abilityOverride_onSlot: `[UNTRANSLATED] on slot`,
|
||||
|
||||
mods_addRiven: `Riven hinzufügen`,
|
||||
mods_fingerprint: `Fingerabdruck`,
|
||||
mods_fingerprintHelp: `Benötigst du Hilfe mit dem Fingerabdruck?`,
|
||||
|
@ -127,6 +127,7 @@ dict = {
|
||||
detailedView_valenceBonusDescription: `You can set or remove the Valence Bonus from your weapon.`,
|
||||
detailedView_modularPartsLabel: `Change Modular Parts`,
|
||||
detailedView_suitInvigorationLabel: `Warframe Invigoration`,
|
||||
detailedView_loadoutLabel: `Loadouts`,
|
||||
|
||||
invigorations_offensive_AbilityStrength: `+200% Ability Strength`,
|
||||
invigorations_offensive_AbilityRange: `+100% Ability Range`,
|
||||
@ -154,6 +155,9 @@ dict = {
|
||||
invigorations_defensiveLabel: `Defensive Upgrade`,
|
||||
invigorations_expiryLabel: `Upgrades Expiry (optional)`,
|
||||
|
||||
abilityOverride_label: `Ability Override`,
|
||||
abilityOverride_onSlot: `on slot`,
|
||||
|
||||
mods_addRiven: `Add Riven`,
|
||||
mods_fingerprint: `Fingerprint`,
|
||||
mods_fingerprintHelp: `Need help with the fingerprint?`,
|
||||
|
@ -128,6 +128,7 @@ dict = {
|
||||
detailedView_valenceBonusDescription: `Puedes establecer o quitar el bono de valencia de tu arma.`,
|
||||
detailedView_modularPartsLabel: `Cambiar partes modulares`,
|
||||
detailedView_suitInvigorationLabel: `Vigorización de Warframe`,
|
||||
detailedView_loadoutLabel: `Equipamientos`,
|
||||
|
||||
invigorations_offensive_AbilityStrength: `+200% Fuerza de Habilidad`,
|
||||
invigorations_offensive_AbilityRange: `+100% Alcance de Habilidad`,
|
||||
@ -155,6 +156,9 @@ dict = {
|
||||
invigorations_defensiveLabel: `Mejora Defensiva`,
|
||||
invigorations_expiryLabel: `Caducidad de Mejoras (opcional)`,
|
||||
|
||||
abilityOverride_label: `[UNTRANSLATED] Ability Override`,
|
||||
abilityOverride_onSlot: `[UNTRANSLATED] on slot`,
|
||||
|
||||
mods_addRiven: `Agregar Agrietado`,
|
||||
mods_fingerprint: `Huella digital`,
|
||||
mods_fingerprintHelp: `¿Necesitas ayuda con la huella digital?`,
|
||||
|
@ -128,6 +128,7 @@ dict = {
|
||||
detailedView_valenceBonusDescription: `Définir le Bonus Valence de l'arme.`,
|
||||
detailedView_modularPartsLabel: `Changer l'équipement modulaire`,
|
||||
detailedView_suitInvigorationLabel: `Invigoration de Warframe`,
|
||||
detailedView_loadoutLabel: `Équipements`,
|
||||
|
||||
invigorations_offensive_AbilityStrength: `+200% de puissance de pouvoir`,
|
||||
invigorations_offensive_AbilityRange: `+100% de portée de pouvoir`,
|
||||
@ -155,6 +156,9 @@ dict = {
|
||||
invigorations_defensiveLabel: `Amélioration défensive`,
|
||||
invigorations_expiryLabel: `Expiration de l'invigoration (optionnel)`,
|
||||
|
||||
abilityOverride_label: `[UNTRANSLATED] Ability Override`,
|
||||
abilityOverride_onSlot: `[UNTRANSLATED] on slot`,
|
||||
|
||||
mods_addRiven: `Ajouter un riven`,
|
||||
mods_fingerprint: `Empreinte`,
|
||||
mods_fingerprintHelp: `Besoin d'aide pour l'empreinte ?`,
|
||||
|
@ -128,6 +128,7 @@ dict = {
|
||||
detailedView_valenceBonusDescription: `Вы можете установить или убрать бонус валентности с вашего оружия.`,
|
||||
detailedView_modularPartsLabel: `Изменить Модульные Части`,
|
||||
detailedView_suitInvigorationLabel: `[UNTRANSLATED] Warframe Invigoration`,
|
||||
detailedView_loadoutLabel: `Конфигурации`,
|
||||
|
||||
invigorations_offensive_AbilityStrength: `[UNTRANSLATED] +200% Ability Strength`,
|
||||
invigorations_offensive_AbilityRange: `[UNTRANSLATED] +100% Ability Range`,
|
||||
@ -155,6 +156,9 @@ dict = {
|
||||
invigorations_defensiveLabel: `[UNTRANSLATED] Defensive Upgrade`,
|
||||
invigorations_expiryLabel: `[UNTRANSLATED] Upgrades Expiry (optional)`,
|
||||
|
||||
abilityOverride_label: `Переопределение способности`,
|
||||
abilityOverride_onSlot: `в ячейке`,
|
||||
|
||||
mods_addRiven: `Добавить Мод Разлома`,
|
||||
mods_fingerprint: `Отпечаток`,
|
||||
mods_fingerprintHelp: `Нужна помощь с отпечатком?`,
|
||||
|
@ -128,6 +128,7 @@ dict = {
|
||||
detailedView_valenceBonusDescription: `您可以设置或移除武器上的效价加成.`,
|
||||
detailedView_modularPartsLabel: `更换部件`,
|
||||
detailedView_suitInvigorationLabel: `编辑战甲活化属性`,
|
||||
detailedView_loadoutLabel: `配置`,
|
||||
|
||||
invigorations_offensive_AbilityStrength: `+200%技能强度`,
|
||||
invigorations_offensive_AbilityRange: `+100%技能范围`,
|
||||
@ -155,6 +156,9 @@ dict = {
|
||||
invigorations_defensiveLabel: `功能型属性`,
|
||||
invigorations_expiryLabel: `活化时效(可选)`,
|
||||
|
||||
abilityOverride_label: `[UNTRANSLATED] Ability Override`,
|
||||
abilityOverride_onSlot: `[UNTRANSLATED] on slot`,
|
||||
|
||||
mods_addRiven: `添加裂罅MOD`,
|
||||
mods_fingerprint: `印记`,
|
||||
mods_fingerprintHelp: `需要印记相关的帮助?`,
|
||||
|
Loading…
x
Reference in New Issue
Block a user