返回提交历史
Modified
README.md
+1
-1
Modified
src/controllers/custom/getItemListsController.ts
+35
-0
Modified
static/webui/index.html
+19
-6
Modified
static/webui/script.js
+48
-4
Modified
static/webui/translations/de.js
+1
-0
Modified
static/webui/translations/en.js
+1
-0
Modified
static/webui/translations/es.js
+1
-0
Modified
static/webui/translations/fr.js
+1
-0
Modified
static/webui/translations/ru.js
+1
-0
Modified
static/webui/translations/zh.js
+1
-0
XFEstudio/SpaceNinjaServer
feat(webui): the circuit override (#2335)
Re #2312 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2335 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
a9359bd9
代码差异
10 个文件
+109
-11
@@ -35,4 +35,4 @@ SpaceNinjaServer requires a `config.json`. To set it up, you can copy the [confi
35
35
- `RadioLegionIntermissionSyndicate` for Intermission I
36
36
- `RadioLegionSyndicate` for The Wolf of Saturn Six
37
37
- `allTheFissures` can be set to `normal` or `hard` to enable all fissures either in normal or steel path, respectively.
38
- `worldState.circuitGameModes` can be provided with an array of valid game modes (`Survival`, `VoidFlood`, `Excavation`, `Defense`, `Exterminate`, `Assassination`, `Alchemy`)
38
- `worldState.circuitGameModes` can be set to an array of game modes which will override the otherwise-random pattern in The Circuit. Valid element values are `Survival`, `VoidFlood`, `Excavation`, `Defense`, `Exterminate`, `Assassination`, and `Alchemy`.
@@ -55,6 +55,7 @@ interface ItemLists {
55
55
EvolutionProgress: ListedItem[];
56
56
mods: ListedItem[];
57
57
Boosters: ListedItem[];
58
//circuitGameModes: ListedItem[];
58
59
}
59
60
60
61
const relicQualitySuffixes: Record<TRelicQuality, string> = {
@@ -64,6 +65,10 @@ const relicQualitySuffixes: Record<TRelicQuality, string> = {
64
65
VPQ_PLATINUM: " [Exceptional]"
65
66
};
66
67
68
/*const toTitleCase = (str: string): string => {
69
return str.replace(/[^\s-]+/g, word => word.charAt(0).toUpperCase() + word.substr(1).toLowerCase());
70
};*/
71
67
72
const getItemListsController: RequestHandler = (req, response) => {
68
73
const lang = getDict(typeof req.query.lang == "string" ? req.query.lang : "en");
69
74
const res: ItemLists = {
@@ -87,6 +92,36 @@ const getItemListsController: RequestHandler = (req, response) => {
87
92
EvolutionProgress: [],
88
93
mods: [],
89
94
Boosters: []
95
/*circuitGameModes: [
96
{
97
uniqueName: "Survival",
98
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Survival", lang))
99
},
100
{
101
uniqueName: "VoidFlood",
102
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Corruption", lang))
103
},
104
{
105
uniqueName: "Excavation",
106
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Excavation", lang))
107
},
108
{
109
uniqueName: "Defense",
110
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Defense", lang))
111
},
112
{
113
uniqueName: "Exterminate",
114
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Exterminate", lang))
115
},
116
{
117
uniqueName: "Assassination",
118
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Assassination", lang))
119
},
120
{
121
uniqueName: "Alchemy",
122
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Alchemy", lang))
123
}
124
]*/
90
125
};
91
126
for (const [uniqueName, item] of Object.entries(ExportWarframes)) {
92
127
res[item.productCategory].push({
@@ -768,14 +768,14 @@
768
768
<input class="form-check-input" type="checkbox" id="unlockAllSimarisResearchEntries" />
769
769
<label class="form-check-label" for="unlockAllSimarisResearchEntries" data-loc="cheats_unlockAllSimarisResearchEntries"></label>
770
770
</div>
771
<form class="form-group mt-2" onsubmit="doSaveConfig('spoofMasteryRank'); return false;">
771
<form class="form-group mt-2" onsubmit="doSaveConfigInt('spoofMasteryRank'); return false;">
772
772
<label class="form-label" for="spoofMasteryRank" data-loc="cheats_spoofMasteryRank"></label>
773
773
<div class="input-group">
774
774
<input class="form-control" id="spoofMasteryRank" type="number" min="-1" max="65535" />
775
775
<button class="btn btn-primary" type="submit" data-loc="cheats_save"></button>
776
776
</div>
777
777
</form>
778
<form class="form-group mt-2" onsubmit="doSaveConfig('nightwaveStandingMultiplier'); return false;">
778
<form class="form-group mt-2" onsubmit="doSaveConfigInt('nightwaveStandingMultiplier'); return false;">
779
779
<label class="form-label" for="nightwaveStandingMultiplier" data-loc="cheats_nightwaveStandingMultiplier"></label>
780
780
<div class="input-group">
781
781
<input class="form-control" id="nightwaveStandingMultiplier" type="number" min="1" max="1000000" value="1" />
@@ -892,6 +892,13 @@
892
892
<option value="hard" data-loc="worldState_allAtOnceSteelPath"></option>
893
893
</select>
894
894
</div>
895
<form class="form-group mt-2" onsubmit="doSaveConfigStringArray('worldState.circuitGameModes'); return false;">
896
<label class="form-label" for="worldState.circuitGameModes" data-loc="worldState_theCircuitOverride"></label>
897
<div class="input-group">
898
<input id="worldState.circuitGameModes" type="text" class="form-control tags-input" list="datalist-circuitGameModes" />
899
<button class="btn btn-primary" type="submit" data-loc="cheats_save"></button>
900
</div>
901
</form>
895
902
</div>
896
903
</div>
897
904
</div>
@@ -923,10 +930,7 @@
923
930
<datalist id="datalist-KubrowPets"></datalist>
924
931
<datalist id="datalist-QuestKeys"></datalist>
925
932
<datalist id="datalist-miscitems"></datalist>
926
<datalist id="datalist-mods">
927
<option data-key="/Lotus/Upgrades/Mods/Fusers/LegendaryModFuser" value="Legendary Core"></option>
928
<option data-key="/Lotus/Upgrades/CosmeticEnhancers/Peculiars/CyoteMod" value="Traumatic Peculiar"></option>
929
</datalist>
933
<datalist id="datalist-mods"></datalist>
930
934
<datalist id="datalist-archonCrystalUpgrades"></datalist>
931
935
<datalist id="datalist-OperatorAmps"></datalist>
932
936
<datalist id="datalist-EvolutionProgress"></datalist>
@@ -958,6 +962,15 @@
958
962
<datalist id="datalist-ModularParts-KUBROW_ANTIGEN"></datalist>
959
963
<datalist id="datalist-ModularParts-KUBROW_MUTAGEN"></datalist>
960
964
<datalist id="datalist-Boosters"></datalist>
965
<datalist id="datalist-circuitGameModes">
966
<option>Survival</option>
967
<option>VoidFlood</option>
968
<option>Excavation</option>
969
<option>Defense</option>
970
<option>Exterminate</option>
971
<option>Assassination</option>
972
<option>Alchemy</option>
973
</datalist>
961
974
<script src="/webui/libs/jquery-3.6.0.min.js"></script>
962
975
<script src="/webui/libs/whirlpool-js.min.js"></script>
963
976
<script src="/webui/libs/single.js"></script>
@@ -1882,12 +1882,27 @@ for (const id of uiConfigs) {
1882
1882
}
1883
1883
}
1884
1884
1885
function doSaveConfig(id) {
1886
const elm = document.getElementById(id);
1885
function doSaveConfigInt(id) {
1887
1886
$.post({
1888
1887
url: "/custom/setConfig?" + window.authz + "&wsid=" + wsid,
1889
1888
contentType: "application/json",
1890
data: JSON.stringify({ [id]: parseInt(elm.value) })
1889
data: JSON.stringify({
1890
[id]: parseInt(document.getElementById(id).value)
1891
})
1892
});
1893
}
1894
1895
function doSaveConfigStringArray(id) {
1896
$.post({
1897
url: "/custom/setConfig?" + window.authz + "&wsid=" + wsid,
1898
contentType: "application/json",
1899
data: JSON.stringify({
1900
[id]: document
1901
.getElementById(id)
1902
.getAttribute("data-tags-value")
1903
.split(", ")
1904
.filter(x => x)
1905
})
1891
1906
});
1892
1907
}
1893
1908
@@ -1914,7 +1929,12 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
1914
1929
if (x.type == "checkbox") {
1915
1930
x.checked = value;
1916
1931
} else if (x.type == "number") {
1917
x.setAttribute("value", `${value}`);
1932
x.setAttribute("value", value);
1933
} else if (x.classList.contains("tags-input")) {
1934
x.value = value.join(", ");
1935
x.oninput();
1936
} else {
1937
x.value = value;
1918
1938
}
1919
1939
}
1920
1940
});
@@ -2597,3 +2617,27 @@ const importSamples = {
2597
2617
function setImportSample(key) {
2598
2618
$("#import-inventory").val(JSON.stringify(importSamples[key], null, 2));
2599
2619
}
2620
2621
document.querySelectorAll(".tags-input").forEach(input => {
2622
const datalist = document.getElementById(input.getAttribute("list"));
2623
const options = [...datalist.querySelectorAll("option")].map(x => x.textContent);
2624
input.oninput = function () {
2625
const value = [];
2626
for (const tag of this.value.split(",")) {
2627
const index = options.map(x => x.toLowerCase()).indexOf(tag.trim().toLowerCase());
2628
if (index != -1) {
2629
value.push(options[index]);
2630
}
2631
}
2632
2633
this.setAttribute("data-tags-value", value.join(", "));
2634
2635
datalist.innerHTML = "";
2636
for (const option of options) {
2637
const elm = document.createElement("option");
2638
elm.textContent = [...value, option, ""].join(", ");
2639
datalist.appendChild(elm);
2640
}
2641
};
2642
input.oninput();
2643
});
@@ -230,6 +230,7 @@ dict = {
230
230
normal: `[UNTRANSLATED] Normal`,
231
231
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
232
232
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
233
worldState_theCircuitOverride: `[UNTRANSLATED] The Circuit Override`,
233
234
234
235
import_importNote: `Du kannst hier eine vollständige oder teilweise Inventarantwort (Client-Darstellung) einfügen. Alle Felder, die vom Importer unterstützt werden, <b>werden in deinem Account überschrieben</b>.`,
235
236
import_submit: `Absenden`,
@@ -229,6 +229,7 @@ dict = {
229
229
normal: `Normal`,
230
230
worldState_allAtOnceNormal: `All At Once, Normal`,
231
231
worldState_allAtOnceSteelPath: `All At Once, Steel Path`,
232
worldState_theCircuitOverride: `The Circuit Override`,
232
233
233
234
import_importNote: `You can provide a full or partial inventory response (client respresentation) here. All fields that are supported by the importer <b>will be overwritten</b> in your account.`,
234
235
import_submit: `Submit`,
@@ -230,6 +230,7 @@ dict = {
230
230
normal: `[UNTRANSLATED] Normal`,
231
231
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
232
232
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
233
worldState_theCircuitOverride: `[UNTRANSLATED] The Circuit Override`,
233
234
234
235
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.`,
235
236
import_submit: `Enviar`,
@@ -230,6 +230,7 @@ dict = {
230
230
normal: `[UNTRANSLATED] Normal`,
231
231
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
232
232
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
233
worldState_theCircuitOverride: `[UNTRANSLATED] The Circuit Override`,
233
234
234
235
import_importNote: `Import manuel. Toutes les modifcations supportées par l'inventaire <b>écraseront celles présentes dans la base de données</b>.`,
235
236
import_submit: `Soumettre`,
@@ -230,6 +230,7 @@ dict = {
230
230
normal: `[UNTRANSLATED] Normal`,
231
231
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
232
232
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
233
worldState_theCircuitOverride: `[UNTRANSLATED] The Circuit Override`,
233
234
234
235
import_importNote: `Вы можете загрузить полный или частичный ответ инвентаря (клиентское представление) здесь. Все поддерживаемые поля <b>будут перезаписаны</b> в вашем аккаунте.`,
235
236
import_submit: `Отправить`,
@@ -230,6 +230,7 @@ dict = {
230
230
normal: `正常`,
231
231
worldState_allAtOnceNormal: `全部开启(普通)`,
232
232
worldState_allAtOnceSteelPath: `全部开启(钢铁之路)`,
233
worldState_theCircuitOverride: `[UNTRANSLATED] The Circuit Override`,
233
234
234
235
import_importNote: `您可以在此处提供完整或部分库存响应(客户端表示)。支持的所有字段<b>将被覆盖</b>到您的账户中。`,
235
236
import_submit: `提交`,