XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

SpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 1 Star 0
返回提交历史

XFEstudio/SpaceNinjaServer

feat(webui): Change weapon Modular Parts (#2471)

Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2471 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>

a16e2716
AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
提交于

代码差异

10 个文件 +184 -50
Added src/controllers/custom/changeModularPartsController.ts +65 -0
@@ -0,0 +1,65 @@
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 changeModularPartsController: RequestHandler = async (req, res) => {
7 const accountId = await getAccountIdForRequest(req);
8 const request = req.body as IUpdateFingerPrintRequest;
9 const inventory = await getInventory(accountId, request.category);
10 const item = inventory[request.category].id(request.oid);
11 if (item) {
12 item.ModularParts = request.modularParts;
13
14 request.modularParts.forEach(part => {
15 const categoryMap = mapping[part];
16 if (categoryMap && categoryMap[request.category]) {
17 item.ItemType = categoryMap[request.category]!;
18 }
19 });
20 await inventory.save();
21 }
22 res.end();
23 };
24
25 interface IUpdateFingerPrintRequest {
26 category: TEquipmentKey;
27 oid: string;
28 modularParts: string[];
29 }
30
31 const mapping: Partial<Record<string, Partial<Record<TEquipmentKey, string>>>> = {
32 "/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelAPart": {
33 LongGuns: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryShotgun",
34 Pistols: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryShotgun"
35 },
36 "/Lotus/Weapons/Infested/Pistols/InfKitGun/Barrels/InfBarrelEgg/InfModularBarrelEggPart": {
37 LongGuns: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryShotgun",
38 Pistols: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryShotgun"
39 },
40 "/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelBPart": {
41 LongGuns: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary",
42 Pistols: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondary"
43 },
44 "/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelCPart": {
45 LongGuns: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary",
46 Pistols: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondary"
47 },
48 "/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelDPart": {
49 LongGuns: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryBeam",
50 Pistols: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryBeam"
51 },
52 "/Lotus/Weapons/Infested/Pistols/InfKitGun/Barrels/InfBarrelBeam/InfModularBarrelBeamPart": {
53 LongGuns: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryBeam",
54 Pistols: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryBeam"
55 },
56 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadA": {
57 MoaPets: "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetAPowerSuit"
58 },
59 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadB": {
60 MoaPets: "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetBPowerSuit"
61 },
62 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadC": {
63 MoaPets: "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetCPowerSuit"
64 }
65 };
Modified src/routes/custom.ts +2 -0
@@ -25,6 +25,7 @@ import { manageQuestsController } from "@/src/controllers/custom/manageQuestsCon
25 25 import { setEvolutionProgressController } from "@/src/controllers/custom/setEvolutionProgressController";
26 26 import { setBoosterController } from "@/src/controllers/custom/setBoosterController";
27 27 import { updateFingerprintController } from "@/src/controllers/custom/updateFingerprintController";
28 import { changeModularPartsController } from "@/src/controllers/custom/changeModularPartsController";
28 29
29 30 import { getConfigController, setConfigController } from "@/src/controllers/custom/configController";
30 31
@@ -55,6 +56,7 @@ customRouter.post("/manageQuests", manageQuestsController);
55 56 customRouter.post("/setEvolutionProgress", setEvolutionProgressController);
56 57 customRouter.post("/setBooster", setBoosterController);
57 58 customRouter.post("/updateFingerprint", updateFingerprintController);
59 customRouter.post("/changeModularParts", changeModularPartsController);
58 60
59 61 customRouter.post("/getConfig", getConfigController);
60 62 customRouter.post("/setConfig", setConfigController);
Modified static/webui/index.html +6 -0
@@ -478,6 +478,12 @@
478 478 </table>
479 479 </div>
480 480 </div>
481 <div id="modularParts-card" class="card mb-3 d-none">
482 <h5 class="card-header" data-loc="detailedView_modularPartsLabel"></h5>
483 <div class="card-body">
484 <form id="modularParts-form" class="input-group mb-3" onsubmit="handleModularPartsChange(event)"></form>
485 </div>
486 </div>
481 487 <div id="valenceBonus-card" class="card mb-3 d-none">
482 488 <h5 class="card-header" data-loc="detailedView_valenceBonusLabel"></h5>
483 489 <div class="card-body">
Modified static/webui/script.js +99 -50
@@ -730,7 +730,10 @@ function updateInventory() {
730 730 td.appendChild(a);
731 731 }
732 732
733 if (["Suits", "LongGuns", "Pistols", "Melee", "SpaceGuns", "SpaceMelee"].includes(category)) {
733 if (
734 ["Suits", "LongGuns", "Pistols", "Melee", "SpaceGuns", "SpaceMelee"].includes(category) ||
735 modularWeapons.includes(item.ItemType)
736 ) {
734 737 const a = document.createElement("a");
735 738 a.href = "/webui/detailedView?productCategory=" + category + "&itemId=" + item.ItemId.$oid;
736 739 a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M278.5 215.6L23 471c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l57-57h68c49.7 0 97.9-14.4 139-41c11.1-7.2 5.5-23-7.8-23c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l81-24.3c2.5-.8 4.8-2.1 6.7-4l22.4-22.4c10.1-10.1 2.9-27.3-11.3-27.3l-32.2 0c-5.1 0-9.2-4.1-9.2-9.2c0-4.1 2.7-7.6 6.5-8.8l112-33.6c4-1.2 7.4-3.9 9.3-7.7C506.4 207.6 512 184.1 512 160c0-41-16.3-80.3-45.3-109.3l-5.5-5.5C432.3 16.3 393 0 352 0s-80.3 16.3-109.3 45.3L139 149C91 197 64 262.1 64 330v55.3L253.6 195.8c6.2-6.2 16.4-6.2 22.6 0c5.4 5.4 6.1 13.6 2.2 19.8z"/></svg>`;
@@ -1239,6 +1242,35 @@ function updateInventory() {
1239 1242 document.getElementById("valenceBonus-procent").value = Math.round(buffValue * 1000) / 10;
1240 1243 }
1241 1244 }
1245 if (modularWeapons.includes(item.ItemType)) {
1246 document.getElementById("modularParts-card").classList.remove("d-none");
1247 const form = document.getElementById("modularParts-form");
1248 form.innerHTML = "";
1249 const requiredParts = getRequiredParts(category, item.ItemType);
1250
1251 requiredParts.forEach(modularPart => {
1252 const input = document.createElement("input");
1253 input.classList.add("form-control");
1254 input.id = "detailedView-modularPart-" + modularPart;
1255 input.setAttribute("list", "datalist-ModularParts-" + modularPart);
1256
1257 const datalist = document.getElementById("datalist-ModularParts-" + modularPart);
1258 const options = Array.from(datalist.options);
1259
1260 input.value =
1261 options.find(option => item.ModularParts.includes(option.getAttribute("data-key")))
1262 ?.value || "";
1263 form.appendChild(input);
1264 });
1265
1266 const changeButton = document.createElement("button");
1267 changeButton.classList.add("btn");
1268 changeButton.classList.add("btn-primary");
1269 changeButton.type = "submit";
1270 changeButton.setAttribute("data-loc", "cheats_changeButton");
1271 changeButton.innerHTML = loc("cheats_changeButton");
1272 form.appendChild(changeButton);
1273 }
1242 1274 } else {
1243 1275 single.loadRoute("/webui/inventory");
1244 1276 }
@@ -1338,47 +1370,41 @@ function doAcquireEquipment(category) {
1338 1370 });
1339 1371 }
1340 1372
1341 function doAcquireModularEquipment(category, WeaponType) {
1342 let requiredParts;
1343 let Parts = [];
1373 function getRequiredParts(category, WeaponType) {
1344 1374 switch (category) {
1345 case "HoverBoards":
1346 WeaponType = "/Lotus/Types/Vehicles/Hoverboard/HoverboardSuit";
1347 requiredParts = ["HB_DECK", "HB_ENGINE", "HB_FRONT", "HB_JET"];
1348 break;
1375 case "Hoverboards":
1376 return ["HB_DECK", "HB_ENGINE", "HB_FRONT", "HB_JET"];
1377
1349 1378 case "OperatorAmps":
1350 requiredParts = ["AMP_OCULUS", "AMP_CORE", "AMP_BRACE"];
1351 break;
1379 return ["AMP_OCULUS", "AMP_CORE", "AMP_BRACE"];
1380
1352 1381 case "Melee":
1353 requiredParts = ["BLADE", "HILT", "HILT_WEIGHT"];
1354 break;
1382 return ["BLADE", "HILT", "HILT_WEIGHT"];
1383
1355 1384 case "LongGuns":
1356 requiredParts = ["GUN_BARREL", "GUN_PRIMARY_HANDLE", "GUN_CLIP"];
1357 break;
1385 return ["GUN_BARREL", "GUN_PRIMARY_HANDLE", "GUN_CLIP"];
1386
1358 1387 case "Pistols":
1359 requiredParts = ["GUN_BARREL", "GUN_SECONDARY_HANDLE", "GUN_CLIP"];
1360 break;
1388 return ["GUN_BARREL", "GUN_SECONDARY_HANDLE", "GUN_CLIP"];
1389
1361 1390 case "MoaPets":
1362 if (WeaponType == "/Lotus/Types/Friendly/Pets/MoaPets/MoaPetPowerSuit") {
1363 requiredParts = ["MOA_ENGINE", "MOA_PAYLOAD", "MOA_HEAD", "MOA_LEG"];
1364 } else {
1365 requiredParts = ["ZANUKA_BODY", "ZANUKA_HEAD", "ZANUKA_LEG", "ZANUKA_TAIL"];
1366 }
1367 break;
1368 case "KubrowPets":
1369 if (
1370 [
1371 "/Lotus/Types/Friendly/Pets/CreaturePets/VulpineInfestedCatbrowPetPowerSuit",
1372 "/Lotus/Types/Friendly/Pets/CreaturePets/HornedInfestedCatbrowPetPowerSuit",
1373 "/Lotus/Types/Friendly/Pets/CreaturePets/ArmoredInfestedCatbrowPetPowerSuit"
1374 ].includes(WeaponType)
1375 ) {
1376 requiredParts = ["CATBROW_ANTIGEN", "CATBROW_MUTAGEN"];
1377 } else {
1378 requiredParts = ["KUBROW_ANTIGEN", "KUBROW_MUTAGEN"];
1379 }
1380 break;
1391 return WeaponType === "/Lotus/Types/Friendly/Pets/MoaPets/MoaPetPowerSuit"
1392 ? ["MOA_ENGINE", "MOA_PAYLOAD", "MOA_HEAD", "MOA_LEG"]
1393 : ["ZANUKA_BODY", "ZANUKA_HEAD", "ZANUKA_LEG", "ZANUKA_TAIL"];
1394
1395 case "KubrowPets": {
1396 return WeaponType.endsWith("InfestedCatbrowPetPowerSuit")
1397 ? ["CATBROW_ANTIGEN", "CATBROW_MUTAGEN"]
1398 : ["KUBROW_ANTIGEN", "KUBROW_MUTAGEN"];
1399 }
1381 1400 }
1401 }
1402
1403 function doAcquireModularEquipment(category, WeaponType) {
1404 if (category === "Hoverboards") WeaponType = "/Lotus/Types/Vehicles/Hoverboard/HoverboardSuit";
1405 const requiredParts = getRequiredParts(category, WeaponType);
1406 let Parts = [];
1407
1382 1408 requiredParts.forEach(part => {
1383 1409 const partName = getKey(document.getElementById("acquire-type-" + category + "-" + part));
1384 1410 if (partName) {
@@ -1495,7 +1521,7 @@ function doAcquireEvolution() {
1495 1521 setEvolutionProgress([{ ItemType: uniqueName, Rank: permanentEvolutionWeapons.has(uniqueName) ? 0 : 1 }]);
1496 1522 }
1497 1523
1498 $("input[list]").on("input", function () {
1524 $(document).on("input", "input[list]", function () {
1499 1525 $(this).removeClass("is-invalid");
1500 1526 });
1501 1527
@@ -2202,6 +2228,8 @@ single.getRoute("#detailedView-route").on("beforeload", function () {
2202 2228 document.getElementById("detailedView-title").textContent = "";
2203 2229 document.querySelector("#detailedView-route .text-body-secondary").textContent = "";
2204 2230 document.getElementById("archonShards-card").classList.add("d-none");
2231 document.getElementById("modularParts-card").classList.add("d-none");
2232 document.getElementById("modularParts-form").innerHTML = "";
2205 2233 document.getElementById("valenceBonus-card").classList.add("d-none");
2206 2234 if (window.didInitialInventoryUpdate) {
2207 2235 updateInventory();
@@ -2359,22 +2387,10 @@ function handleModularSelection(category) {
2359 2387 modularFieldsZanuka.style.display = "none";
2360 2388 }
2361 2389 } else if (inventoryCategory === "KubrowPets") {
2362 if (
2363 [
2364 "/Lotus/Types/Friendly/Pets/CreaturePets/VulpineInfestedCatbrowPetPowerSuit",
2365 "/Lotus/Types/Friendly/Pets/CreaturePets/HornedInfestedCatbrowPetPowerSuit",
2366 "/Lotus/Types/Friendly/Pets/CreaturePets/ArmoredInfestedCatbrowPetPowerSuit"
2367 ].includes(key)
2368 ) {
2390 if (key.endsWith("InfestedCatbrowPetPowerSuit")) {
2369 2391 modularFieldsCatbrow.style.display = "";
2370 2392 modularFieldsKubrow.style.display = "none";
2371 } else if (
2372 [
2373 "/Lotus/Types/Friendly/Pets/CreaturePets/VizierPredatorKubrowPetPowerSuit",
2374 "/Lotus/Types/Friendly/Pets/CreaturePets/PharaohPredatorKubrowPetPowerSuit",
2375 "/Lotus/Types/Friendly/Pets/CreaturePets/MedjayPredatorKubrowPetPowerSuit"
2376 ].includes(key)
2377 ) {
2393 } else if (key.endsWith("PredatorKubrowPetPowerSuit")) {
2378 2394 modularFieldsCatbrow.style.display = "none";
2379 2395 modularFieldsKubrow.style.display = "";
2380 2396 } else {
@@ -2813,3 +2829,36 @@ async function markAllAsRead() {
2813 2829 }
2814 2830 toast(loc(any ? "code_succRelog" : "code_nothingToDo"));
2815 2831 }
2832
2833 function handleModularPartsChange(event) {
2834 event.preventDefault();
2835 const urlParams = new URLSearchParams(window.location.search);
2836 const form = document.getElementById("modularParts-form");
2837 const inputs = form.querySelectorAll("input");
2838 const modularParts = [];
2839 inputs.forEach(input => {
2840 const key = getKey(input);
2841 if (!key) {
2842 input.classList.add("is-invalid");
2843 } else {
2844 modularParts.push(key);
2845 }
2846 });
2847
2848 if (inputs.length == modularParts.length) {
2849 revalidateAuthz().then(() => {
2850 $.post({
2851 url: "/custom/changeModularParts?" + window.authz,
2852 contentType: "application/json",
2853 data: JSON.stringify({
2854 category: urlParams.get("productCategory"),
2855 oid: urlParams.get("itemId"),
2856 modularParts
2857 })
2858 }).then(function () {
2859 toast(loc("code_succChange"));
2860 updateInventory();
2861 });
2862 });
2863 }
2864 }
Modified static/webui/translations/de.js +2 -0
@@ -61,6 +61,7 @@ dict = {
61 61 code_pigment: `Pigment`,
62 62 code_mature: `Für den Kampf auswachsen lassen`,
63 63 code_unmature: `Genetisches Altern zurücksetzen`,
64 code_succChange: `[UNTRANSLATED] Successfully changed.`,
64 65 login_description: `Melde dich mit deinem OpenWF-Account an (denselben Angaben wie im Spiel, wenn du dich mit diesem Server verbindest).`,
65 66 login_emailLabel: `E-Mail-Adresse`,
66 67 login_passwordLabel: `Passwort`,
@@ -123,6 +124,7 @@ dict = {
123 124 detailedView_archonShardsDescription2: `Hinweis: Jede Archon-Scherbe benötigt beim Laden etwas Zeit, um angewendet zu werden.`,
124 125 detailedView_valenceBonusLabel: `Valenz-Bonus`,
125 126 detailedView_valenceBonusDescription: `[UNTRANSLATED] You can set or remove the Valence Bonus from your weapon.`,
127 detailedView_modularPartsLabel: `[UNTRANSLATED] Change Modular Parts`,
126 128
127 129 mods_addRiven: `Riven hinzufügen`,
128 130 mods_fingerprint: `Fingerabdruck`,
Modified static/webui/translations/en.js +2 -0
@@ -60,6 +60,7 @@ dict = {
60 60 code_pigment: `Pigment`,
61 61 code_mature: `Mature for combat`,
62 62 code_unmature: `Regress genetic aging`,
63 code_succChange: `Successfully changed.`,
63 64 login_description: `Login using your OpenWF account credentials (same as in-game when connecting to this server).`,
64 65 login_emailLabel: `Email address`,
65 66 login_passwordLabel: `Password`,
@@ -122,6 +123,7 @@ dict = {
122 123 detailedView_archonShardsDescription2: `Note that each archon shard takes some time to be applied when loading in.`,
123 124 detailedView_valenceBonusLabel: `Valence Bonus`,
124 125 detailedView_valenceBonusDescription: `You can set or remove the Valence Bonus from your weapon.`,
126 detailedView_modularPartsLabel: `Change Modular Parts`,
125 127
126 128 mods_addRiven: `Add Riven`,
127 129 mods_fingerprint: `Fingerprint`,
Modified static/webui/translations/es.js +2 -0
@@ -61,6 +61,7 @@ dict = {
61 61 code_pigment: `Pigmento`,
62 62 code_mature: `Listo para el combate`,
63 63 code_unmature: `Regresar el envejecimiento genético`,
64 code_succChange: `[UNTRANSLATED] Successfully changed.`,
64 65 login_description: `Inicia sesión con las credenciales de tu cuenta OpenWF (las mismas que usas en el juego al conectarte a este servidor).`,
65 66 login_emailLabel: `Dirección de correo electrónico`,
66 67 login_passwordLabel: `Contraseña`,
@@ -123,6 +124,7 @@ dict = {
123 124 detailedView_archonShardsDescription2: `Ten en cuenta que cada fragmento de archón tarda un poco en aplicarse al cargar`,
124 125 detailedView_valenceBonusLabel: `Bônus de Valência`,
125 126 detailedView_valenceBonusDescription: `Puedes establecer o quitar el bono de valencia de tu arma.`,
127 detailedView_modularPartsLabel: `[UNTRANSLATED] Change Modular Parts`,
126 128
127 129 mods_addRiven: `Agregar Agrietado`,
128 130 mods_fingerprint: `Huella digital`,
Modified static/webui/translations/fr.js +2 -0
@@ -61,6 +61,7 @@ dict = {
61 61 code_pigment: `Pigment`,
62 62 code_mature: `Maturer pour le combat`,
63 63 code_unmature: `Régrésser l'âge génétique`,
64 code_succChange: `[UNTRANSLATED] Successfully changed.`,
64 65 login_description: `Connexion avec les informations de connexion OpenWF.`,
65 66 login_emailLabel: `Email`,
66 67 login_passwordLabel: `Mot de passe`,
@@ -123,6 +124,7 @@ dict = {
123 124 detailedView_archonShardsDescription2: `Un délai sera présent entre l'application des éclats et le chargement en jeu.`,
124 125 detailedView_valenceBonusLabel: `Bonus de Valence`,
125 126 detailedView_valenceBonusDescription: `[UNTRANSLATED] You can set or remove the Valence Bonus from your weapon.`,
127 detailedView_modularPartsLabel: `[UNTRANSLATED] Change Modular Parts`,
126 128
127 129 mods_addRiven: `Ajouter un riven`,
128 130 mods_fingerprint: `Empreinte`,
Modified static/webui/translations/ru.js +2 -0
@@ -61,6 +61,7 @@ dict = {
61 61 code_pigment: `Пигмент`,
62 62 code_mature: `Подготовить к сражениям`,
63 63 code_unmature: `Регрессия генетического старения`,
64 code_succChange: `Успешно изменено.`,
64 65 login_description: `Войдите, используя учетные данные OpenWF (те же, что и в игре при подключении к этому серверу).`,
65 66 login_emailLabel: `Адрес электронной почты`,
66 67 login_passwordLabel: `Пароль`,
@@ -123,6 +124,7 @@ dict = {
123 124 detailedView_archonShardsDescription2: `Обратите внимание: каждый фрагмент архонта применяется с задержкой при загрузке.`,
124 125 detailedView_valenceBonusLabel: `Бонус Валентности`,
125 126 detailedView_valenceBonusDescription: `Вы можете установить или убрать бонус валентности с вашего оружия.`,
127 detailedView_modularPartsLabel: `Изменить Модульные Части`,
126 128
127 129 mods_addRiven: `Добавить Мод Разлома`,
128 130 mods_fingerprint: `Отпечаток`,
Modified static/webui/translations/zh.js +2 -0
@@ -61,6 +61,7 @@ dict = {
61 61 code_pigment: `颜料`,
62 62 code_mature: `成长并战备`,
63 63 code_unmature: `逆转衰老基因`,
64 code_succChange: `[UNTRANSLATED] Successfully changed.`,
64 65 login_description: `使用您的 OpenWF 账户凭证登录(与游戏内连接本服务器时使用的昵称相同).`,
65 66 login_emailLabel: `电子邮箱`,
66 67 login_passwordLabel: `密码`,
@@ -123,6 +124,7 @@ dict = {
123 124 detailedView_archonShardsDescription2: `请注意,在加载时,每个执政官源力石都需要一定的时间来生效。`,
124 125 detailedView_valenceBonusLabel: `效价加成`,
125 126 detailedView_valenceBonusDescription: `您可以设置或移除武器上的效价加成.`,
127 detailedView_modularPartsLabel: `[UNTRANSLATED] Change Modular Parts`,
126 128
127 129 mods_addRiven: `添加裂罅MOD`,
128 130 mods_fingerprint: `印记`,