feat(webui): the circuit override #2335
@ -35,4 +35,4 @@ SpaceNinjaServer requires a `config.json`. To set it up, you can copy the [confi
|
||||
- `RadioLegionIntermissionSyndicate` for Intermission I
|
||||
- `RadioLegionSyndicate` for The Wolf of Saturn Six
|
||||
- `allTheFissures` can be set to `normal` or `hard` to enable all fissures either in normal or steel path, respectively.
|
||||
- `worldState.circuitGameModes` can be provided with an array of valid game modes (`Survival`, `VoidFlood`, `Excavation`, `Defense`, `Exterminate`, `Assassination`, `Alchemy`)
|
||||
- `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 {
|
||||
EvolutionProgress: ListedItem[];
|
||||
mods: ListedItem[];
|
||||
Boosters: ListedItem[];
|
||||
//circuitGameModes: ListedItem[];
|
||||
}
|
||||
|
||||
const relicQualitySuffixes: Record<TRelicQuality, string> = {
|
||||
@ -64,6 +65,10 @@ const relicQualitySuffixes: Record<TRelicQuality, string> = {
|
||||
VPQ_PLATINUM: " [Exceptional]"
|
||||
};
|
||||
|
||||
/*const toTitleCase = (str: string): string => {
|
||||
return str.replace(/[^\s-]+/g, word => word.charAt(0).toUpperCase() + word.substr(1).toLowerCase());
|
||||
};*/
|
||||
|
||||
const getItemListsController: RequestHandler = (req, response) => {
|
||||
const lang = getDict(typeof req.query.lang == "string" ? req.query.lang : "en");
|
||||
const res: ItemLists = {
|
||||
@ -87,6 +92,36 @@ const getItemListsController: RequestHandler = (req, response) => {
|
||||
EvolutionProgress: [],
|
||||
mods: [],
|
||||
Boosters: []
|
||||
/*circuitGameModes: [
|
||||
{
|
||||
uniqueName: "Survival",
|
||||
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Survival", lang))
|
||||
},
|
||||
{
|
||||
uniqueName: "VoidFlood",
|
||||
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Corruption", lang))
|
||||
},
|
||||
{
|
||||
uniqueName: "Excavation",
|
||||
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Excavation", lang))
|
||||
},
|
||||
{
|
||||
uniqueName: "Defense",
|
||||
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Defense", lang))
|
||||
},
|
||||
{
|
||||
uniqueName: "Exterminate",
|
||||
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Exterminate", lang))
|
||||
},
|
||||
{
|
||||
uniqueName: "Assassination",
|
||||
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Assassination", lang))
|
||||
},
|
||||
{
|
||||
uniqueName: "Alchemy",
|
||||
name: toTitleCase(getString("/Lotus/Language/Missions/MissionName_Alchemy", lang))
|
||||
}
|
||||
]*/
|
||||
};
|
||||
for (const [uniqueName, item] of Object.entries(ExportWarframes)) {
|
||||
res[item.productCategory].push({
|
||||
|
@ -768,14 +768,14 @@
|
||||
<input class="form-check-input" type="checkbox" id="unlockAllSimarisResearchEntries" />
|
||||
<label class="form-check-label" for="unlockAllSimarisResearchEntries" data-loc="cheats_unlockAllSimarisResearchEntries"></label>
|
||||
</div>
|
||||
<form class="form-group mt-2" onsubmit="doSaveConfig('spoofMasteryRank'); return false;">
|
||||
<form class="form-group mt-2" onsubmit="doSaveConfigInt('spoofMasteryRank'); return false;">
|
||||
<label class="form-label" for="spoofMasteryRank" data-loc="cheats_spoofMasteryRank"></label>
|
||||
<div class="input-group">
|
||||
<input class="form-control" id="spoofMasteryRank" type="number" min="-1" max="65535" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="cheats_save"></button>
|
||||
</div>
|
||||
</form>
|
||||
<form class="form-group mt-2" onsubmit="doSaveConfig('nightwaveStandingMultiplier'); return false;">
|
||||
<form class="form-group mt-2" onsubmit="doSaveConfigInt('nightwaveStandingMultiplier'); return false;">
|
||||
<label class="form-label" for="nightwaveStandingMultiplier" data-loc="cheats_nightwaveStandingMultiplier"></label>
|
||||
<div class="input-group">
|
||||
<input class="form-control" id="nightwaveStandingMultiplier" type="number" min="1" max="1000000" value="1" />
|
||||
@ -892,6 +892,13 @@
|
||||
<option value="hard" data-loc="worldState_allAtOnceSteelPath"></option>
|
||||
</select>
|
||||
</div>
|
||||
<form class="form-group mt-2" onsubmit="doSaveConfigStringArray('worldState.circuitGameModes'); return false;">
|
||||
<label class="form-label" for="worldState.circuitGameModes" data-loc="worldState_theCircuitOverride"></label>
|
||||
<div class="input-group">
|
||||
<input id="worldState.circuitGameModes" type="text" class="form-control tags-input" list="datalist-circuitGameModes" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="cheats_save"></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -923,10 +930,7 @@
|
||||
<datalist id="datalist-KubrowPets"></datalist>
|
||||
<datalist id="datalist-QuestKeys"></datalist>
|
||||
<datalist id="datalist-miscitems"></datalist>
|
||||
<datalist id="datalist-mods">
|
||||
<option data-key="/Lotus/Upgrades/Mods/Fusers/LegendaryModFuser" value="Legendary Core"></option>
|
||||
<option data-key="/Lotus/Upgrades/CosmeticEnhancers/Peculiars/CyoteMod" value="Traumatic Peculiar"></option>
|
||||
</datalist>
|
||||
<datalist id="datalist-mods"></datalist>
|
||||
<datalist id="datalist-archonCrystalUpgrades"></datalist>
|
||||
<datalist id="datalist-OperatorAmps"></datalist>
|
||||
<datalist id="datalist-EvolutionProgress"></datalist>
|
||||
@ -958,6 +962,15 @@
|
||||
<datalist id="datalist-ModularParts-KUBROW_ANTIGEN"></datalist>
|
||||
<datalist id="datalist-ModularParts-KUBROW_MUTAGEN"></datalist>
|
||||
<datalist id="datalist-Boosters"></datalist>
|
||||
<datalist id="datalist-circuitGameModes">
|
||||
<option>Survival</option>
|
||||
<option>VoidFlood</option>
|
||||
<option>Excavation</option>
|
||||
<option>Defense</option>
|
||||
<option>Exterminate</option>
|
||||
<option>Assassination</option>
|
||||
<option>Alchemy</option>
|
||||
</datalist>
|
||||
<script src="/webui/libs/jquery-3.6.0.min.js"></script>
|
||||
<script src="/webui/libs/whirlpool-js.min.js"></script>
|
||||
<script src="/webui/libs/single.js"></script>
|
||||
|
@ -1882,12 +1882,27 @@ for (const id of uiConfigs) {
|
||||
}
|
||||
}
|
||||
|
||||
function doSaveConfig(id) {
|
||||
const elm = document.getElementById(id);
|
||||
function doSaveConfigInt(id) {
|
||||
$.post({
|
||||
url: "/custom/setConfig?" + window.authz + "&wsid=" + wsid,
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({ [id]: parseInt(elm.value) })
|
||||
data: JSON.stringify({
|
||||
[id]: parseInt(document.getElementById(id).value)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function doSaveConfigStringArray(id) {
|
||||
$.post({
|
||||
url: "/custom/setConfig?" + window.authz + "&wsid=" + wsid,
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({
|
||||
[id]: document
|
||||
.getElementById(id)
|
||||
.getAttribute("data-tags-value")
|
||||
.split(", ")
|
||||
.filter(x => x)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
@ -1914,7 +1929,12 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
|
||||
if (x.type == "checkbox") {
|
||||
x.checked = value;
|
||||
} else if (x.type == "number") {
|
||||
x.setAttribute("value", `${value}`);
|
||||
x.setAttribute("value", value);
|
||||
} else if (x.classList.contains("tags-input")) {
|
||||
x.value = value.join(", ");
|
||||
x.oninput();
|
||||
} else {
|
||||
x.value = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -2597,3 +2617,27 @@ const importSamples = {
|
||||
function setImportSample(key) {
|
||||
$("#import-inventory").val(JSON.stringify(importSamples[key], null, 2));
|
||||
}
|
||||
|
||||
document.querySelectorAll(".tags-input").forEach(input => {
|
||||
const datalist = document.getElementById(input.getAttribute("list"));
|
||||
const options = [...datalist.querySelectorAll("option")].map(x => x.textContent);
|
||||
input.oninput = function () {
|
||||
const value = [];
|
||||
for (const tag of this.value.split(",")) {
|
||||
const index = options.map(x => x.toLowerCase()).indexOf(tag.trim().toLowerCase());
|
||||
if (index != -1) {
|
||||
value.push(options[index]);
|
||||
}
|
||||
}
|
||||
|
||||
this.setAttribute("data-tags-value", value.join(", "));
|
||||
|
||||
datalist.innerHTML = "";
|
||||
for (const option of options) {
|
||||
const elm = document.createElement("option");
|
||||
elm.textContent = [...value, option, ""].join(", ");
|
||||
datalist.appendChild(elm);
|
||||
}
|
||||
};
|
||||
input.oninput();
|
||||
});
|
||||
|
@ -230,6 +230,7 @@ dict = {
|
||||
normal: `[UNTRANSLATED] Normal`,
|
||||
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
|
||||
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
|
||||
worldState_theCircuitOverride: `[UNTRANSLATED] The Circuit Override`,
|
||||
|
||||
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>.`,
|
||||
import_submit: `Absenden`,
|
||||
|
@ -229,6 +229,7 @@ dict = {
|
||||
normal: `Normal`,
|
||||
worldState_allAtOnceNormal: `All At Once, Normal`,
|
||||
worldState_allAtOnceSteelPath: `All At Once, Steel Path`,
|
||||
worldState_theCircuitOverride: `The Circuit Override`,
|
||||
|
||||
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.`,
|
||||
import_submit: `Submit`,
|
||||
|
@ -230,6 +230,7 @@ dict = {
|
||||
normal: `[UNTRANSLATED] Normal`,
|
||||
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
|
||||
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
|
||||
worldState_theCircuitOverride: `[UNTRANSLATED] The Circuit Override`,
|
||||
|
||||
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`,
|
||||
|
@ -230,6 +230,7 @@ dict = {
|
||||
normal: `[UNTRANSLATED] Normal`,
|
||||
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
|
||||
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
|
||||
worldState_theCircuitOverride: `[UNTRANSLATED] The Circuit Override`,
|
||||
|
||||
import_importNote: `Import manuel. Toutes les modifcations supportées par l'inventaire <b>écraseront celles présentes dans la base de données</b>.`,
|
||||
import_submit: `Soumettre`,
|
||||
|
@ -230,6 +230,7 @@ dict = {
|
||||
normal: `[UNTRANSLATED] Normal`,
|
||||
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
|
||||
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
|
||||
worldState_theCircuitOverride: `[UNTRANSLATED] The Circuit Override`,
|
||||
|
||||
import_importNote: `Вы можете загрузить полный или частичный ответ инвентаря (клиентское представление) здесь. Все поддерживаемые поля <b>будут перезаписаны</b> в вашем аккаунте.`,
|
||||
import_submit: `Отправить`,
|
||||
|
@ -230,6 +230,7 @@ dict = {
|
||||
normal: `正常`,
|
||||
worldState_allAtOnceNormal: `全部开启(普通)`,
|
||||
worldState_allAtOnceSteelPath: `全部开启(钢铁之路)`,
|
||||
worldState_theCircuitOverride: `[UNTRANSLATED] The Circuit Override`,
|
||||
|
||||
import_importNote: `您可以在此处提供完整或部分库存响应(客户端表示)。支持的所有字段<b>将被覆盖</b>到您的账户中。`,
|
||||
import_submit: `提交`,
|
||||
|
Loading…
x
Reference in New Issue
Block a user