diff --git a/src/controllers/custom/editSuitInvigorationUpgradeController.ts b/src/controllers/custom/editSuitInvigorationUpgradeController.ts new file mode 100644 index 00000000..bc624911 --- /dev/null +++ b/src/controllers/custom/editSuitInvigorationUpgradeController.ts @@ -0,0 +1,34 @@ +import { getAccountIdForRequest } from "@/src/services/loginService"; +import { getInventory } from "@/src/services/inventoryService"; +import { RequestHandler } from "express"; + +const DEFAULT_UPGRADE_EXPIRY_MS = 7 * 24 * 60 * 60 * 1000; // 7 days + +export const editSuitInvigorationUpgradeController: RequestHandler = async (req, res) => { + const accountId = await getAccountIdForRequest(req); + const { oid, data } = req.body as { + oid: string; + data?: { + DefensiveUpgrade: string; + OffensiveUpgrade: string; + UpgradesExpiry?: number; + }; + }; + const inventory = await getInventory(accountId); + const suit = inventory.Suits.id(oid)!; + if (data) { + suit.DefensiveUpgrade = data.DefensiveUpgrade; + suit.OffensiveUpgrade = data.OffensiveUpgrade; + if (data.UpgradesExpiry) { + suit.UpgradesExpiry = new Date(data.UpgradesExpiry); + } else { + suit.UpgradesExpiry = new Date(Date.now() + DEFAULT_UPGRADE_EXPIRY_MS); + } + } else { + suit.DefensiveUpgrade = undefined; + suit.OffensiveUpgrade = undefined; + suit.UpgradesExpiry = undefined; + } + await inventory.save(); + res.end(); +}; diff --git a/src/routes/custom.ts b/src/routes/custom.ts index bc0427f4..9eb3d9e4 100644 --- a/src/routes/custom.ts +++ b/src/routes/custom.ts @@ -26,6 +26,7 @@ import { setEvolutionProgressController } from "@/src/controllers/custom/setEvol import { setBoosterController } from "@/src/controllers/custom/setBoosterController"; import { updateFingerprintController } from "@/src/controllers/custom/updateFingerprintController"; import { changeModularPartsController } from "@/src/controllers/custom/changeModularPartsController"; +import { editSuitInvigorationUpgradeController } from "@/src/controllers/custom/editSuitInvigorationUpgradeController"; import { getConfigController, setConfigController } from "@/src/controllers/custom/configController"; @@ -57,6 +58,7 @@ customRouter.post("/setEvolutionProgress", setEvolutionProgressController); customRouter.post("/setBooster", setBoosterController); customRouter.post("/updateFingerprint", updateFingerprintController); customRouter.post("/changeModularParts", changeModularPartsController); +customRouter.post("/editSuitInvigorationUpgrade", editSuitInvigorationUpgradeController); customRouter.post("/getConfig", getConfigController); customRouter.post("/setConfig", setConfigController); diff --git a/static/webui/index.html b/static/webui/index.html index c6f6baa3..d01f8c90 100644 --- a/static/webui/index.html +++ b/static/webui/index.html @@ -478,6 +478,56 @@ +
+
+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
diff --git a/static/webui/script.js b/static/webui/script.js index b04a88c4..449da772 100644 --- a/static/webui/script.js +++ b/static/webui/script.js @@ -1231,6 +1231,13 @@ function updateInventory() { } document.getElementById("crystals-list").appendChild(tr); }); + + document.getElementById("edit-suit-invigorations-card").classList.remove("d-none"); + const { OffensiveUpgrade, DefensiveUpgrade, UpgradesExpiry } = + suitInvigorationUpgradeData(item); + document.getElementById("dv-invigoration-offensive").value = OffensiveUpgrade; + document.getElementById("dv-invigoration-defensive").value = DefensiveUpgrade; + document.getElementById("dv-invigoration-expiry").value = UpgradesExpiry; } else if (["LongGuns", "Pistols", "Melee", "SpaceGuns", "SpaceMelee"].includes(category)) { document.getElementById("valenceBonus-card").classList.remove("d-none"); document.getElementById("valenceBonus-innateDamage").value = ""; @@ -2863,3 +2870,74 @@ function handleModularPartsChange(event) { }); } } +function suitInvigorationUpgradeData(suitData) { + let expiryDate = ""; + if (suitData.UpgradesExpiry) { + if (suitData.UpgradesExpiry.$date) { + expiryDate = new Date(parseInt(suitData.UpgradesExpiry.$date.$numberLong)); + } else if (typeof suitData.UpgradesExpiry === "number") { + expiryDate = new Date(suitData.UpgradesExpiry); + } else if (suitData.UpgradesExpiry instanceof Date) { + expiryDate = suitData.UpgradesExpiry; + } + if (expiryDate && !isNaN(expiryDate.getTime())) { + const year = expiryDate.getFullYear(); + const month = String(expiryDate.getMonth() + 1).padStart(2, "0"); + const day = String(expiryDate.getDate()).padStart(2, "0"); + const hours = String(expiryDate.getHours()).padStart(2, "0"); + const minutes = String(expiryDate.getMinutes()).padStart(2, "0"); + expiryDate = `${year}-${month}-${day}T${hours}:${minutes}`; + } else { + expiryDate = ""; + } + } + return { + oid: suitData.ItemId.$oid, + OffensiveUpgrade: suitData.OffensiveUpgrade || "", + DefensiveUpgrade: suitData.DefensiveUpgrade || "", + UpgradesExpiry: expiryDate + }; +} + +function submitSuitInvigorationUpgrade(event) { + event.preventDefault(); + const oid = new URLSearchParams(window.location.search).get("itemId"); + const offensiveUpgrade = document.getElementById("dv-invigoration-offensive").value; + const defensiveUpgrade = document.getElementById("dv-invigoration-defensive").value; + const expiry = document.getElementById("dv-invigoration-expiry").value; + + if (!offensiveUpgrade || !defensiveUpgrade) { + alert(loc("code_requiredInvigorationUpgrade")); + return; + } + + const data = { + OffensiveUpgrade: offensiveUpgrade, + DefensiveUpgrade: defensiveUpgrade + }; + + if (expiry) { + data.UpgradesExpiry = new Date(expiry).getTime(); + } + + editSuitInvigorationUpgrade(oid, data); +} + +function clearSuitInvigorationUpgrades() { + editSuitInvigorationUpgrade(new URLSearchParams(window.location.search).get("itemId"), null); +} + +async function editSuitInvigorationUpgrade(oid, data) { + /* data?: { + DefensiveUpgrade: string; + OffensiveUpgrade: string; + UpgradesExpiry?: number; + }*/ + $.post({ + url: "/custom/editSuitInvigorationUpgrade?" + window.authz, + contentType: "application/json", + data: JSON.stringify({ oid, data }) + }).done(function () { + updateInventory(); + }); +} diff --git a/static/webui/translations/de.js b/static/webui/translations/de.js index 3c53b488..6ba7a2ed 100644 --- a/static/webui/translations/de.js +++ b/static/webui/translations/de.js @@ -62,6 +62,7 @@ dict = { code_mature: `Für den Kampf auswachsen lassen`, code_unmature: `Genetisches Altern zurücksetzen`, code_succChange: `Erfolgreich geändert.`, + code_requiredInvigorationUpgrade: `[UNTRANSLATED] You must select both an offensive and a defensive upgrade.`, login_description: `Melde dich mit deinem OpenWF-Account an (denselben Angaben wie im Spiel, wenn du dich mit diesem Server verbindest).`, login_emailLabel: `E-Mail-Adresse`, login_passwordLabel: `Passwort`, @@ -125,6 +126,36 @@ dict = { detailedView_valenceBonusLabel: `Valenz-Bonus`, detailedView_valenceBonusDescription: `Du kannst den Valenz-Bonus deiner Waffe festlegen oder entfernen.`, detailedView_modularPartsLabel: `Modulare Teile ändern`, + detailedView_editSuitInvigoration: `[UNTRANSLATED] Edit Suit Invigoration`, + + invigorations_offensive_PowerStrength: `[UNTRANSLATED] Power Strength`, + invigorations_offensive_PowerRange: `[UNTRANSLATED] Power Range`, + invigorations_offensive_PowerDuration: `[UNTRANSLATED] Power Duration`, + invigorations_offensive_MeleeDamage: `[UNTRANSLATED] Melee Damage`, + invigorations_offensive_PrimaryDamage: `[UNTRANSLATED] Primary Damage`, + invigorations_offensive_SecondaryDamage: `[UNTRANSLATED] Secondary Damage`, + invigorations_offensive_PrimaryCritChance: `[UNTRANSLATED] Primary Critical Chance`, + invigorations_offensive_SecondaryCritChance: `[UNTRANSLATED] Secondary Critical Chance`, + invigorations_offensive_MeleeCritChance: `[UNTRANSLATED] Melee Critical Chance`, + + invigorations_utility_PowerEfficiency: `[UNTRANSLATED] Power Efficiency`, + invigorations_utility_MovementSpeed: `[UNTRANSLATED] Movement Speed`, + invigorations_utility_ParkourSpeed: `[UNTRANSLATED] Parkour Speed`, + invigorations_utility_Health: `[UNTRANSLATED] Health`, + invigorations_utility_Energy: `[UNTRANSLATED] Energy`, + invigorations_utility_StatusResistance: `[UNTRANSLATED] Status Resistance`, + invigorations_utility_ReloadSpeed: `[UNTRANSLATED] Reload Speed`, + invigorations_utility_HealthRegen: `[UNTRANSLATED] Health Regen`, + invigorations_utility_Armor: `[UNTRANSLATED] Armor`, + invigorations_utility_Jumps: `[UNTRANSLATED] Jumps`, + invigorations_utility_EnergyRegen: `[UNTRANSLATED] Energy Regen`, + + invigorations_offensiveLabel: `[UNTRANSLATED] Offensive Upgrade`, + invigorations_defensiveLabel: `[UNTRANSLATED] Defensive Upgrade`, + invigorations_expiryLabel: `[UNTRANSLATED] Upgrades Expiry (optional)`, + invigorations_applyButton: `[UNTRANSLATED] Apply Upgrades`, + invigorations_clearButton: `[UNTRANSLATED] Clear Upgrades`, + invigorations_noneOption: `[UNTRANSLATED] None`, mods_addRiven: `Riven hinzufügen`, mods_fingerprint: `Fingerabdruck`, diff --git a/static/webui/translations/en.js b/static/webui/translations/en.js index b95e2c66..725bb705 100644 --- a/static/webui/translations/en.js +++ b/static/webui/translations/en.js @@ -61,6 +61,7 @@ dict = { code_mature: `Mature for combat`, code_unmature: `Regress genetic aging`, code_succChange: `Successfully changed.`, + code_requiredInvigorationUpgrade: `You must select both an offensive and a defensive upgrade.`, login_description: `Login using your OpenWF account credentials (same as in-game when connecting to this server).`, login_emailLabel: `Email address`, login_passwordLabel: `Password`, @@ -124,6 +125,36 @@ dict = { detailedView_valenceBonusLabel: `Valence Bonus`, detailedView_valenceBonusDescription: `You can set or remove the Valence Bonus from your weapon.`, detailedView_modularPartsLabel: `Change Modular Parts`, + detailedView_editSuitInvigoration: `Edit Suit Invigoration`, + + invigorations_offensive_PowerStrength: `Power Strength`, + invigorations_offensive_PowerRange: `Power Range`, + invigorations_offensive_PowerDuration: `Power Duration`, + invigorations_offensive_MeleeDamage: `Melee Damage`, + invigorations_offensive_PrimaryDamage: `Primary Damage`, + invigorations_offensive_SecondaryDamage: `Secondary Damage`, + invigorations_offensive_PrimaryCritChance: `Primary Critical Chance`, + invigorations_offensive_SecondaryCritChance: `Secondary Critical Chance`, + invigorations_offensive_MeleeCritChance: `Melee Critical Chance`, + + invigorations_utility_PowerEfficiency: `Power Efficiency`, + invigorations_utility_MovementSpeed: `Movement Speed`, + invigorations_utility_ParkourSpeed: `Parkour Speed`, + invigorations_utility_Health: `Health`, + invigorations_utility_Energy: `Energy`, + invigorations_utility_StatusResistance: `Status Resistance`, + invigorations_utility_ReloadSpeed: `Reload Speed`, + invigorations_utility_HealthRegen: `Health Regen`, + invigorations_utility_Armor: `Armor`, + invigorations_utility_Jumps: `Jumps`, + invigorations_utility_EnergyRegen: `Energy Regen`, + + invigorations_offensiveLabel: `Offensive Upgrade`, + invigorations_defensiveLabel: `Defensive Upgrade`, + invigorations_expiryLabel: `Upgrades Expiry (optional)`, + invigorations_applyButton: `Apply Upgrades`, + invigorations_clearButton: `Clear Upgrades`, + invigorations_noneOption: `None`, mods_addRiven: `Add Riven`, mods_fingerprint: `Fingerprint`, diff --git a/static/webui/translations/es.js b/static/webui/translations/es.js index 16a764b4..c7527b96 100644 --- a/static/webui/translations/es.js +++ b/static/webui/translations/es.js @@ -62,6 +62,7 @@ dict = { code_mature: `Listo para el combate`, code_unmature: `Regresar el envejecimiento genético`, code_succChange: `Cambiado correctamente`, + code_requiredInvigorationUpgrade: `[UNTRANSLATED] You must select both an offensive and a defensive upgrade.`, login_description: `Inicia sesión con las credenciales de tu cuenta OpenWF (las mismas que usas en el juego al conectarte a este servidor).`, login_emailLabel: `Dirección de correo electrónico`, login_passwordLabel: `Contraseña`, @@ -125,6 +126,36 @@ dict = { detailedView_valenceBonusLabel: `Bônus de Valência`, detailedView_valenceBonusDescription: `Puedes establecer o quitar el bono de valencia de tu arma.`, detailedView_modularPartsLabel: `Cambiar partes modulares`, + detailedView_editSuitInvigoration: `[UNTRANSLATED] Edit Suit Invigoration`, + + invigorations_offensive_PowerStrength: `[UNTRANSLATED] Power Strength`, + invigorations_offensive_PowerRange: `[UNTRANSLATED] Power Range`, + invigorations_offensive_PowerDuration: `[UNTRANSLATED] Power Duration`, + invigorations_offensive_MeleeDamage: `[UNTRANSLATED] Melee Damage`, + invigorations_offensive_PrimaryDamage: `[UNTRANSLATED] Primary Damage`, + invigorations_offensive_SecondaryDamage: `[UNTRANSLATED] Secondary Damage`, + invigorations_offensive_PrimaryCritChance: `[UNTRANSLATED] Primary Critical Chance`, + invigorations_offensive_SecondaryCritChance: `[UNTRANSLATED] Secondary Critical Chance`, + invigorations_offensive_MeleeCritChance: `[UNTRANSLATED] Melee Critical Chance`, + + invigorations_utility_PowerEfficiency: `[UNTRANSLATED] Power Efficiency`, + invigorations_utility_MovementSpeed: `[UNTRANSLATED] Movement Speed`, + invigorations_utility_ParkourSpeed: `[UNTRANSLATED] Parkour Speed`, + invigorations_utility_Health: `[UNTRANSLATED] Health`, + invigorations_utility_Energy: `[UNTRANSLATED] Energy`, + invigorations_utility_StatusResistance: `[UNTRANSLATED] Status Resistance`, + invigorations_utility_ReloadSpeed: `[UNTRANSLATED] Reload Speed`, + invigorations_utility_HealthRegen: `[UNTRANSLATED] Health Regen`, + invigorations_utility_Armor: `[UNTRANSLATED] Armor`, + invigorations_utility_Jumps: `[UNTRANSLATED] Jumps`, + invigorations_utility_EnergyRegen: `[UNTRANSLATED] Energy Regen`, + + invigorations_offensiveLabel: `[UNTRANSLATED] Offensive Upgrade`, + invigorations_defensiveLabel: `[UNTRANSLATED] Defensive Upgrade`, + invigorations_expiryLabel: `[UNTRANSLATED] Upgrades Expiry (optional)`, + invigorations_applyButton: `[UNTRANSLATED] Apply Upgrades`, + invigorations_clearButton: `[UNTRANSLATED] Clear Upgrades`, + invigorations_noneOption: `[UNTRANSLATED] None`, mods_addRiven: `Agregar Agrietado`, mods_fingerprint: `Huella digital`, diff --git a/static/webui/translations/fr.js b/static/webui/translations/fr.js index f83433e9..3e0ffada 100644 --- a/static/webui/translations/fr.js +++ b/static/webui/translations/fr.js @@ -62,6 +62,7 @@ dict = { code_mature: `Maturer pour le combat`, code_unmature: `Régrésser l'âge génétique`, code_succChange: `[UNTRANSLATED] Successfully changed.`, + code_requiredInvigorationUpgrade: `[UNTRANSLATED] You must select both an offensive and a defensive upgrade.`, login_description: `Connexion avec les informations de connexion OpenWF.`, login_emailLabel: `Email`, login_passwordLabel: `Mot de passe`, @@ -125,6 +126,36 @@ dict = { detailedView_valenceBonusLabel: `Bonus de Valence`, detailedView_valenceBonusDescription: `[UNTRANSLATED] You can set or remove the Valence Bonus from your weapon.`, detailedView_modularPartsLabel: `[UNTRANSLATED] Change Modular Parts`, + detailedView_editSuitInvigoration: `[UNTRANSLATED] Edit Suit Invigoration`, + + invigorations_offensive_PowerStrength: `[UNTRANSLATED] Power Strength`, + invigorations_offensive_PowerRange: `[UNTRANSLATED] Power Range`, + invigorations_offensive_PowerDuration: `[UNTRANSLATED] Power Duration`, + invigorations_offensive_MeleeDamage: `[UNTRANSLATED] Melee Damage`, + invigorations_offensive_PrimaryDamage: `[UNTRANSLATED] Primary Damage`, + invigorations_offensive_SecondaryDamage: `[UNTRANSLATED] Secondary Damage`, + invigorations_offensive_PrimaryCritChance: `[UNTRANSLATED] Primary Critical Chance`, + invigorations_offensive_SecondaryCritChance: `[UNTRANSLATED] Secondary Critical Chance`, + invigorations_offensive_MeleeCritChance: `[UNTRANSLATED] Melee Critical Chance`, + + invigorations_utility_PowerEfficiency: `[UNTRANSLATED] Power Efficiency`, + invigorations_utility_MovementSpeed: `[UNTRANSLATED] Movement Speed`, + invigorations_utility_ParkourSpeed: `[UNTRANSLATED] Parkour Speed`, + invigorations_utility_Health: `[UNTRANSLATED] Health`, + invigorations_utility_Energy: `[UNTRANSLATED] Energy`, + invigorations_utility_StatusResistance: `[UNTRANSLATED] Status Resistance`, + invigorations_utility_ReloadSpeed: `[UNTRANSLATED] Reload Speed`, + invigorations_utility_HealthRegen: `[UNTRANSLATED] Health Regen`, + invigorations_utility_Armor: `[UNTRANSLATED] Armor`, + invigorations_utility_Jumps: `[UNTRANSLATED] Jumps`, + invigorations_utility_EnergyRegen: `[UNTRANSLATED] Energy Regen`, + + invigorations_offensiveLabel: `[UNTRANSLATED] Offensive Upgrade`, + invigorations_defensiveLabel: `[UNTRANSLATED] Defensive Upgrade`, + invigorations_expiryLabel: `[UNTRANSLATED] Upgrades Expiry (optional)`, + invigorations_applyButton: `[UNTRANSLATED] Apply Upgrades`, + invigorations_clearButton: `[UNTRANSLATED] Clear Upgrades`, + invigorations_noneOption: `[UNTRANSLATED] None`, mods_addRiven: `Ajouter un riven`, mods_fingerprint: `Empreinte`, diff --git a/static/webui/translations/ru.js b/static/webui/translations/ru.js index 20720f84..d5e460aa 100644 --- a/static/webui/translations/ru.js +++ b/static/webui/translations/ru.js @@ -62,6 +62,7 @@ dict = { code_mature: `Подготовить к сражениям`, code_unmature: `Регрессия генетического старения`, code_succChange: `Успешно изменено.`, + code_requiredInvigorationUpgrade: `[UNTRANSLATED] You must select both an offensive and a defensive upgrade.`, login_description: `Войдите, используя учетные данные OpenWF (те же, что и в игре при подключении к этому серверу).`, login_emailLabel: `Адрес электронной почты`, login_passwordLabel: `Пароль`, @@ -125,6 +126,36 @@ dict = { detailedView_valenceBonusLabel: `Бонус Валентности`, detailedView_valenceBonusDescription: `Вы можете установить или убрать бонус валентности с вашего оружия.`, detailedView_modularPartsLabel: `Изменить Модульные Части`, + detailedView_editSuitInvigoration: `[UNTRANSLATED] Edit Suit Invigoration`, + + invigorations_offensive_PowerStrength: `[UNTRANSLATED] Power Strength`, + invigorations_offensive_PowerRange: `[UNTRANSLATED] Power Range`, + invigorations_offensive_PowerDuration: `[UNTRANSLATED] Power Duration`, + invigorations_offensive_MeleeDamage: `[UNTRANSLATED] Melee Damage`, + invigorations_offensive_PrimaryDamage: `[UNTRANSLATED] Primary Damage`, + invigorations_offensive_SecondaryDamage: `[UNTRANSLATED] Secondary Damage`, + invigorations_offensive_PrimaryCritChance: `[UNTRANSLATED] Primary Critical Chance`, + invigorations_offensive_SecondaryCritChance: `[UNTRANSLATED] Secondary Critical Chance`, + invigorations_offensive_MeleeCritChance: `[UNTRANSLATED] Melee Critical Chance`, + + invigorations_utility_PowerEfficiency: `[UNTRANSLATED] Power Efficiency`, + invigorations_utility_MovementSpeed: `[UNTRANSLATED] Movement Speed`, + invigorations_utility_ParkourSpeed: `[UNTRANSLATED] Parkour Speed`, + invigorations_utility_Health: `[UNTRANSLATED] Health`, + invigorations_utility_Energy: `[UNTRANSLATED] Energy`, + invigorations_utility_StatusResistance: `[UNTRANSLATED] Status Resistance`, + invigorations_utility_ReloadSpeed: `[UNTRANSLATED] Reload Speed`, + invigorations_utility_HealthRegen: `[UNTRANSLATED] Health Regen`, + invigorations_utility_Armor: `[UNTRANSLATED] Armor`, + invigorations_utility_Jumps: `[UNTRANSLATED] Jumps`, + invigorations_utility_EnergyRegen: `[UNTRANSLATED] Energy Regen`, + + invigorations_offensiveLabel: `[UNTRANSLATED] Offensive Upgrade`, + invigorations_defensiveLabel: `[UNTRANSLATED] Defensive Upgrade`, + invigorations_expiryLabel: `[UNTRANSLATED] Upgrades Expiry (optional)`, + invigorations_applyButton: `[UNTRANSLATED] Apply Upgrades`, + invigorations_clearButton: `[UNTRANSLATED] Clear Upgrades`, + invigorations_noneOption: `[UNTRANSLATED] None`, mods_addRiven: `Добавить Мод Разлома`, mods_fingerprint: `Отпечаток`, diff --git a/static/webui/translations/zh.js b/static/webui/translations/zh.js index b432b88f..eef6474f 100644 --- a/static/webui/translations/zh.js +++ b/static/webui/translations/zh.js @@ -62,6 +62,7 @@ dict = { code_mature: `成长并战备`, code_unmature: `逆转衰老基因`, code_succChange: `更改成功.`, + code_requiredInvigorationUpgrade: `[UNTRANSLATED] You must select both an offensive and a defensive upgrade.`, login_description: `使用您的 OpenWF 账户凭证登录(与游戏内连接本服务器时使用的昵称相同).`, login_emailLabel: `电子邮箱`, login_passwordLabel: `密码`, @@ -125,6 +126,36 @@ dict = { detailedView_valenceBonusLabel: `效价加成`, detailedView_valenceBonusDescription: `您可以设置或移除武器上的效价加成.`, detailedView_modularPartsLabel: `更换部件`, + detailedView_editSuitInvigoration: `[UNTRANSLATED] Edit Suit Invigoration`, + + invigorations_offensive_PowerStrength: `[UNTRANSLATED] Power Strength`, + invigorations_offensive_PowerRange: `[UNTRANSLATED] Power Range`, + invigorations_offensive_PowerDuration: `[UNTRANSLATED] Power Duration`, + invigorations_offensive_MeleeDamage: `[UNTRANSLATED] Melee Damage`, + invigorations_offensive_PrimaryDamage: `[UNTRANSLATED] Primary Damage`, + invigorations_offensive_SecondaryDamage: `[UNTRANSLATED] Secondary Damage`, + invigorations_offensive_PrimaryCritChance: `[UNTRANSLATED] Primary Critical Chance`, + invigorations_offensive_SecondaryCritChance: `[UNTRANSLATED] Secondary Critical Chance`, + invigorations_offensive_MeleeCritChance: `[UNTRANSLATED] Melee Critical Chance`, + + invigorations_utility_PowerEfficiency: `[UNTRANSLATED] Power Efficiency`, + invigorations_utility_MovementSpeed: `[UNTRANSLATED] Movement Speed`, + invigorations_utility_ParkourSpeed: `[UNTRANSLATED] Parkour Speed`, + invigorations_utility_Health: `[UNTRANSLATED] Health`, + invigorations_utility_Energy: `[UNTRANSLATED] Energy`, + invigorations_utility_StatusResistance: `[UNTRANSLATED] Status Resistance`, + invigorations_utility_ReloadSpeed: `[UNTRANSLATED] Reload Speed`, + invigorations_utility_HealthRegen: `[UNTRANSLATED] Health Regen`, + invigorations_utility_Armor: `[UNTRANSLATED] Armor`, + invigorations_utility_Jumps: `[UNTRANSLATED] Jumps`, + invigorations_utility_EnergyRegen: `[UNTRANSLATED] Energy Regen`, + + invigorations_offensiveLabel: `[UNTRANSLATED] Offensive Upgrade`, + invigorations_defensiveLabel: `[UNTRANSLATED] Defensive Upgrade`, + invigorations_expiryLabel: `[UNTRANSLATED] Upgrades Expiry (optional)`, + invigorations_applyButton: `[UNTRANSLATED] Apply Upgrades`, + invigorations_clearButton: `[UNTRANSLATED] Clear Upgrades`, + invigorations_noneOption: `[UNTRANSLATED] None`, mods_addRiven: `添加裂罅MOD`, mods_fingerprint: `印记`,