Compare commits

..

2 Commits

Author SHA1 Message Date
bdd6de80f8 fix
All checks were successful
Build / build (pull_request) Successful in 1m35s
2025-06-29 00:03:56 +02:00
fd6b6ec9ab feat(webui): Valence Bonus
Some checks failed
Build / build (pull_request) Failing after 39s
Closes #1181
2025-06-28 14:49:38 -07:00
11 changed files with 117 additions and 170 deletions

View File

@ -28,13 +28,12 @@ import { updateWorldStateCollections } from "./services/worldStateService";
JSON.stringify = JSONStringify;
validateConfig();
syncConfigWithDatabase();
mongoose
.connect(config.mongodbUrl)
.then(() => {
logger.info("Connected to MongoDB");
syncConfigWithDatabase();
startWebServer();
void updateWorldStateCollections();

View File

@ -4,8 +4,7 @@ import {
ISetShipCustomizationsRequest,
IShipDecorationsRequest,
IShipDecorationsResponse,
ISetPlacedDecoInfoRequest,
TBootLocation
ISetPlacedDecoInfoRequest
} from "@/src/types/shipTypes";
import { logger } from "@/src/utils/logger";
import { Types } from "mongoose";
@ -15,7 +14,6 @@ import { Guild } from "../models/guildModel";
import { hasGuildPermission } from "./guildService";
import { GuildPermission } from "../types/guildTypes";
import { ExportResources } from "warframe-public-export-plus";
import { RoomsType, TPersonalRoomsDatabaseDocument } from "../types/personalRoomsTypes";
export const setShipCustomizations = async (
accountId: string,
@ -185,19 +183,6 @@ export const handleSetShipDecorations = async (
};
};
const getRoomsForBootLocation = (
personalRooms: TPersonalRoomsDatabaseDocument,
bootLocation: TBootLocation | undefined
): RoomsType[] => {
if (bootLocation == "SHOP") {
return personalRooms.TailorShop.Rooms;
}
if (bootLocation == "APARTMENT") {
return personalRooms.Apartment.Rooms;
}
return personalRooms.Ship.Rooms;
};
export const handleSetPlacedDecoInfo = async (accountId: string, req: ISetPlacedDecoInfoRequest): Promise<void> => {
if (req.GuildId && req.ComponentId) {
const guild = (await Guild.findById(req.GuildId))!;
@ -212,14 +197,14 @@ export const handleSetPlacedDecoInfo = async (accountId: string, req: ISetPlaced
const personalRooms = await getPersonalRooms(accountId);
const room = getRoomsForBootLocation(personalRooms, req.BootLocation).find(room => room.Name === req.Room);
const room = personalRooms.Ship.Rooms.find(room => room.Name === req.Room);
if (!room) {
throw new Error(`unknown room: ${req.Room}`);
throw new Error("room not found");
}
const placedDeco = room.PlacedDecos.id(req.DecoId);
if (!placedDeco) {
throw new Error(`unknown deco id: ${req.DecoId}`);
throw new Error("deco not found");
}
placedDeco.PictureFrameInfo = req.PictureFrameInfo;

View File

@ -154,7 +154,7 @@ export interface ISetPlacedDecoInfoRequest {
DecoId: string;
Room: string;
PictureFrameInfo: IPictureFrameInfo;
BootLocation?: TBootLocation;
BootLocation?: string;
ComponentId?: string;
GuildId?: string;
}

View File

@ -13,7 +13,8 @@
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand">OpenWF WebUI</a>
<div class="ms-auto nav-item dropdown">
<ul class="navbar-nav ms-auto mb-0">
<li class="nav-item dropdown">
<button id="active-lang-name" class="nav-link dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false"></button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item active" href="#" data-lang="en" onclick="event.preventDefault();setLanguage('en');">English</a></li>
@ -31,12 +32,9 @@
<li><a class="dropdown-item" href="#" data-lang="zh" onclick="event.preventDefault();setLanguage('zh');">简体中文</a></li>
<li><a class="dropdown-item" href="#" data-lang="tc" onclick="event.preventDefault();setLanguage('tc');">繁體中文</a></li>
<li><a class="dropdown-item" href="#" data-lang="th" onclick="event.preventDefault();setLanguage('th');">แบบไทย</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item active" href="#" data-loc="theme_dark" data-theme="dark" onclick="event.preventDefault();setTheme('dark');"></a></li>
<li><a class="dropdown-item" href="#" data-loc="theme_light" data-theme="light" onclick="event.preventDefault();setTheme('light');"></a></li>
</ul>
</div>
<div class="nav-item dropdown user-dropdown">
</li>
<li class="nav-item dropdown user-dropdown">
<button class="nav-link dropdown-toggle displayname" data-bs-toggle="dropdown" aria-expanded="false"></button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="/webui/" onclick="doLogout();" data-loc="navbar_logout"></a></li>
@ -44,7 +42,8 @@
<li><a class="dropdown-item" href="#" onclick="event.preventDefault();renameAccount();" data-loc="navbar_renameAccount"></a></li>
<li><a class="dropdown-item" href="#" onclick="event.preventDefault();deleteAccount();" data-loc="navbar_deleteAccount"></a></li>
</ul>
</div>
</li>
</ul>
</div>
</nav>
<div class="container pt-3 pb-3" id="main-view">

View File

@ -230,18 +230,6 @@ function setLanguage(lang) {
}
}
function setActiveTheme(theme) {
document.documentElement.setAttribute("data-bs-theme", theme);
document.querySelector("[data-theme].active").classList.remove("active");
document.querySelector("[data-theme=" + theme + "]").classList.add("active");
}
setActiveTheme(localStorage.getItem("theme") ?? "dark");
function setTheme(theme) {
setActiveTheme(theme);
localStorage.setItem("theme", theme);
}
const webUiModularWeapons = [
"/Lotus/Weapons/Sentients/OperatorAmplifiers/OperatorAmpWeapon",
"/Lotus/Weapons/Ostron/Melee/LotusModularWeapon",
@ -2437,7 +2425,7 @@ async function doMaxPlexus() {
async function doUnlockAllMissions() {
await revalidateAuthz();
await fetch("/custom/completeAllMissions?" + window.authz);
toast(loc("cheats_unlockAllMissions_ok"));
updateInventory();
}
const importSamples = {

View File

@ -136,7 +136,6 @@ dict = {
cheats_skipAllDialogue: `Alle Dialoge überspringen`,
cheats_unlockAllScans: `Alle Scans freischalten`,
cheats_unlockAllMissions: `Alle Missionen freischalten`,
cheats_unlockAllMissions_ok: `[UNTRANSLATED] Success. Please note that you'll need to enter a dojo/relay or relog for the client to refresh the star chart.`,
cheats_infiniteCredits: `Unendlich Credits`,
cheats_infinitePlatinum: `Unendlich Platinum`,
cheats_infiniteEndo: `Unendlich Endo`,
@ -306,8 +305,5 @@ dict = {
damageType_Poison: `Gift`,
damageType_Radiation: `Strahlung`,
theme_dark: `[UNTRANSLATED] Dark Theme`,
theme_light: `[UNTRANSLATED] Light Theme`,
prettier_sucks_ass: ``
};

View File

@ -135,7 +135,6 @@ dict = {
cheats_skipAllDialogue: `Skip All Dialogue`,
cheats_unlockAllScans: `Unlock All Scans`,
cheats_unlockAllMissions: `Unlock All Missions`,
cheats_unlockAllMissions_ok: `Success. Please note that you'll need to enter a dojo/relay or relog for the client to refresh the star chart.`,
cheats_infiniteCredits: `Infinite Credits`,
cheats_infinitePlatinum: `Infinite Platinum`,
cheats_infiniteEndo: `Infinite Endo`,
@ -305,8 +304,5 @@ dict = {
damageType_Poison: `Toxin`,
damageType_Radiation: `Radiation`,
theme_dark: `Dark Theme`,
theme_light: `Light Theme`,
prettier_sucks_ass: ``
};

View File

@ -1,6 +1,6 @@
// Spanish translation by hxedcl
dict = {
general_inventoryUpdateNote: `Para ver los cambios en el juego, necesitas volver a sincronizar tu inventario, por ejemplo, usando el comando /sync del bootstrapper, visitando un dojo o repetidor, o volviendo a iniciar sesión.`,
general_inventoryUpdateNote: `[UNTRANSLATED] Note: To see changes in-game, you need to resync your inventory, e.g. using the bootstrapper's /sync command, visiting a dojo/relay, or relogging.`,
general_addButton: `Agregar`,
general_setButton: `[UNTRANSLATED] Set`,
general_removeButton: `[UNTRANSLATED] Remove`,
@ -136,7 +136,6 @@ dict = {
cheats_skipAllDialogue: `Omitir todos los diálogos`,
cheats_unlockAllScans: `Desbloquear todos los escaneos`,
cheats_unlockAllMissions: `Desbloquear todas las misiones`,
cheats_unlockAllMissions_ok: `[UNTRANSLATED] Success. Please note that you'll need to enter a dojo/relay or relog for the client to refresh the star chart.`,
cheats_infiniteCredits: `Créditos infinitos`,
cheats_infinitePlatinum: `Platino infinito`,
cheats_infiniteEndo: `Endo infinito`,
@ -183,64 +182,64 @@ dict = {
cheats_fastClanAscension: `Ascenso rápido del clan`,
cheats_missionsCanGiveAllRelics: `Las misiones pueden otorgar todas las reliquias`,
cheats_unlockAllSimarisResearchEntries: `Desbloquear todas las entradas de investigación de Simaris`,
cheats_disableDailyTribute: `Desactivar tributo diario`,
cheats_disableDailyTribute: `[UNTRANSLATED] Disable Daily Tribute`,
cheats_spoofMasteryRank: `Rango de maestría simulado (-1 para desactivar)`,
cheats_nightwaveStandingMultiplier: `Multiplicador de Reputación de Onda Nocturna`,
cheats_save: `Guardar`,
cheats_account: `Cuenta`,
cheats_unlockAllFocusSchools: `Desbloquear todas las escuelas de enfoque`,
cheats_helminthUnlockAll: `Subir al máximo el Helminto`,
cheats_addMissingSubsumedAbilities: `Agregar habilidades subsumidas faltantes`,
cheats_addMissingSubsumedAbilities: `[UNTRANSLATED] Add Missing Subsumed Abilities`,
cheats_intrinsicsUnlockAll: `Maximizar todos los intrínsecos`,
cheats_changeSupportedSyndicate: `Sindicatos disponibles`,
cheats_changeButton: `Cambiar`,
cheats_none: `Ninguno`,
worldState: `Estado del mundo`,
worldState_creditBoost: `Potenciador de Créditos`,
worldState_affinityBoost: `Potenciador de Afinidad`,
worldState_resourceBoost: `Potenciador de Recursos`,
worldState_starDays: `Días estelares`,
worldState_galleonOfGhouls: `Galeón de Gules`,
disabled: `Desactivado`,
worldState_we1: `Semana 1`,
worldState_we2: `Semana 2`,
worldState_we3: `Semana 3`,
worldState_eidolonOverride: `Tiempo de las Llanuras de Eidolon`,
worldState_day: `Dia`,
worldState_night: `Noche`,
worldState_vallisOverride: `Tiempo del Valle del Orbe`,
worldState_warm: `Cálido`,
worldState_cold: `Frío`,
worldState_duviriOverride: `Tiempo de Duviri`,
worldState_joy: `Alegría`,
worldState_anger: `Ira`,
worldState_envy: `Envidia`,
worldState_sorrow: `Tristeza`,
worldState_fear: `Miedo`,
worldState_nightwaveOverride: `Volúmen de Onda Nocturna`,
worldState_RadioLegionIntermission13Syndicate: `Mix de Nora Vol. 9`,
worldState_RadioLegionIntermission12Syndicate: `Mix de Nora Vol. 8`,
worldState_RadioLegionIntermission11Syndicate: `Mix de Nora Vol. 7`,
worldState_RadioLegionIntermission10Syndicate: `Mix de Nora Vol. 6 `,
worldState_RadioLegionIntermission9Syndicate: `Mix de Nora Vol. 5`,
worldState_RadioLegionIntermission8Syndicate: `Mix de Nora Vol. 4`,
worldState_RadioLegionIntermission7Syndicate: `Mix de Nora Vol. 3`,
worldState_RadioLegionIntermission6Syndicate: `Mix de Nora Vol. 2`,
worldState_RadioLegionIntermission5Syndicate: `Mix de Nora Vol. 1`,
worldState_RadioLegionIntermission4Syndicate: `Elección de Nora`,
worldState_RadioLegionIntermission3Syndicate: `Intermedio III`,
worldState_RadioLegion3Syndicate: `El Artesano de Cristal`,
worldState_RadioLegionIntermission2Syndicate: `Intermedio II`,
worldState_RadioLegion2Syndicate: `El Emisario`,
worldState_RadioLegionIntermissionSyndicate: `Intermedio I`,
worldState_RadioLegionSyndicate: `El lobo de Saturno Seis`,
worldState_fissures: `Fisuras`,
normal: `Normal`,
worldState_allAtOnceNormal: `Todo a la vez, normal`,
worldState_allAtOnceSteelPath: `Todo a la vez, Camino de Acero`,
worldState_theCircuitOverride: `Cambio del Circuito`,
worldState_darvoStockMultiplier: `Multiplicador de stock de Darvo`,
worldState: `[UNTRANSLATED] World State`,
worldState_creditBoost: `[UNTRANSLATED] Credit Boost`,
worldState_affinityBoost: `[UNTRANSLATED] Affinity Boost`,
worldState_resourceBoost: `[UNTRANSLATED] Resource Boost`,
worldState_starDays: `[UNTRANSLATED] Star Days`,
worldState_galleonOfGhouls: `[UNTRANSLATED] Galleon of Ghouls`,
disabled: `[UNTRANSLATED] Disabled`,
worldState_we1: `[UNTRANSLATED] Weekend 1`,
worldState_we2: `[UNTRANSLATED] Weekend 2`,
worldState_we3: `[UNTRANSLATED] Weekend 3`,
worldState_eidolonOverride: `[UNTRANSLATED] Eidolon Override`,
worldState_day: `[UNTRANSLATED] Day`,
worldState_night: `[UNTRANSLATED] Night`,
worldState_vallisOverride: `[UNTRANSLATED] Orb Vallis Override`,
worldState_warm: `[UNTRANSLATED] Warm`,
worldState_cold: `[UNTRANSLATED] Cold`,
worldState_duviriOverride: `[UNTRANSLATED] Duviri Override`,
worldState_joy: `[UNTRANSLATED] Joy`,
worldState_anger: `[UNTRANSLATED] Anger`,
worldState_envy: `[UNTRANSLATED] Envy`,
worldState_sorrow: `[UNTRANSLATED] Sorrow`,
worldState_fear: `[UNTRANSLATED] Fear`,
worldState_nightwaveOverride: `[UNTRANSLATED] Nightwave Override`,
worldState_RadioLegionIntermission13Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 9`,
worldState_RadioLegionIntermission12Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 8`,
worldState_RadioLegionIntermission11Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 7`,
worldState_RadioLegionIntermission10Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 6`,
worldState_RadioLegionIntermission9Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 5`,
worldState_RadioLegionIntermission8Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 4`,
worldState_RadioLegionIntermission7Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 3`,
worldState_RadioLegionIntermission6Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 2`,
worldState_RadioLegionIntermission5Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 1`,
worldState_RadioLegionIntermission4Syndicate: `[UNTRANSLATED] Nora's Choice`,
worldState_RadioLegionIntermission3Syndicate: `[UNTRANSLATED] Intermission III`,
worldState_RadioLegion3Syndicate: `[UNTRANSLATED] Glassmaker`,
worldState_RadioLegionIntermission2Syndicate: `[UNTRANSLATED] Intermission II`,
worldState_RadioLegion2Syndicate: `[UNTRANSLATED] The Emissary`,
worldState_RadioLegionIntermissionSyndicate: `[UNTRANSLATED] Intermission I`,
worldState_RadioLegionSyndicate: `[UNTRANSLATED] The Wolf of Saturn Six`,
worldState_fissures: `[UNTRANSLATED] Fissures`,
normal: `[UNTRANSLATED] Normal`,
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
worldState_theCircuitOverride: `[UNTRANSLATED] The Circuit Override`,
worldState_darvoStockMultiplier: `[UNTRANSLATED] Darvo Stock Multiplier`,
import_importNote: `Puedes proporcionar una respuesta de inventario completa o parcial (representación del cliente) aquí. Todos los campos compatibles con el importador <b>serán sobrescritos</b> en tu cuenta.`,
import_submit: `Enviar`,
@ -265,7 +264,7 @@ dict = {
upgrade_WarframeGlobeEffectEnergy: `+|VAL|% de efectividad de orbes de energía`,
upgrade_WarframeGlobeEffectHealth: `+|VAL|% de efectividad de orbes de salud`,
upgrade_WarframeHealthMax: `+|VAL| de salud máxima`,
upgrade_WarframeHPBoostFromImpact: `+|VAL1| de salud al eliminar con daño explosivo (máx. |VAL2| de salud)`,
upgrade_WarframeHPBoostFromImpact: `[UNTRANSLATED] +|VAL1| Health on kill with Blast Damage (Max |VAL2| Health)`,
upgrade_WarframeParkourVelocity: `+|VAL|% de velocidad de parkour`,
upgrade_WarframeRadiationDamageBoost: `+|VAL|% de daño de habilidades a enemigos con estado radiactivo`,
upgrade_WarframeRegen: `+|VAL| de regeneración de salud por segundo`,
@ -288,7 +287,7 @@ dict = {
upgrade_DamageReductionOnHack: `75% de reducción de daño al hackear`,
upgrade_OnExecutionReviveCompanion: `Las ejecuciones reducen el tiempo de recuperación del compañero en 15s`,
upgrade_OnExecutionParkourSpeed: `+60% de velocidad de parkour durante 15s tras una ejecución`,
upgrade_AvatarTimeLimitIncrease: `+8s para hackear`,
upgrade_AvatarTimeLimitIncrease: `[UNTRANSLATED] +8s to Hacking`,
upgrade_ElectrifyOnHack: `Electrocuta a los enemigos en un radio de 20m al hackear`,
upgrade_OnExecutionTerrify: `50% de probabilidad de que enemigos en un radio de 15m entren en pánico por 8s tras una ejecución`,
upgrade_OnHackLockers: `Desbloquea 5 casilleros en un radio de 20m tras hackear`,
@ -306,8 +305,5 @@ dict = {
damageType_Poison: `Tóxico`,
damageType_Radiation: `Radioativo`,
theme_dark: `[UNTRANSLATED] Dark Theme`,
theme_light: `[UNTRANSLATED] Light Theme`,
prettier_sucks_ass: ``
};

View File

@ -136,7 +136,6 @@ dict = {
cheats_skipAllDialogue: `Passer les dialogues`,
cheats_unlockAllScans: `Débloquer tous les scans`,
cheats_unlockAllMissions: `Débloquer toutes les missions`,
cheats_unlockAllMissions_ok: `[UNTRANSLATED] Success. Please note that you'll need to enter a dojo/relay or relog for the client to refresh the star chart.`,
cheats_infiniteCredits: `Crédits infinis`,
cheats_infinitePlatinum: `Platinum infini`,
cheats_infiniteEndo: `Endo infini`,
@ -298,9 +297,6 @@ dict = {
upgrade_SwiftExecute: `Vitesse des miséricordes augmentée de 50%`,
upgrade_OnHackInvis: `Invisible pendant 15 secondes après un piratage`,
theme_dark: `[UNTRANSLATED] Dark Theme`,
theme_light: `[UNTRANSLATED] Light Theme`,
damageType_Electricity: `Électrique`,
damageType_Fire: `Feu`,
damageType_Freeze: `Glace`,

View File

@ -136,7 +136,6 @@ dict = {
cheats_skipAllDialogue: `Пропустить все диалоги`,
cheats_unlockAllScans: `Разблокировать все сканирования`,
cheats_unlockAllMissions: `Разблокировать все миссии`,
cheats_unlockAllMissions_ok: `[UNTRANSLATED] Success. Please note that you'll need to enter a dojo/relay or relog for the client to refresh the star chart.`,
cheats_infiniteCredits: `Бесконечные кредиты`,
cheats_infinitePlatinum: `Бесконечная платина`,
cheats_infiniteEndo: `Бесконечное эндо`,
@ -306,8 +305,5 @@ dict = {
damageType_Poison: `Токсин`,
damageType_Radiation: `Радиация`,
theme_dark: `[UNTRANSLATED] Dark Theme`,
theme_light: `[UNTRANSLATED] Light Theme`,
prettier_sucks_ass: ``
};

View File

@ -1,6 +1,6 @@
// Chinese translation by meb154, bishan178 & Corvus
dict = {
general_inventoryUpdateNote: `注意:要在游戏中查看更改,您需要重新同步库存,例如使用引导程序的 /sync 命令、访问道场 / 中继站或重新登录`,
general_inventoryUpdateNote: `[UNTRANSLATED] Note: To see changes in-game, you need to resync your inventory, e.g. using the bootstrapper's /sync command, visiting a dojo/relay, or relogging.`,
general_addButton: `添加`,
general_setButton: `[UNTRANSLATED] Set`,
general_removeButton: `[UNTRANSLATED] Remove`,
@ -136,7 +136,6 @@ dict = {
cheats_skipAllDialogue: `跳过所有对话`,
cheats_unlockAllScans: `解锁所有扫描`,
cheats_unlockAllMissions: `解锁所有任务`,
cheats_unlockAllMissions_ok: `[UNTRANSLATED] Success. Please note that you'll need to enter a dojo/relay or relog for the client to refresh the star chart.`,
cheats_infiniteCredits: `无限现金`,
cheats_infinitePlatinum: `无限白金`,
cheats_infiniteEndo: `无限内融核心`,
@ -183,7 +182,7 @@ dict = {
cheats_fastClanAscension: `快速升级氏族`,
cheats_missionsCanGiveAllRelics: `任务可获取所有遗物`,
cheats_unlockAllSimarisResearchEntries: `解锁所有Simaris研究条目`,
cheats_disableDailyTribute: `禁用每日登录奖励`,
cheats_disableDailyTribute: `[UNTRANSLATED] Disable Daily Tribute`,
cheats_spoofMasteryRank: `伪造精通段位(-1为禁用)`,
cheats_nightwaveStandingMultiplier: `午夜电波声望倍率`,
cheats_save: `保存`,
@ -240,59 +239,59 @@ dict = {
worldState_allAtOnceNormal: `全部开启(普通)`,
worldState_allAtOnceSteelPath: `全部开启(钢铁之路)`,
worldState_theCircuitOverride: `无尽回廊任务循环配置:`,
worldState_darvoStockMultiplier: `Darvo特惠库存倍率`,
worldState_darvoStockMultiplier: `[UNTRANSLATED] Darvo Stock Multiplier`,
import_importNote: `您可以在此处提供完整或部分库存响应(客户端表示)。支持的所有字段<b>将被覆盖</b>到您的账户中。`,
import_submit: `提交`,
import_samples: `示例:`,
import_samples_maxFocus: `所有专精学派完全精通`,
upgrade_Equilibrium: `拾取生命球+|VAL|% 能量,拾取能量球+|VAL|% 生命`,
upgrade_Equilibrium: `+|VAL|% 能量 来自生命球, +|VAL|% 生命 来自能量球`,
upgrade_MeleeCritDamage: `+|VAL|% 近战暴击伤害`,
upgrade_PrimaryStatusChance: `+|VAL|% 主武器触发几率`,
upgrade_PrimaryStatusChance: `+|VAL|% 主武器触发几率`,
upgrade_SecondaryCritChance: `+|VAL|% 次要武器暴击几率`,
upgrade_WarframeAbilityDuration: `+|VAL|% 技能持续时间`,
upgrade_WarframeAbilityStrength: `+|VAL|% 技能强度`,
upgrade_WarframeArmourMax: `+|VAL| 护甲`,
upgrade_WarframeBlastProc: `使用爆炸伤害击杀敌人时恢复+|VAL| 护盾`,
upgrade_WarframeBlastProc: `+|VAL| 护盾在击杀时附带爆炸伤害`,
upgrade_WarframeCastingSpeed: `+|VAL|% 施放速度`,
upgrade_WarframeCorrosiveDamageBoost: `对受腐蚀异常影响的敌人+|VAL|% 额外技能伤害`,
upgrade_WarframeCorrosiveStack: `腐蚀异常最大堆叠层数+|VAL|`,
upgrade_WarframeCritDamageBoost: `+|VAL|% 近战暴击伤害 (最大能量超过500伤害翻倍)`,
upgrade_WarframeElectricDamage: `主要武器获得+|VAL1|% 电击伤害 (每装备一颗深红,蔚蓝,紫晶源力石+|VAL2|% 额外点击伤害 )`,
upgrade_WarframeElectricDamageBoost: `对受电击异常影响的敌人+|VAL|% 额外技能伤害`,
upgrade_WarframeCorrosiveDamageBoost: `对受腐蚀状态影响的敌人 +|VAL|% 技能伤害`,
upgrade_WarframeCorrosiveStack: `腐蚀状态最大堆叠数 +|VAL|`,
upgrade_WarframeCritDamageBoost: `+|VAL|% 近战暴击伤害 (500能量以上翻倍)`,
upgrade_WarframeElectricDamage: `+|VAL1|% 主武器伤害效果 (+|VAL2|% 每附加一个碎片)`,
upgrade_WarframeElectricDamageBoost: `对受电能状态影响的敌人 +|VAL|% 技能伤害`,
upgrade_WarframeEnergyMax: `+|VAL| 最大能量`,
upgrade_WarframeGlobeEffectEnergy: `+|VAL|% 能量球效果`,
upgrade_WarframeGlobeEffectHealth: `+|VAL|% 生命球效果`,
upgrade_WarframeHealthMax: `+|VAL| 生命`,
upgrade_WarframeHPBoostFromImpact: ` 通过爆炸伤害击杀的每个敌人可增加|VAL1| 生命上限 (最大 |VAL2| 生命上限)`,
upgrade_WarframeHealthMax: `+|VAL| 生命`,
upgrade_WarframeHPBoostFromImpact: `[UNTRANSLATED] +|VAL1| Health on kill with Blast Damage (Max |VAL2| Health)`,
upgrade_WarframeParkourVelocity: `+|VAL|% 跑酷速度`,
upgrade_WarframeRadiationDamageBoost: `对受辐射状态影响的敌人 +|VAL|% 技能伤害`,
upgrade_WarframeRegen: `+|VAL| /s生命再生`,
upgrade_WarframeShieldMax: `+|VAL| 护盾`,
upgrade_WarframeStartingEnergy: `进任务时+|VAL|% 初始能量`,
upgrade_WarframeToxinDamage: `毒素伤害额外+|VAL|% 伤害`,
upgrade_WarframeToxinHeal: `每当敌人受到毒素伤害时回复|VAL| 生命值`,
upgrade_WarframeRegen: `+|VAL| 生命再生/s`,
upgrade_WarframeShieldMax: `+|VAL| 护盾`,
upgrade_WarframeStartingEnergy: `+|VAL|% 能量出生时`,
upgrade_WarframeToxinDamage: `+|VAL|% 毒素伤害效果`,
upgrade_WarframeToxinHeal: `+|VAL| 生命 对毒素状态的敌人造成伤害时`,
upgrade_WeaponCritBoostFromHeat: `每个被火焰伤害杀死的敌人, 增加|VAL1|% 次要武器暴击几率 (最大 |VAL2|%)`,
upgrade_AvatarAbilityRange: `+7.5% 技能范围`,
upgrade_AvatarAbilityEfficiency: `+5% 技能效率`,
upgrade_AvatarEnergyRegen: `+0.5 能量再生/秒`,
upgrade_AvatarEnemyRadar: `+5米 敌雷达`,
upgrade_AvatarLootRadar: `+7米 寻物雷达`,
upgrade_AvatarEnemyRadar: `+5米 雷达`,
upgrade_AvatarLootRadar: `+7米 战利品雷达`,
upgrade_WeaponAmmoMax: `+15% 弹药最大容量`,
upgrade_EnemyArmorReductionAura: `-3% 敌方护甲`,
upgrade_OnExecutionAmmo: `怜悯之击可装填100%主要武器和次要武器弹匣容量`,
upgrade_OnExecutionHealthDrop: `怜悯之击有100%几率掉落生命球`,
upgrade_OnExecutionEnergyDrop: `怜悯之击有50%几率掉落能量`,
upgrade_OnFailHackReset: `入侵失败后有+50%几率重新尝`,
upgrade_OnExecutionAmmo: `怜悯之击 100% 补充主次要武器弹匣`,
upgrade_OnExecutionHealthDrop: `怜悯之击 100% 几率 掉落生命球`,
upgrade_OnExecutionEnergyDrop: `怜悯之击 50% 几率 掉落生命`,
upgrade_OnFailHackReset: `+50% 在入侵失败时重`,
upgrade_DamageReductionOnHack: `入侵时,+75% 伤害减免`,
upgrade_OnExecutionReviveCompanion: `怜悯之击减少15秒同伴复苏时间 `,
upgrade_OnExecutionParkourSpeed: `怜悯之击后+60% 跑酷速度持续15秒 `,
upgrade_OnExecutionReviveCompanion: `怜悯之击 减少同伴复苏时间 15秒`,
upgrade_OnExecutionParkourSpeed: `怜悯之击 15秒内 +60% 跑酷速度`,
upgrade_AvatarTimeLimitIncrease: `+8秒 入侵时间`,
upgrade_ElectrifyOnHack: `入侵时震慑20米之内的敌人`,
upgrade_OnExecutionTerrify: `怜悯之击有50%几率让15米以内的敌人进入恐惧状态8秒`,
upgrade_OnExecutionTerrify: `怜悯之击 50% 几率让 15米 以内的敌人恐慌`,
upgrade_OnHackLockers: `入侵后解锁20米内的5个储物柜`,
upgrade_OnExecutionBlind: `怜悯之击致盲18米范围内的敌人`,
upgrade_OnExecutionBlind: `怜悯之击 致盲18米之内的敌人`,
upgrade_OnExecutionDrainPower: `怜悯之击会使下一个技能有100%的机会获得+50%的技能强度`,
upgrade_OnHackSprintSpeed: `入侵后+75%冲刺速度持续15秒`,
upgrade_SwiftExecute: `怜悯之击速度提升50%`,
@ -306,8 +305,5 @@ dict = {
damageType_Poison: `毒素`,
damageType_Radiation: `辐射`,
theme_dark: `[UNTRANSLATED] Dark Theme`,
theme_light: `[UNTRANSLATED] Light Theme`,
prettier_sucks_ass: ``
};