返回提交历史
Added
src/controllers/api/descentRewardsController.ts
+357
-0
Modified
src/controllers/api/purchaseController.ts
+8
-2
Modified
src/models/inventoryModels/inventoryModel.ts
+34
-1
Modified
src/routes/api.ts
+3
-1
Added
src/services/descentService.ts
+1003
-0
Modified
src/services/worldStateService.ts
+8
-0
Modified
src/types/inventoryTypes/inventoryTypes.ts
+23
-0
Modified
src/types/worldStateTypes.ts
+17
-0
Modified
static/fixed_responses/gameToBuildVersion.json
+1
-0
XFEstudio/SpaceNinjaServer
feat: descent generation (#3134)
Re #3129 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/3134 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
5e37cd91
代码差异
9 个文件
+1454
-4
@@ -0,0 +1,357 @@
1
import type { RequestHandler } from "express";
2
import { getAccountForRequest } from "../../services/loginService.ts";
3
import { getJSONfromString } from "../../helpers/stringHelpers.ts";
4
import type { TDescentCategory } from "../../types/inventoryTypes/inventoryTypes.ts";
5
import { getInventory } from "../../services/inventoryService.ts";
6
import type { ICountedStoreItem } from "warframe-public-export-plus";
7
import { getRandomElement, getRandomInt } from "../../services/rngService.ts";
8
import { logger } from "../../utils/logger.ts";
9
import { version_compare } from "../../helpers/inventoryHelpers.ts";
10
import gameToBuildVersion from "../../../static/fixed_responses/gameToBuildVersion.json" with { type: "json" };
11
12
export const descentRewardsController: RequestHandler = async (req, res) => {
13
const account = await getAccountForRequest(req);
14
if (account.BuildLabel && version_compare(account.BuildLabel, gameToBuildVersion["41.0.0"]) < 0) {
15
throw new Error(
16
`account logged into ${account.BuildLabel} (< 41.0.0) but is now attempting to call a >= 41.0.0 endpoint ?!`
17
);
18
}
19
const payload = getJSONfromString<IDescentRewardsRequest>(String(req.body));
20
if (payload.Mode == "r") {
21
const inventory = await getInventory(account._id.toString(), "DescentRewards");
22
inventory.DescentRewards ??= [];
23
let entry = inventory.DescentRewards.find(x => x.Category == payload.Category);
24
if (!entry) {
25
entry = {
26
Category: payload.Category,
27
Expiry: new Date(0),
28
FloorsClaimed: 0,
29
PendingRewards: [],
30
Seed: 0,
31
SelectedUpgrades: []
32
};
33
inventory.DescentRewards.push(entry);
34
}
35
36
const weekStart = 1734307200_000 + Math.trunc((Date.now() - 1734307200_000) / 604800000) * 604800000;
37
const weekEnd = weekStart + 604800000;
38
39
if (entry.Expiry.getTime() != weekEnd) {
40
entry.Expiry = new Date(weekEnd);
41
entry.FloorsClaimed = 0;
42
entry.PendingRewards = [
43
{
44
FloorCheckpoint: 2,
45
Rewards: [getRandomElement(bronzeRewards[payload.Category])!]
46
},
47
{
48
FloorCheckpoint: 4,
49
Rewards: [
50
getRandomElement(
51
payload.Category == "DM_COH_NORMAL" ? bronzeRewards.DM_COH_NORMAL : spSilverRewards
52
)!
53
]
54
},
55
{
56
FloorCheckpoint: 6,
57
Rewards: [getRandomElement(arcaneRewards)!]
58
},
59
{
60
FloorCheckpoint: 9,
61
Rewards: [getRandomElement(bronzeRewards[payload.Category])!]
62
},
63
{
64
FloorCheckpoint: 11,
65
Rewards: [
66
getRandomElement(
67
payload.Category == "DM_COH_NORMAL" ? bronzeRewards.DM_COH_NORMAL : spSilverRewards
68
)!
69
]
70
},
71
{
72
FloorCheckpoint: 13,
73
Rewards: [getRandomElement(arcaneRewards)!]
74
},
75
{
76
FloorCheckpoint: 16,
77
Rewards: [getRandomElement(bronzeRewards[payload.Category])!]
78
},
79
{
80
FloorCheckpoint: 18,
81
Rewards: [
82
payload.Category == "DM_COH_NORMAL"
83
? getRandomElement(bronzeRewards.DM_COH_NORMAL)!
84
: {
85
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/SteelEssence",
86
ItemCount: 25
87
}
88
]
89
},
90
{
91
FloorCheckpoint: 20,
92
Rewards: [getRandomElement(tripleArcaneRewards)!]
93
},
94
{
95
FloorCheckpoint: 21,
96
Rewards: [getRandomElement(finalRewards[payload.Category])!]
97
}
98
];
99
entry.Seed = getRandomInt(-1_000_000_000, 1_000_000_000);
100
entry.SelectedUpgrades = [];
101
}
102
103
await inventory.save();
104
res.json({
105
Expiry: { $date: { $numberLong: weekEnd.toString() } },
106
FloorClaimed: entry.FloorsClaimed,
107
PendingRewards: entry.PendingRewards,
108
Seed: entry.Seed,
109
SelectedUpgrades: entry.SelectedUpgrades
110
});
111
} else {
112
logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
113
throw new Error(`unexpected descentRewards mode: ${payload.Mode}`);
114
}
115
};
116
117
type IDescentRewardsRequest =
118
| {
119
Mode: "r";
120
Category: TDescentCategory;
121
}
122
| {
123
Mode: "something else";
124
};
125
126
// https://wiki.warframe.com/w/The_Descendia#Rewards
127
128
const bronzeRewards: Record<TDescentCategory, ICountedStoreItem[]> = {
129
DM_COH_NORMAL: [
130
{
131
StoreItem: "/Lotus/StoreItems/Types/PickUps/Credits/10000Credits",
132
ItemCount: 3
133
},
134
{
135
StoreItem: "/Lotus/StoreItems/Upgrades/Mods/FusionBundles/JunctionRewardNPFusionBundleA",
136
ItemCount: 1
137
},
138
{
139
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/DistillPoints",
140
ItemCount: 50
141
},
142
{
143
StoreItem: "/Lotus/StoreItems/Types/Gameplay/Tau/Resources/CoHResourceCommonItem",
144
ItemCount: 25
145
},
146
{
147
StoreItem: "/Lotus/StoreItems/Types/Gameplay/Tau/Resources/CoHResourceRareItem",
148
ItemCount: 5
149
}
150
],
151
DM_COH_HARD: [
152
{
153
StoreItem: "/Lotus/StoreItems/Types/Gameplay/Tau/Resources/CoHResourceCommonItem",
154
ItemCount: 75
155
},
156
{
157
StoreItem: "/Lotus/StoreItems/Types/Gameplay/Tau/Resources/CoHResourceRareItem",
158
ItemCount: 15
159
}
160
]
161
};
162
163
const arcaneRewards: ICountedStoreItem[] = [
164
{
165
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Offensive/DamageForBonusArmour",
166
ItemCount: 1
167
},
168
{
169
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Offensive/SplitStatusProcsOnStackedStatusHit",
170
ItemCount: 1
171
},
172
{
173
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Offensive/MultishotForMaxEnergy",
174
ItemCount: 1
175
},
176
{
177
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Utility/AbilityDurationOnCast",
178
ItemCount: 1
179
},
180
{
181
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Defensive/ShieldMaxForAbilityStrength",
182
ItemCount: 1
183
},
184
{
185
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Defensive/MaxDPSTakenForArmour",
186
ItemCount: 1
187
},
188
{
189
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Defensive/StealDefensiveStatsOnRoll",
190
ItemCount: 1
191
},
192
{
193
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Offensive/RadialDamageOnMaxRadiationStackHit",
194
ItemCount: 1
195
},
196
{
197
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Utility/FreezeEnemiesOnRoll",
198
ItemCount: 1
199
}
200
];
201
202
const tripleArcaneRewards: ICountedStoreItem[] = [
203
{
204
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Offensive/DamageForBonusArmour",
205
ItemCount: 3
206
},
207
{
208
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Offensive/SplitStatusProcsOnStackedStatusHit",
209
ItemCount: 3
210
},
211
{
212
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Offensive/MultishotForMaxEnergy",
213
ItemCount: 3
214
},
215
{
216
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Utility/AbilityDurationOnCast",
217
ItemCount: 3
218
},
219
{
220
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Defensive/ShieldMaxForAbilityStrength",
221
ItemCount: 3
222
},
223
{
224
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Defensive/MaxDPSTakenForArmour",
225
ItemCount: 3
226
},
227
{
228
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Defensive/StealDefensiveStatsOnRoll",
229
ItemCount: 3
230
},
231
{
232
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Offensive/RadialDamageOnMaxRadiationStackHit",
233
ItemCount: 3
234
},
235
{
236
StoreItem: "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Utility/FreezeEnemiesOnRoll",
237
ItemCount: 3
238
}
239
];
240
241
const spSilverRewards: ICountedStoreItem[] = [
242
{
243
StoreItem: "/Lotus/StoreItems/Types/Recipes/Components/FormaBlueprint",
244
ItemCount: 1
245
},
246
{
247
StoreItem: "/Lotus/StoreItems/Upgrades/Mods/Randomized/RawMeleeRandomMod",
248
ItemCount: 1
249
},
250
{
251
StoreItem: "/Lotus/StoreItems/Upgrades/Mods/Randomized/RawPistolRandomMod",
252
ItemCount: 1
253
},
254
{
255
StoreItem: "/Lotus/StoreItems/Upgrades/Mods/Randomized/RawRifleRandomMod",
256
ItemCount: 1
257
},
258
{
259
StoreItem: "/Lotus/StoreItems/Upgrades/Mods/Randomized/RawShotgunRandomMod",
260
ItemCount: 1
261
},
262
{
263
StoreItem: "/Lotus/StoreItems/Upgrades/Mods/Randomized/RawModularMeleeRandomMod",
264
ItemCount: 1
265
},
266
{
267
StoreItem: "/Lotus/StoreItems/Upgrades/Mods/Randomized/RawModularPistolRandomMod",
268
ItemCount: 1
269
},
270
{
271
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/WeaponPrimaryArcaneUnlocker",
272
ItemCount: 1
273
},
274
{
275
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/WeaponSecondaryArcaneUnlocker",
276
ItemCount: 1
277
},
278
{
279
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/WeaponMeleeArcaneUnlocker",
280
ItemCount: 1
281
},
282
{
283
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/WeaponAmpArcaneUnlocker",
284
ItemCount: 1
285
}
286
];
287
288
const finalRewards: Record<TDescentCategory, ICountedStoreItem[]> = {
289
DM_COH_NORMAL: [
290
{
291
StoreItem: "/Lotus/StoreItems/Types/Recipes/Components/FormaBlueprint",
292
ItemCount: 1
293
},
294
{
295
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/WeaponPrimaryArcaneUnlocker",
296
ItemCount: 1
297
},
298
{
299
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/WeaponSecondaryArcaneUnlocker",
300
ItemCount: 1
301
},
302
{
303
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/WeaponMeleeArcaneUnlocker",
304
ItemCount: 1
305
},
306
{
307
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/WeaponAmpArcaneUnlocker",
308
ItemCount: 1
309
}
310
],
311
DM_COH_HARD: [
312
{
313
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/OrokinCatalyst",
314
ItemCount: 1
315
},
316
{
317
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/OrokinReactor",
318
ItemCount: 1
319
},
320
{
321
StoreItem: "/Lotus/StoreItems/Types/Recipes/Components/FormaAuraBlueprint",
322
ItemCount: 1
323
},
324
{
325
StoreItem: "/Lotus/StoreItems/Types/Recipes/Lens/AttackLensOstronBlueprint",
326
ItemCount: 1
327
},
328
{
329
StoreItem: "/Lotus/StoreItems/Types/Recipes/Lens/DefenseLensOstronBlueprint",
330
ItemCount: 1
331
},
332
{
333
StoreItem: "/Lotus/StoreItems/Types/Recipes/Lens/PowerLensOstronBlueprint",
334
ItemCount: 1
335
},
336
{
337
StoreItem: "/Lotus/StoreItems/Types/Recipes/Lens/TacticLensOstronBlueprint",
338
ItemCount: 1
339
},
340
{
341
StoreItem: "/Lotus/StoreItems/Types/Recipes/Lens/WardLensOstronBlueprint",
342
ItemCount: 1
343
},
344
{
345
StoreItem: "/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalAmar",
346
ItemCount: 1
347
},
348
{
349
StoreItem: "/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalNira",
350
ItemCount: 1
351
},
352
{
353
StoreItem: "/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalBoreal",
354
ItemCount: 1
355
}
356
]
357
};
@@ -1,5 +1,5 @@
1
1
import type { RequestHandler } from "express";
2
import { getAccountIdForRequest } from "../../services/loginService.ts";
2
import { getAccountForRequest } from "../../services/loginService.ts";
3
3
import type { IPurchaseRequest } from "../../types/purchaseTypes.ts";
4
4
import { handlePurchase } from "../../services/purchaseService.ts";
5
5
import { getInventory } from "../../services/inventoryService.ts";
@@ -7,7 +7,13 @@ import { sendWsBroadcastTo } from "../../services/wsService.ts";
7
7
8
8
export const purchaseController: RequestHandler = async (req, res) => {
9
9
const purchaseRequest = JSON.parse(String(req.body)) as IPurchaseRequest;
10
const accountId = await getAccountIdForRequest(req);
10
const account = await getAccountForRequest(req);
11
if (purchaseRequest.buildLabel && account.BuildLabel && purchaseRequest.buildLabel != account.BuildLabel) {
12
throw new Error(
13
`account logged into ${account.BuildLabel} but is now attempting a purchase in ${purchaseRequest.buildLabel} ?!`
14
);
15
}
16
const accountId = account._id.toString();
11
17
const inventory = await getInventory(accountId);
12
18
const response = await handlePurchase(purchaseRequest, inventory);
13
19
await inventory.save();
@@ -92,7 +92,10 @@ import type {
92
92
INokkoColony,
93
93
IJournalEntry,
94
94
IDialogueResetDateClient,
95
IDialogueResetDateDatabase
95
IDialogueResetDateDatabase,
96
IDescentLevelReward,
97
IDescentCategoryRewardClient,
98
IDescentCategoryRewardDatabase
96
99
} from "../../types/inventoryTypes/inventoryTypes.ts";
97
100
import { equipmentKeys } from "../../types/inventoryTypes/inventoryTypes.ts";
98
101
import type { IOid, ITypeCount } from "../../types/commonTypes.ts";
@@ -867,6 +870,34 @@ endlessXpProgressSchema.set("toJSON", {
867
870
}
868
871
});
869
872
873
const descentLevelRewardSchema = new Schema<IDescentLevelReward>(
874
{
875
FloorCheckpoint: Number,
876
Rewards: [countedStoreItemSchema]
877
},
878
{ _id: false }
879
);
880
881
const descentCategoryRewardSchema = new Schema<IDescentCategoryRewardDatabase>(
882
{
883
Category: { type: String, required: true },
884
Expiry: Date,
885
FloorsClaimed: { type: Number, default: 0 },
886
PendingRewards: { type: [descentLevelRewardSchema], default: [] },
887
Seed: Number,
888
SelectedUpgrades: { type: [String], default: [] }
889
},
890
{ _id: false }
891
);
892
descentCategoryRewardSchema.set("toJSON", {
893
transform(_doc, ret: Record<string, any>) {
894
const db = ret as IDescentCategoryRewardDatabase;
895
const client = ret as IDescentCategoryRewardClient;
896
897
client.Expiry = toMongoDate(db.Expiry);
898
}
899
});
900
870
901
const crewShipWeaponEmplacementsSchema = new Schema<ICrewShipWeaponEmplacementsDatabase>(
871
902
{
872
903
PRIMARY_A: EquipmentSelectionSchema,
@@ -1862,6 +1893,8 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
1862
1893
1863
1894
EndlessXP: { type: [endlessXpProgressSchema], default: undefined },
1864
1895
1896
DescentRewards: { type: [descentCategoryRewardSchema], default: undefined },
1897
1865
1898
DialogueHistory: dialogueHistorySchema,
1866
1899
CalendarProgress: calenderProgressSchema,
1867
1900
@@ -46,6 +46,7 @@ import { customObstacleCourseLeaderboardController } from "../controllers/api/cu
46
46
import { declineAllianceInviteController } from "../controllers/api/declineAllianceInviteController.ts";
47
47
import { declineGuildInviteController } from "../controllers/api/declineGuildInviteController.ts";
48
48
import { deleteSessionController } from "../controllers/api/deleteSessionController.ts";
49
import { descentRewardsController } from "../controllers/api/descentRewardsController.ts";
49
50
import { destroyDojoDecoController } from "../controllers/api/destroyDojoDecoController.ts";
50
51
import { divvyAllianceVaultController } from "../controllers/api/divvyAllianceVaultController.ts";
51
52
import { dojoComponentRushController } from "../controllers/api/dojoComponentRushController.ts";
@@ -280,6 +281,7 @@ apiRouter.post("/crewShipFusion.php", crewShipFusionController);
280
281
apiRouter.post("/crewShipIdentifySalvage.php", crewShipIdentifySalvageController);
281
282
apiRouter.post("/customizeGuildRanks.php", customizeGuildRanksController);
282
283
apiRouter.post("/customObstacleCourseLeaderboard.php", customObstacleCourseLeaderboardController);
284
apiRouter.post("/descentRewards.php", descentRewardsController);
283
285
apiRouter.post("/destroyDojoDeco.php", destroyDojoDecoController);
284
286
apiRouter.post("/dojoComponentRush.php", dojoComponentRushController);
285
287
apiRouter.post("/drones.php", dronesController);
@@ -312,6 +314,7 @@ apiRouter.post("/hubBlessing.php", hubBlessingController);
312
314
apiRouter.post("/inbox.php", inboxController); // from ~U15, don't know when they changed it to GET
313
315
apiRouter.post("/infestedFoundry.php", infestedFoundryController);
314
316
apiRouter.post("/instantCompleteRecipe.php", claimCompletedRecipeController); // U8
317
apiRouter.post("/inventory.php", inventoryController); // used by companion app
315
318
apiRouter.post("/inventorySlots.php", inventorySlotsController);
316
319
apiRouter.post("/joinSession.php", joinSessionController);
317
320
apiRouter.post("/login.php", loginController);
@@ -381,6 +384,5 @@ apiRouter.post("/updateTheme.php", updateThemeController);
381
384
apiRouter.post("/upgrades.php", upgradesController);
382
385
apiRouter.post("/valenceSwap.php", valenceSwapController);
383
386
apiRouter.post("/wishlist.php", wishlistController);
384
apiRouter.post("/inventory.php", inventoryController); // used by companion app
385
387
386
388
export { apiRouter };
@@ -43,6 +43,7 @@ import { logger } from "../utils/logger.ts";
43
43
import { DailyDeal, Fissure } from "../models/worldStateModel.ts";
44
44
import { factionToInt, getConquest, getMissionTypeForLegacyOverride } from "./conquestService.ts";
45
45
import gameToBuildVersion from "../../static/fixed_responses/gameToBuildVersion.json" with { type: "json" };
46
import { getDescent } from "./descentService.ts";
46
47
47
48
const sortieBosses = [
48
49
"SORTIE_BOSS_HYENA",
@@ -3612,6 +3613,13 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
3612
3613
}
3613
3614
}
3614
3615
3616
if (!buildLabel || version_compare(buildLabel, gameToBuildVersion["41.0.0"]) >= 0) {
3617
worldState.Descents = [getDescent(week)];
3618
if (isBeforeNextExpectedWorldStateRefresh(timeMs, weekEnd)) {
3619
worldState.Descents.push(getDescent(week + 1));
3620
}
3621
}
3622
3615
3623
// Sentient Anomaly + Xtra Cheese cycles
3616
3624
const halfHour = Math.trunc(timeMs / (unixTimesInMs.hour / 2));
3617
3625
const hourInSeconds = 3600;
@@ -111,6 +111,7 @@ export interface IInventoryDatabase
111
111
| "QualifyingInvasions"
112
112
| "LastInventorySync"
113
113
| "EndlessXP"
114
| "DescentRewards"
114
115
| "PersonalGoalProgress"
115
116
| "CurrentLoadOutIds"
116
117
| TEquipmentKey
@@ -156,6 +157,7 @@ export interface IInventoryDatabase
156
157
QualifyingInvasions: IInvasionProgressDatabase[];
157
158
LastInventorySync?: Types.ObjectId;
158
159
EndlessXP?: IEndlessXpProgressDatabase[];
160
DescentRewards?: IDescentCategoryRewardDatabase[];
159
161
PersonalGoalProgress?: IGoalProgressDatabase[];
160
162
MissionRelicRewards?: ITypeCount[];
161
163
}
@@ -419,6 +421,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
419
421
Harvestable: boolean;
420
422
DeathSquadable: boolean;
421
423
EndlessXP?: IEndlessXpProgressClient[];
424
DescentRewards?: IDescentCategoryRewardClient[];
422
425
DialogueHistory?: IDialogueHistoryClient;
423
426
CalendarProgress?: ICalendarProgress;
424
427
SongChallenges?: ISongChallenge[];
@@ -1129,6 +1132,26 @@ export interface IEndlessXpReward {
1129
1132
Rewards: ICountedStoreItem[];
1130
1133
}
1131
1134
1135
export type TDescentCategory = "DM_COH_NORMAL" | "DM_COH_HARD";
1136
1137
export interface IDescentCategoryRewardClient {
1138
Category: TDescentCategory;
1139
Expiry: IMongoDate;
1140
FloorsClaimed: number;
1141
PendingRewards: IDescentLevelReward[];
1142
Seed: number;
1143
SelectedUpgrades: string[];
1144
}
1145
1146
export interface IDescentCategoryRewardDatabase extends Omit<IDescentCategoryRewardClient, "Expiry"> {
1147
Expiry: Date;
1148
}
1149
1150
export interface IDescentLevelReward {
1151
FloorCheckpoint: number;
1152
Rewards: ICountedStoreItem[];
1153
}
1154
1132
1155
export interface IDialogueHistoryClient {
1133
1156
YearIteration?: number;
1134
1157
Resets?: number; // added in 38.5.0, removed in 41.0.0
@@ -36,6 +36,7 @@ export interface IWorldState {
36
36
};
37
37
KnownCalendarSeasons: ICalendarSeason[];
38
38
Conquests?: IConquest[];
39
Descents?: IDescent[];
39
40
Tmp?: string;
40
41
}
41
42
@@ -468,6 +469,22 @@ export interface IConquestMission {
468
469
];
469
470
}
470
471
472
export interface IDescent {
473
Activation: IMongoDate;
474
Expiry: IMongoDate;
475
RandSeed: number;
476
Challenges: IDescentFloor[];
477
}
478
479
export interface IDescentFloor {
480
Index: number; // 1..21
481
Type: string;
482
Challenge: string;
483
Level: string;
484
Specs: string[];
485
Auras: string[];
486
}
487
471
488
export interface ITmp {
472
489
cavabegin: string;
473
490
PurchasePlatformLockEnabled: boolean; // Seems unused
@@ -1,4 +1,5 @@
1
1
{
2
"41.0.0": "2025.12.09.14.18",
2
3
"40.0.0": "2025.09.25.17.01",
3
4
"39.1.0": "2025.08.26.09.49",
4
5
"38.6.0": "2025.05.20.10.18",