返回提交历史
Modified
src/controllers/api/focusController.ts
+158
-22
Modified
src/models/inventoryModels/inventoryModel.ts
+4
-1
Modified
src/types/inventoryTypes/inventoryTypes.ts
+2
-0
Modified
static/webui/script.js
+2
-2
XFEstudio/XFESpaceNinjaServer
feat: focus 2.0 (#2898)
Implemented all the ops we handle for focus 3.0 + activating/deactivating upgrades + the pool mechanic Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2898 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
737d0136
代码差异
4 个文件
+166
-25
@@ -1,23 +1,91 @@
1
1
import type { RequestHandler } from "express";
2
import { getAccountIdForRequest } from "../../services/loginService.ts";
2
import { getAccountForRequest } from "../../services/loginService.ts";
3
3
import { getInventory, addMiscItems, addEquipment, occupySlot } from "../../services/inventoryService.ts";
4
4
import type { IMiscItem, TFocusPolarity, TEquipmentKey } from "../../types/inventoryTypes/inventoryTypes.ts";
5
5
import { InventorySlot } from "../../types/inventoryTypes/inventoryTypes.ts";
6
6
import { logger } from "../../utils/logger.ts";
7
7
import { ExportFocusUpgrades } from "warframe-public-export-plus";
8
8
import { Inventory } from "../../models/inventoryModels/inventoryModel.ts";
9
import { version_compare } from "../../helpers/inventoryHelpers.ts";
9
10
10
11
export const focusController: RequestHandler = async (req, res) => {
11
const accountId = await getAccountIdForRequest(req);
12
switch (req.query.op) {
12
const account = await getAccountForRequest(req);
13
14
let op = req.query.op as string;
15
const focus2 = account.BuildLabel && version_compare(account.BuildLabel, "2022.04.29.12.53") < 0;
16
if (focus2) {
17
// Focus 2.0
18
switch (req.query.op) {
19
case Focus2Operation.InstallLens:
20
op = "InstallLens";
21
break;
22
case Focus2Operation.UnlockWay:
23
op = "UnlockWay";
24
break;
25
case Focus2Operation.UnlockUpgrade:
26
op = "UnlockUpgrade";
27
break;
28
case Focus2Operation.IncreasePool:
29
op = "IncreasePool";
30
break;
31
case Focus2Operation.LevelUpUpgrade:
32
op = "LevelUpUpgrade";
33
break;
34
case Focus2Operation.ActivateWay:
35
op = "ActivateWay";
36
break;
37
case Focus2Operation.UpdateUpgrade:
38
op = "UpdateUpgrade";
39
break;
40
case Focus2Operation.SentTrainingAmplifier:
41
op = "SentTrainingAmplifier";
42
break;
43
case Focus2Operation.UnbindUpgrade:
44
op = "UnbindUpgrade";
45
break;
46
case Focus2Operation.ConvertShard:
47
op = "ConvertShard";
48
break;
49
}
50
} else {
51
// Focus 3.0
52
switch (req.query.op) {
53
case Focus3Operation.InstallLens:
54
op = "InstallLens";
55
break;
56
case Focus3Operation.UnlockWay:
57
op = "UnlockWay";
58
break;
59
case Focus3Operation.UnlockUpgrade:
60
op = "UnlockUpgrade";
61
break;
62
case Focus3Operation.LevelUpUpgrade:
63
op = "LevelUpUpgrade";
64
break;
65
case Focus3Operation.ActivateWay:
66
op = "ActivateWay";
67
break;
68
case Focus3Operation.SentTrainingAmplifier:
69
op = "SentTrainingAmplifier";
70
break;
71
case Focus3Operation.UnbindUpgrade:
72
op = "UnbindUpgrade";
73
break;
74
case Focus3Operation.ConvertShard:
75
op = "ConvertShard";
76
break;
77
}
78
}
79
80
switch (op) {
13
81
default:
14
82
logger.error("Unhandled focus op type: " + String(req.query.op));
15
83
logger.debug(String(req.body));
16
84
res.end();
17
85
break;
18
case FocusOperation.InstallLens: {
86
case "InstallLens": {
19
87
const request = JSON.parse(String(req.body)) as ILensInstallRequest;
20
const inventory = await getInventory(accountId);
88
const inventory = await getInventory(account._id.toString());
21
89
const item = inventory[request.Category].id(request.WeaponId);
22
90
if (item) {
23
91
item.FocusLens = request.LensType;
@@ -35,10 +103,10 @@ export const focusController: RequestHandler = async (req, res) => {
35
103
});
36
104
break;
37
105
}
38
case FocusOperation.UnlockWay: {
106
case "UnlockWay": {
39
107
const focusType = (JSON.parse(String(req.body)) as IWayRequest).FocusType;
40
108
const focusPolarity = focusTypeToPolarity(focusType);
41
const inventory = await getInventory(accountId, "FocusAbility FocusUpgrades FocusXP");
109
const inventory = await getInventory(account._id.toString(), "FocusAbility FocusUpgrades FocusXP");
42
110
const cost = inventory.FocusAbility ? 50_000 : 0;
43
111
inventory.FocusAbility ??= focusType;
44
112
inventory.FocusUpgrades.push({ ItemType: focusType });
@@ -52,12 +120,29 @@ export const focusController: RequestHandler = async (req, res) => {
52
120
});
53
121
break;
54
122
}
55
case FocusOperation.ActivateWay: {
123
case "IncreasePool": {
124
const request = JSON.parse(String(req.body)) as IIncreasePoolRequest;
125
const focusPolarity = focusTypeToPolarity(request.FocusType);
126
const inventory = await getInventory(account._id.toString(), "FocusXP FocusCapacity");
127
let cost = 0;
128
for (let capacity = request.CurrentTotalCapacity; capacity != request.NewTotalCapacity; ++capacity) {
129
cost += increasePoolCost[capacity - 5];
130
}
131
inventory.FocusXP![focusPolarity]! -= cost;
132
inventory.FocusCapacity = request.NewTotalCapacity;
133
await inventory.save();
134
res.json({
135
TotalCapacity: request.NewTotalCapacity,
136
FocusPointCosts: { [focusPolarity]: cost }
137
});
138
break;
139
}
140
case "ActivateWay": {
56
141
const focusType = (JSON.parse(String(req.body)) as IWayRequest).FocusType;
57
142
58
143
await Inventory.updateOne(
59
144
{
60
accountOwnerId: accountId
145
accountOwnerId: account._id.toString()
61
146
},
62
147
{
63
148
FocusAbility: focusType
@@ -69,13 +154,20 @@ export const focusController: RequestHandler = async (req, res) => {
69
154
});
70
155
break;
71
156
}
72
case FocusOperation.UnlockUpgrade: {
157
case "UnlockUpgrade": {
73
158
const request = JSON.parse(String(req.body)) as IUnlockUpgradeRequest;
74
159
const focusPolarity = focusTypeToPolarity(request.FocusTypes[0]);
75
const inventory = await getInventory(accountId);
160
const inventory = await getInventory(account._id.toString());
76
161
let cost = 0;
77
162
for (const focusType of request.FocusTypes) {
78
cost += ExportFocusUpgrades[focusType].baseFocusPointCost;
163
if (focusType in ExportFocusUpgrades) {
164
cost += ExportFocusUpgrades[focusType].baseFocusPointCost;
165
} else if (focusType == "/Lotus/Upgrades/Focus/Power/Residual/ChannelEfficiencyFocusUpgrade") {
166
// Zenurik's Inner Might (Focus 2.0)
167
cost += 50_000;
168
} else {
169
logger.warn(`unknown focus upgrade ${focusType}, will unlock it for free`);
170
}
79
171
inventory.FocusUpgrades.push({ ItemType: focusType, Level: 0 });
80
172
}
81
173
inventory.FocusXP![focusPolarity]! -= cost;
@@ -86,15 +178,20 @@ export const focusController: RequestHandler = async (req, res) => {
86
178
});
87
179
break;
88
180
}
89
case FocusOperation.LevelUpUpgrade: {
181
case "LevelUpUpgrade":
182
case "UpdateUpgrade": {
90
183
const request = JSON.parse(String(req.body)) as ILevelUpUpgradeRequest;
91
184
const focusPolarity = focusTypeToPolarity(request.FocusInfos[0].ItemType);
92
const inventory = await getInventory(accountId);
185
const inventory = await getInventory(account._id.toString());
93
186
let cost = 0;
94
187
for (const focusUpgrade of request.FocusInfos) {
95
188
cost += focusUpgrade.FocusXpCost;
96
189
const focusUpgradeDb = inventory.FocusUpgrades.find(entry => entry.ItemType == focusUpgrade.ItemType)!;
97
focusUpgradeDb.Level = focusUpgrade.Level;
190
if (op == "UpdateUpgrade") {
191
focusUpgradeDb.IsActive = focusUpgrade.IsActive;
192
} else {
193
focusUpgradeDb.Level = focusUpgrade.Level;
194
}
98
195
}
99
196
inventory.FocusXP![focusPolarity]! -= cost;
100
197
await inventory.save();
@@ -104,9 +201,9 @@ export const focusController: RequestHandler = async (req, res) => {
104
201
});
105
202
break;
106
203
}
107
case FocusOperation.SentTrainingAmplifier: {
204
case "SentTrainingAmplifier": {
108
205
const request = JSON.parse(String(req.body)) as ISentTrainingAmplifierRequest;
109
const inventory = await getInventory(accountId);
206
const inventory = await getInventory(account._id.toString());
110
207
const inventoryChanges = addEquipment(inventory, "OperatorAmps", request.StartingWeaponType, {
111
208
ModularParts: [
112
209
"/Lotus/Weapons/Sentients/OperatorAmplifiers/SentTrainingAmplifier/SentAmpTrainingGrip",
@@ -119,10 +216,10 @@ export const focusController: RequestHandler = async (req, res) => {
119
216
res.json(inventoryChanges.OperatorAmps![0]);
120
217
break;
121
218
}
122
case FocusOperation.UnbindUpgrade: {
219
case "UnbindUpgrade": {
123
220
const request = JSON.parse(String(req.body)) as IUnbindUpgradeRequest;
124
221
const focusPolarity = focusTypeToPolarity(request.FocusTypes[0]);
125
const inventory = await getInventory(accountId);
222
const inventory = await getInventory(account._id.toString());
126
223
inventory.FocusXP![focusPolarity]! -= 750_000 * request.FocusTypes.length;
127
224
addMiscItems(inventory, [
128
225
{
@@ -149,7 +246,7 @@ export const focusController: RequestHandler = async (req, res) => {
149
246
});
150
247
break;
151
248
}
152
case FocusOperation.ConvertShard: {
249
case "ConvertShard": {
153
250
const request = JSON.parse(String(req.body)) as IConvertShardRequest;
154
251
// Tally XP
155
252
let xp = 0;
@@ -167,7 +264,7 @@ export const focusController: RequestHandler = async (req, res) => {
167
264
for (const shard of request.Shards) {
168
265
shard.ItemCount *= -1;
169
266
}
170
const inventory = await getInventory(accountId);
267
const inventory = await getInventory(account._id.toString());
171
268
const polarity = request.Polarity;
172
269
inventory.FocusXP ??= {};
173
270
inventory.FocusXP[polarity] ??= 0;
@@ -179,7 +276,8 @@ export const focusController: RequestHandler = async (req, res) => {
179
276
}
180
277
};
181
278
182
enum FocusOperation {
279
// Focus 3.0
280
enum Focus3Operation {
183
281
InstallLens = "1",
184
282
UnlockWay = "2",
185
283
UnlockUpgrade = "3",
@@ -190,6 +288,20 @@ enum FocusOperation {
190
288
ConvertShard = "9"
191
289
}
192
290
291
// Focus 2.0
292
enum Focus2Operation {
293
InstallLens = "1",
294
UnlockWay = "2",
295
UnlockUpgrade = "3",
296
IncreasePool = "4",
297
LevelUpUpgrade = "5",
298
ActivateWay = "6",
299
UpdateUpgrade = "7", // used to change the IsActive state, same format as ILevelUpUpgradeRequest
300
SentTrainingAmplifier = "9",
301
UnbindUpgrade = "10",
302
ConvertShard = "11"
303
}
304
193
305
// For UnlockWay & ActivateWay
194
306
interface IWayRequest {
195
307
FocusType: string;
@@ -199,6 +311,13 @@ interface IUnlockUpgradeRequest {
199
311
FocusTypes: string[];
200
312
}
201
313
314
// Focus 2.0
315
interface IIncreasePoolRequest {
316
FocusType: string;
317
CurrentTotalCapacity: number;
318
NewTotalCapacity: number;
319
}
320
202
321
interface ILevelUpUpgradeRequest {
203
322
FocusInfos: {
204
323
ItemType: string;
@@ -206,6 +325,7 @@ interface ILevelUpUpgradeRequest {
206
325
IsUniversal: boolean;
207
326
Level: number;
208
327
IsActiveAbility: boolean;
328
IsActive?: number; // Focus 2.0
209
329
}[];
210
330
}
211
331
@@ -240,3 +360,19 @@ const shardValues = {
240
360
"/Lotus/Types/Gameplay/Eidolon/Resources/SentientShards/SentientShardBrilliantItem": 25_000,
241
361
"/Lotus/Types/Gameplay/Eidolon/Resources/SentientShards/SentientShardBrilliantTierTwoItem": 40_000
242
362
};
363
364
// Starting at a capacity of 5 (Source: https://wiki.warframe.com/w/Focus_2.0)
365
const increasePoolCost = [
366
2576, 3099, 3638, 4190, 4755, 5331, 5918, 6514, 7120, 7734, 8357, 8988, 9626, 10271, 10923, 11582, 12247, 12918,
367
13595, 14277, 14965, 15659, 16357, 17061, 17769, 18482, 19200, 19922, 20649, 21380, 22115, 22854, 23597, 24344,
368
25095, 25850, 26609, 27371, 28136, 28905, 29678, 30454, 31233, 32015, 32801, 33590, 34382, 35176, 35974, 36775,
369
37579, 38386, 39195, 40008, 40823, 41641, 42461, 43284, 44110, 44938, 45769, 46603, 47439, 48277, 49118, 49961,
370
50807, 51655, 52505, 53357, 54212, 55069, 55929, 56790, 57654, 58520, 59388, 60258, 61130, 62005, 62881, 63759,
371
64640, 65522, 66407, 67293, 68182, 69072, 69964, 70858, 71754, 72652, 73552, 74453, 75357, 76262, 77169, 78078,
372
78988, 79900, 80814, 81730, 82648, 83567, 84488, 85410, 86334, 87260, 88188, 89117, 90047, 90980, 91914, 92849,
373
93786, 94725, 95665, 96607, 97550, 98495, 99441, 100389, 101338, 102289, 103241, 104195, 105150, 106107, 107065,
374
108024, 108985, 109948, 110911, 111877, 112843, 113811, 114780, 115751, 116723, 117696, 118671, 119647, 120624,
375
121603, 122583, 123564, 124547, 125531, 126516, 127503, 128490, 129479, 130470, 131461, 132454, 133448, 134443,
376
135440, 136438, 137437, 138437, 139438, 140441, 141444, 142449, 143455, 144463, 145471, 146481, 147492, 148503,
377
149517
378
];
@@ -146,7 +146,8 @@ const focusUpgradeSchema = new Schema<IFocusUpgrade>(
146
146
{
147
147
ItemType: String,
148
148
Level: Number,
149
IsUniversal: Boolean
149
IsUniversal: Boolean,
150
IsActive: Number
150
151
},
151
152
{ _id: false }
152
153
);
@@ -1542,6 +1543,8 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
1542
1543
FocusAbility: String,
1543
1544
//The treeways of the Focus school.(Active and passive Ability)
1544
1545
FocusUpgrades: [focusUpgradeSchema],
1546
//Focus 2.0 Pool
1547
FocusCapacity: Number,
1545
1548
1546
1549
//Achievement
1547
1550
ChallengeProgress: [challengeProgressSchema],
@@ -340,6 +340,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
340
340
EmailItems: ITypeCount[];
341
341
CompletedSyndicates: string[];
342
342
FocusXP?: IFocusXP;
343
FocusCapacity?: number;
343
344
Wishlist: string[];
344
345
Alignment?: IAlignment;
345
346
CompletedSorties: string[];
@@ -638,6 +639,7 @@ export interface IFocusUpgrade {
638
639
ItemType: string;
639
640
Level?: number;
640
641
IsUniversal?: boolean;
642
IsActive?: number; // Focus 2.0
641
643
}
642
644
643
645
export interface IFocusXP {
@@ -3276,13 +3276,13 @@ function unlockFocusSchool(upgradeType) {
3276
3276
return new Promise(resolve => {
3277
3277
// Deselect current FocusAbility so we will be able to unlock the way for free
3278
3278
$.post({
3279
url: "/api/focus.php?" + window.authz + "&op=5",
3279
url: "/api/focus.php?" + window.authz + "&op=ActivateWay",
3280
3280
contentType: "text/plain",
3281
3281
data: JSON.stringify({ FocusType: null })
3282
3282
}).done(function () {
3283
3283
// Unlock the way now
3284
3284
$.post({
3285
url: "/api/focus.php?" + window.authz + "&op=2",
3285
url: "/api/focus.php?" + window.authz + "&op=UnlockWay",
3286
3286
contentType: "text/plain",
3287
3287
data: JSON.stringify({
3288
3288
FocusType: upgradeType