返回提交历史
Modified
src/controllers/api/infestedFoundryController.ts
+1
-4
Modified
src/controllers/custom/getItemListsController.ts
+3
-1
Added
src/controllers/custom/popArchonCrystalUpgradeController.ts
+18
-0
Added
src/controllers/custom/pushArchonCrystalUpgradeController.ts
+20
-0
Modified
src/routes/custom.ts
+7
-0
Modified
src/routes/webui.ts
+3
-0
Added
static/fixed_responses/webuiArchonCrystalUpgrades.json
+81
-0
Modified
static/webui/index.html
+30
-10
Modified
static/webui/script.js
+170
-43
Modified
static/webui/style.css
+0
-1
XFEstudio/SpaceNinjaServer
feat(webui): add options to add and remove archon shard upgrades (#437)
afbc1801
代码差异
10 个文件
+333
-59
@@ -13,10 +13,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
13
13
const request = getJSONfromString(String(req.body)) as IShardInstallRequest;
14
14
const inventory = await getInventory(accountId);
15
15
const suit = inventory.Suits.find(suit => suit._id.toString() == request.SuitId.$oid)!;
16
if (
17
!suit.ArchonCrystalUpgrades ||
18
suit.ArchonCrystalUpgrades.length != 5 // we shouldn't have an array like this, but older inventories may disagree...
19
) {
16
if (!suit.ArchonCrystalUpgrades || suit.ArchonCrystalUpgrades.length != 5) {
20
17
suit.ArchonCrystalUpgrades = [{}, {}, {}, {}, {}];
21
18
}
22
19
suit.ArchonCrystalUpgrades[request.Slot] = {
@@ -8,6 +8,7 @@ import {
8
8
ExportWarframes,
9
9
ExportWeapons
10
10
} from "warframe-public-export-plus";
11
import archonCrystalUpgrades from "@/static/fixed_responses/webuiArchonCrystalUpgrades.json";
11
12
12
13
interface ListedItem {
13
14
uniqueName: string;
@@ -77,7 +78,8 @@ const getItemListsController: RequestHandler = (_req, res) => {
77
78
weapons,
78
79
miscitems,
79
80
mods,
80
badItems
81
badItems,
82
archonCrystalUpgrades
81
83
});
82
84
};
83
85
@@ -0,0 +1,18 @@
1
import { RequestHandler } from "express";
2
import { getAccountIdForRequest } from "@/src/services/loginService";
3
import { getInventory } from "@/src/services/inventoryService";
4
5
// eslint-disable-next-line @typescript-eslint/no-misused-promises
6
export const popArchonCrystalUpgradeController: RequestHandler = async (req, res) => {
7
const accountId = await getAccountIdForRequest(req);
8
const inventory = await getInventory(accountId);
9
const suit = inventory.Suits.find(suit => suit._id.toString() == (req.query.oid as string));
10
if (suit && suit.ArchonCrystalUpgrades) {
11
suit.ArchonCrystalUpgrades = suit.ArchonCrystalUpgrades.filter(
12
x => x.UpgradeType != (req.query.type as string)
13
);
14
await inventory.save();
15
res.end();
16
}
17
res.status(400).end();
18
};
@@ -0,0 +1,20 @@
1
import { RequestHandler } from "express";
2
import { getAccountIdForRequest } from "@/src/services/loginService";
3
import { getInventory } from "@/src/services/inventoryService";
4
5
// eslint-disable-next-line @typescript-eslint/no-misused-promises
6
export const pushArchonCrystalUpgradeController: RequestHandler = async (req, res) => {
7
const accountId = await getAccountIdForRequest(req);
8
const inventory = await getInventory(accountId);
9
const suit = inventory.Suits.find(suit => suit._id.toString() == (req.query.oid as string));
10
if (suit) {
11
suit.ArchonCrystalUpgrades ??= [];
12
const count = (req.query.count as number | undefined) ?? 1;
13
for (let i = 0; i != count; ++i) {
14
suit.ArchonCrystalUpgrades.push({ UpgradeType: req.query.type as string });
15
}
16
await inventory.save();
17
res.end();
18
}
19
res.status(400).end();
20
};
@@ -1,13 +1,20 @@
1
1
import express from "express";
2
2
3
import { getItemListsController } from "@/src/controllers/custom/getItemListsController";
4
import { pushArchonCrystalUpgradeController } from "@/src/controllers/custom/pushArchonCrystalUpgradeController";
5
import { popArchonCrystalUpgradeController } from "@/src/controllers/custom/popArchonCrystalUpgradeController";
6
3
7
import { createAccountController } from "@/src/controllers/custom/createAccountController";
4
8
import { addItemController } from "@/src/controllers/custom/addItemController";
9
5
10
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
6
11
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
7
12
8
13
const customRouter = express.Router();
9
14
10
15
customRouter.get("/getItemLists", getItemListsController);
16
customRouter.get("/pushArchonCrystalUpgrade", pushArchonCrystalUpgradeController);
17
customRouter.get("/popArchonCrystalUpgrade", popArchonCrystalUpgradeController);
11
18
12
19
customRouter.post("/createAccount", createAccountController);
13
20
customRouter.post("/addItem", addItemController);
@@ -22,6 +22,9 @@ webuiRouter.use("/webui", (req, res, next) => {
22
22
webuiRouter.get("/webui/inventory", (_req, res) => {
23
23
res.sendFile(path.join(rootDir, "static/webui/index.html"));
24
24
});
25
webuiRouter.get(/webui\/powersuit\/(.+)/, (_req, res) => {
26
res.sendFile(path.join(rootDir, "static/webui/index.html"));
27
});
25
28
webuiRouter.get("/webui/mods", (_req, res) => {
26
29
res.sendFile(path.join(rootDir, "static/webui/index.html"));
27
30
});
@@ -0,0 +1,81 @@
1
{
2
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeEquilibrium": "+20% Energy from Health pickups, +20% Health from Energy pickups",
3
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeEquilibriumMythic": "+30% Energy from Health pickups, +30% Health from Energy pickups",
4
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeMeleeCritDamage": "+25% Melee Critical Damage",
5
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeMeleeCritDamageMythic": "+37.5% Melee Critical Damage",
6
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradePrimaryStatusChance": "+25% Primary Status Chance",
7
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradePrimaryStatusChanceMythic": "+37.5% Primary Status Chance",
8
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeSecondaryCritChance": "+25% Secondary Critical Chance",
9
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeSecondaryCritChanceMythic": "+37.5% Secondary Critical Chance",
10
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeAbilityDuration": "+10% Ability Duration",
11
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeAbilityDurationMythic": "+15% Ability Duration",
12
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeAbilityStrength": "+10% Ability Strength",
13
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeAbilityStrengthMythic": "+15% Ability Strength",
14
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeArmourMax": "+150 Armor",
15
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeArmourMaxMythic": "+225 Armor",
16
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeBlastProc": "+5 Shields on inflicting Blast Status",
17
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeBlastProcMythic": "+7.5 Shields on inflicting Blast Status",
18
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeCastingSpeed": "+25% Casting Speed",
19
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeCastingSpeedMythic": "+37.5% Casting Speed",
20
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeCorrosiveDamageBoost": "+10% Ability Damage on enemies affected by Corrosion Status",
21
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeCorrosiveDamageBoostMythic": "+15% Ability Damage on enemies affected by Corrosion Status",
22
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeCorrosiveStack": "Increase max stacks of Corrosion Status by +2",
23
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeCorrosiveStackMythic": "Increase max stacks of Corrosion Status by +3",
24
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeCritDamageBoost": "+25% Melee Critical Damage (Doubles over 500 Energy)",
25
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeCritDamageBoostMythic": "+37% Melee Critical Damage (Doubles over 500 Energy)",
26
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeElectricDamage": "+30% Primary Electricity Damage (+10% per additional Shard)",
27
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeElectricDamageMythic": "+45% Primary Electricity Damage (+15% per additional Shard)",
28
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeElectricDamageBoost": "+10% Ability Damage on enemies affected by Electricity Status",
29
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeElectricDamageBoostMythic": "+15% Ability Damage on enemies affected by Electricity Status",
30
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeEnergyMax": "+50 Energy Max",
31
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeEnergyMaxMythic": "+75 Energy Max",
32
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeGlobeEffectEnergy": "+50% Energy Orb Effectiveness",
33
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeGlobeEffectEnergyMythic": "+75% Energy Orb Effectiveness",
34
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeGlobeEffectHealth": "+100% Health Orb Effectiveness",
35
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeGlobeEffectHealthMythic": "+150% Health Orb Effectiveness",
36
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeHealthMax": "+150 Health",
37
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeHealthMaxMythic": "+225 Health",
38
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeHPBoostFromImpact": "+1 Health per enemy killed with Blast Damage (Max 300 Health)",
39
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeHPBoostFromImpactMythic": "+2 Health per enemy killed with Blast Damage (Max 450 Health)",
40
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeParkourVelocity": "+15% Parkour Velocity",
41
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeParkourVelocityMythic": "+22.5% Parkour Velocity",
42
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeRadiationDamageBoost": "+10% Ability Damage on enemies affected by Radiation Status",
43
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeRadiationDamageBoostMythic": "+15% Ability Damage on enemies affected by Radiation Status",
44
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeRegen": "+5 Health Regen/s",
45
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeRegenMythic": "+7.5 Health Regen/s",
46
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeShieldMax": "+150 Shield",
47
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeShieldMaxMythic": "+225 Shield",
48
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeStartingEnergy": "+30% Energy on Spawn",
49
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeStartingEnergyMythic": "+45% Energy on Spawn",
50
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeToxinDamage": "+30% Toxin Status Effect Damage",
51
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeToxinDamageMythic": "+45% Toxin Status Effect Damage",
52
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeToxinHeal": "+2 Health on damaging enemies with Toxin Status",
53
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWarframeToxinHealMythic": "+3 Health on damaging enemies with Toxin Status",
54
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWeaponCritBoostFromHeat": "+1% Secondary Critical Chance per Heat-affected enemy killed (Max 50%)",
55
"/Lotus/Upgrades/Invigorations/ArchonCrystalUpgrades/ArchonCrystalUpgradeWeaponCritBoostFromHeatMythic": "+1.5% Secondary Critical Chance per Heat-affected enemy killed (Max 75%)",
56
57
"/Lotus/Upgrades/Mods/Warframe/AvatarEnergyRegenMod": "+0.5 Energy Regen/s",
58
"/Lotus/Upgrades/Mods/Warframe/AvatarEnemyRadarMod": "+5m Enemy Radar",
59
"/Lotus/Upgrades/Mods/Warframe/AvatarLootRadarMod": "+7m Loot Radar",
60
61
"/Lotus/Upgrades/Mods/Rifle/WeaponAmmoMaxMod": "+15% Ammo Max",
62
63
"/Lotus/Upgrades/Mods/Aura/EnemyArmorReductionAuraMod": "-3% Enemy Armor",
64
65
"/Lotus/Upgrades/Mods/DataSpike/Assassin/OnExecutionAmmoMod": "100% Primary and Secondary Magazine Refill on Mercy",
66
"/Lotus/Upgrades/Mods/DataSpike/Assassin/OnExecutionHealthDropMod": "100% chance to drop a Health Orb on Mercy",
67
"/Lotus/Upgrades/Mods/DataSpike/Assassin/OnExecutionEnergyDropMod": "50% chance to drop an Energy Orb on Mercy",
68
"/Lotus/Upgrades/Mods/DataSpike/Cipher/OnFailHackResetMod": "+50% to retry on Hacking failure",
69
"/Lotus/Upgrades/Mods/DataSpike/Cipher/DamageReductionOnHackMod": "75% Damage Reduction while Hacking",
70
"/Lotus/Upgrades/Mods/DataSpike/Assassin/OnExecutionReviveCompanionMod": "Mercy Kills reduce Companion Recovery by 15s",
71
"/Lotus/Upgrades/Mods/DataSpike/Assassin/OnExecutionParkourSpeedMod": "+60% Parkour Speed after a Mercy for 15s",
72
"/Lotus/Upgrades/Mods/Warframe/AvatarTimeLimitIncreaseMod": "+8s to Hacking",
73
"/Lotus/Upgrades/Mods/DataSpike/Cipher/ElectrifyOnHackMod": "Shock enemies within 20m while Hacking",
74
"/Lotus/Upgrades/Mods/DataSpike/Assassin/OnExecutionTerrifyMod": "50% chance for enemies within 15m to cower in fear for 8 seconds on Mercy",
75
"/Lotus/Upgrades/Mods/DataSpike/Cipher/OnHackLockersMod": "Unlock 5 lockers within 20m after Hacking",
76
"/Lotus/Upgrades/Mods/DataSpike/Assassin/OnExecutionBlindMod": "Blind enemies within 18m on Mercy",
77
"/Lotus/Upgrades/Mods/DataSpike/Assassin/OnExecutionDrainPowerMod": "100% chance for next ability cast to gain +50% Ability Strength on Mercy",
78
"/Lotus/Upgrades/Mods/DataSpike/Cipher/OnHackSprintSpeedMod": "+75% Sprint Speed for 15s after Hacking",
79
"/Lotus/Upgrades/Mods/DataSpike/Assassin/SwiftExecuteMod": "Speed of Mercy Kills increased by 50%",
80
"/Lotus/Upgrades/Mods/DataSpike/Cipher/OnHackInvisMod": "Invisible for 15 seconds after hacking"
81
}
@@ -3,8 +3,8 @@
3
3
<head>
4
4
<title>OpenWF WebUI</title>
5
5
<meta name="viewport" content="width=device-width, initial-scale=1" />
6
<link rel="stylesheet" href="libs/bootstrap.min.css" />
7
<link rel="stylesheet" href="style.css" />
6
<link rel="stylesheet" href="/webui/libs/bootstrap.min.css" />
7
<link rel="stylesheet" href="/webui/style.css" />
8
8
</head>
9
9
<body>
10
10
<nav class="navbar sticky-top bg-body-tertiary">
@@ -63,7 +63,7 @@
63
63
</form>
64
64
</div>
65
65
<div data-route="/webui/inventory" data-title="Inventory | OpenWF WebUI">
66
<p id="refresh-note" class="mb-4">
66
<p class="mb-4">
67
67
Note: Changes made here will only be reflected in-game when the game re-downloads your
68
68
inventory. Visiting the navigation should be the easiest way to trigger that.
69
69
</p>
@@ -106,8 +106,27 @@
106
106
</div>
107
107
</div>
108
108
</div>
109
<div id="powersuit-route" data-route="~ /webui/powersuit/(.+)" data-title="Inventory | OpenWF WebUI">
110
<h3 class="mb-0"></h3>
111
<p class="text-body-secondary"></p>
112
<div class="card mb-4">
113
<h5 class="card-header">Archon Shard Slots</h5>
114
<div class="card-body">
115
<p>You can use these unlimited slots to apply a wide range of upgrades.</p>
116
<form class="input-group mb-3" onsubmit="doPushArchonCrystalUpgrade();return false;">
117
<input type="number" id="archon-crystal-add-count" min="1" value="1" class="form-control" style="max-width:100px" />
118
<span class="input-group-text">x</span>
119
<input class="form-control" list="datalist-archonCrystalUpgrades" />
120
<button class="btn btn-primary" type="submit">Add</button>
121
</form>
122
<table class="table table-hover w-100">
123
<tbody id="crystals-list"></tbody>
124
</table>
125
</div>
126
</div>
127
</div>
109
128
<div data-route="/webui/mods" data-title="Mods | OpenWF WebUI">
110
<p id="refresh-note" class="mb-4">
129
<p class="mb-4">
111
130
Note: Changes made here will only be reflected in-game when the game re-downloads your
112
131
inventory. Visiting the navigation should be the easiest way to trigger that.
113
132
</p>
@@ -259,11 +278,12 @@
259
278
<datalist id="datalist-weapons"></datalist>
260
279
<datalist id="datalist-miscitems"></datalist>
261
280
<datalist id="datalist-mods"></datalist>
262
<script src="libs/jquery-3.6.0.min.js"></script>
263
<script src="libs/whirlpool-js.min.js"></script>
264
<script src="libs/single.js"></script>
265
<script src="riven-tool/RivenParser.js"></script>
266
<script src="script.js"></script>
267
<script src="libs/bootstrap.bundle.min.js"></script>
281
<datalist id="datalist-archonCrystalUpgrades"></datalist>
282
<script src="/webui/libs/jquery-3.6.0.min.js"></script>
283
<script src="/webui/libs/whirlpool-js.min.js"></script>
284
<script src="/webui/libs/single.js"></script>
285
<script src="/webui/riven-tool/RivenParser.js"></script>
286
<script src="/webui/script.js"></script>
287
<script src="/webui/libs/bootstrap.bundle.min.js"></script>
268
288
</body>
269
289
</html>
@@ -15,7 +15,6 @@ function loginFromLocalStorage() {
15
15
window.accountId = data.id;
16
16
window.authz = "accountId=" + data.id + "&nonce=" + data.Nonce;
17
17
updateInventory();
18
fetchSettings();
19
18
},
20
19
() => {
21
20
logout();
@@ -88,6 +87,8 @@ single.on("route_load", function (event) {
88
87
window.itemListPromise = new Promise(resolve => {
89
88
const req = $.get("/custom/getItemLists");
90
89
req.done(data => {
90
window.archonCrystalUpgrades = data.archonCrystalUpgrades;
91
91
92
const itemMap = {
92
93
// Generics for rivens
93
94
"/Lotus/Weapons/Tenno/Archwing/Primary/ArchGun": { name: "Archgun" },
@@ -105,7 +106,14 @@ window.itemListPromise = new Promise(resolve => {
105
106
"/Lotus/Upgrades/CosmeticEnhancers/Peculiars/CyoteMod": { name: "Traumatic Peculiar" }
106
107
};
107
108
for (const [type, items] of Object.entries(data)) {
108
if (type != "badItems") {
109
if (type == "archonCrystalUpgrades") {
110
Object.entries(items).forEach(([uniqueName, name]) => {
111
const option = document.createElement("option");
112
option.setAttribute("data-key", uniqueName);
113
option.value = name;
114
document.getElementById("datalist-" + type).appendChild(option);
115
});
116
} else if (type != "badItems") {
109
117
items.forEach(item => {
110
118
if (item.uniqueName in data.badItems) {
111
119
item.name += " (Imposter)";
@@ -127,6 +135,9 @@ function updateInventory() {
127
135
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
128
136
req.done(data => {
129
137
window.itemListPromise.then(itemMap => {
138
window.didInitialInventoryUpdate = true;
139
140
// Populate inventory route
130
141
document.getElementById("warframe-list").innerHTML = "";
131
142
data.Suits.forEach(item => {
132
143
const tr = document.createElement("tr");
@@ -152,13 +163,21 @@ function updateInventory() {
152
163
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`;
153
164
td.appendChild(a);
154
165
}
166
{
167
const a = document.createElement("a");
168
a.href = "/webui/powersuit/" + item.ItemId.$oid;
169
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>`;
170
td.appendChild(a);
171
}
155
172
{
156
173
const a = document.createElement("a");
157
174
a.href = "#";
158
175
a.onclick = function (event) {
159
176
event.preventDefault();
160
177
const name = prompt("Enter new custom name:");
161
renameGear("Suits", item.ItemId.$oid, name);
178
if (name !== null) {
179
renameGear("Suits", item.ItemId.$oid, name);
180
}
162
181
};
163
182
a.title = "Rename";
164
183
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M0 80V229.5c0 17 6.7 33.3 18.7 45.3l176 176c25 25 65.5 25 90.5 0L418.7 317.3c25-25 25-65.5 0-90.5l-176-176c-12-12-28.3-18.7-45.3-18.7H48C21.5 32 0 53.5 0 80zm112 32a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>`;
@@ -179,7 +198,6 @@ function updateInventory() {
179
198
}
180
199
document.getElementById("warframe-list").appendChild(tr);
181
200
});
182
183
201
document.getElementById("weapon-list").innerHTML = "";
184
202
["LongGuns", "Pistols", "Melee"].forEach(category => {
185
203
data[category].forEach(item => {
@@ -212,7 +230,9 @@ function updateInventory() {
212
230
a.onclick = function (event) {
213
231
event.preventDefault();
214
232
const name = prompt("Enter new custom name:");
215
renameGear(category, item.ItemId.$oid, name);
233
if (name !== null) {
234
renameGear(category, item.ItemId.$oid, name);
235
}
216
236
};
217
237
a.title = "Rename";
218
238
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M0 80V229.5c0 17 6.7 33.3 18.7 45.3l176 176c25 25 65.5 25 90.5 0L418.7 317.3c25-25 25-65.5 0-90.5l-176-176c-12-12-28.3-18.7-45.3-18.7H48C21.5 32 0 53.5 0 80zm112 32a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>`;
@@ -235,6 +255,7 @@ function updateInventory() {
235
255
});
236
256
});
237
257
258
// Populate mods route
238
259
document.getElementById("riven-list").innerHTML = "";
239
260
document.getElementById("mods-list").innerHTML = "";
240
261
data.Upgrades.forEach(item => {
@@ -369,6 +390,56 @@ function updateInventory() {
369
390
document.getElementById("mods-list").appendChild(tr);
370
391
}
371
392
});
393
394
// Populate powersuit route
395
if (single.getCurrentPath().substr(0, 17) == "/webui/powersuit/") {
396
const oid = single.getCurrentPath().substr(17);
397
const item = data.Suits.find(x => x.ItemId.$oid == oid);
398
if (item) {
399
if (item.ItemName) {
400
$("#powersuit-route h3").text(item.ItemName);
401
$("#powersuit-route .text-body-secondary").text(itemMap[item.ItemType]?.name ?? item.ItemType);
402
} else {
403
$("#powersuit-route h3").text(itemMap[item.ItemType]?.name ?? item.ItemType);
404
$("#powersuit-route .text-body-secondary").text("");
405
}
406
407
const uniqueUpgrades = {};
408
(item.ArchonCrystalUpgrades ?? []).forEach(upgrade => {
409
uniqueUpgrades[upgrade.UpgradeType] ??= 0;
410
uniqueUpgrades[upgrade.UpgradeType] += 1;
411
});
412
413
document.getElementById("crystals-list").innerHTML = "";
414
Object.entries(uniqueUpgrades).forEach(([upgradeType, count]) => {
415
const tr = document.createElement("tr");
416
{
417
const td = document.createElement("td");
418
td.textContent = count + "x " + (archonCrystalUpgrades[upgradeType] ?? upgradeType);
419
tr.appendChild(td);
420
}
421
{
422
const td = document.createElement("td");
423
td.classList = "text-end";
424
{
425
const a = document.createElement("a");
426
a.href = "#";
427
a.onclick = function (event) {
428
event.preventDefault();
429
doPopArchonCrystalUpgrade(upgradeType);
430
};
431
a.title = "Remove";
432
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>`;
433
td.appendChild(a);
434
}
435
tr.appendChild(td);
436
}
437
document.getElementById("crystals-list").appendChild(tr);
438
});
439
} else {
440
single.loadRoute("/webui/inventory");
441
}
442
}
372
443
});
373
444
});
374
445
}
@@ -656,26 +727,6 @@ $("#mod-to-acquire").on("input", () => {
656
727
$("#mod-to-acquire").removeClass("is-invalid");
657
728
});
658
729
659
function fetchSettings() {
660
fetch("/custom/config")
661
.then(response => response.json())
662
.then(json =>
663
Object.entries(json).forEach(entry => {
664
const [key, value] = entry;
665
var x = document.getElementById(`${key}`);
666
if (x != null) {
667
if (x.type == "checkbox") {
668
if (value === true) {
669
x.setAttribute("checked", "checked");
670
}
671
} else if (x.type == "number") {
672
x.setAttribute("value", `${value}`);
673
}
674
}
675
})
676
);
677
}
678
679
730
const uiConfigs = [
680
731
"autoCreateAccount",
681
732
"skipStoryModeChoice",
@@ -721,27 +772,52 @@ function doChangeSettings() {
721
772
722
773
// Cheats route
723
774
724
fetch("http://localhost:61558/ping", { mode: "no-cors" }).then(() => {
725
$("#client-cheats-nok").addClass("d-none");
726
$("#client-cheats-ok").removeClass("d-none");
775
single.getRoute("/webui/cheats").on("beforeload", function () {
776
fetch("/custom/config")
777
.then(response => response.json())
778
.then(json =>
779
Object.entries(json).forEach(entry => {
780
const [key, value] = entry;
781
var x = document.getElementById(`${key}`);
782
if (x != null) {
783
if (x.type == "checkbox") {
784
if (value === true) {
785
x.setAttribute("checked", "checked");
786
}
787
} else if (x.type == "number") {
788
x.setAttribute("value", `${value}`);
789
}
790
}
791
})
792
);
793
794
fetch("http://localhost:61558/ping", { mode: "no-cors" })
795
.then(() => {
796
$("#client-cheats-ok").removeClass("d-none");
797
$("#client-cheats-nok").addClass("d-none");
727
798
728
fetch("http://localhost:61558/skip_mission_start_timer")
729
.then(res => res.text())
730
.then(res => {
731
document.getElementById("skip_mission_start_timer").checked = res == "1";
732
});
733
document.getElementById("skip_mission_start_timer").onchange = function () {
734
fetch("http://localhost:61558/skip_mission_start_timer?" + this.checked);
735
};
799
fetch("http://localhost:61558/skip_mission_start_timer")
800
.then(res => res.text())
801
.then(res => {
802
document.getElementById("skip_mission_start_timer").checked = res == "1";
803
});
804
document.getElementById("skip_mission_start_timer").onchange = function () {
805
fetch("http://localhost:61558/skip_mission_start_timer?" + this.checked);
806
};
736
807
737
fetch("http://localhost:61558/fov_override")
738
.then(res => res.text())
739
.then(res => {
740
document.getElementById("fov_override").value = parseFloat(res) * 10000;
808
fetch("http://localhost:61558/fov_override")
809
.then(res => res.text())
810
.then(res => {
811
document.getElementById("fov_override").value = parseFloat(res) * 10000;
812
});
813
document.getElementById("fov_override").oninput = function () {
814
fetch("http://localhost:61558/fov_override?" + this.value);
815
};
816
})
817
.catch(function () {
818
$("#client-cheats-nok").removeClass("d-none");
819
$("#client-cheats-ok").addClass("d-none");
741
820
});
742
document.getElementById("fov_override").oninput = function () {
743
fetch("http://localhost:61558/fov_override?" + this.value);
744
};
745
821
});
746
822
747
823
function doUnlockAllFocusSchools() {
@@ -798,3 +874,54 @@ function unlockFocusSchool(upgradeType) {
798
874
});
799
875
});
800
876
}
877
878
// Powersuit Route
879
880
single.getRoute("#powersuit-route").on("beforeload", function () {
881
this.element.querySelector("h3").textContent = "Loading...";
882
if (window.didInitialInventoryUpdate) {
883
updateInventory();
884
}
885
});
886
887
function doPushArchonCrystalUpgrade() {
888
const uniqueName = getKey(document.querySelector("[list='datalist-archonCrystalUpgrades']"));
889
if (!uniqueName) {
890
$("[list='datalist-archonCrystalUpgrades']").addClass("is-invalid").focus();
891
return;
892
}
893
revalidateAuthz(() => {
894
$.get(
895
"/custom/pushArchonCrystalUpgrade?" +
896
window.authz +
897
"&oid=" +
898
single.getCurrentPath().substr(17) +
899
"&type=" +
900
uniqueName +
901
"&count=" +
902
$("#archon-crystal-add-count").val()
903
).done(function () {
904
$("[list='datalist-archonCrystalUpgrades']").val("");
905
updateInventory();
906
});
907
});
908
}
909
910
$("[list='datalist-archonCrystalUpgrades']").on("input", () => {
911
$("[list='datalist-archonCrystalUpgrades']").removeClass("is-invalid");
912
});
913
914
function doPopArchonCrystalUpgrade(type) {
915
revalidateAuthz(() => {
916
$.get(
917
"/custom/popArchonCrystalUpgrade?" +
918
window.authz +
919
"&oid=" +
920
single.getCurrentPath().substr(17) +
921
"&type=" +
922
type
923
).done(function () {
924
updateInventory();
925
});
926
});
927
}
@@ -6,7 +6,6 @@
6
6
body.logged-in #sidebar {
7
7
position: sticky;
8
8
top: 5rem;
9
height: 100px;
10
9
margin-right: 3rem;
11
10
}
12
11