返回提交历史
Added
src/controllers/api/guildVaultBonusRewardsController.ts
+183
-0
Modified
src/controllers/api/inventoryController.ts
+3
-0
Modified
src/models/inventoryModels/inventoryModel.ts
+26
-2
Modified
src/routes/api.ts
+2
-0
Modified
src/services/importService.ts
+3
-0
Modified
src/types/inventoryTypes/inventoryTypes.ts
+15
-0
XFEstudio/XFESpaceNinjaServer
feat: roll guild vault bonus (#4309)
Initial implementation re #4296 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/4309 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
7685db16
代码差异
6 个文件
+232
-2
@@ -0,0 +1,183 @@
1
import type { RequestHandler } from "express";
2
import { logger } from "../../utils/logger.ts";
3
import { getRandomElement } from "../../services/rngService.ts";
4
import type { ITypeCount } from "../../types/commonTypes.ts";
5
import type { IWeekGuildVaultBonusReward } from "../../types/inventoryTypes/inventoryTypes.ts";
6
import { getAccountIdForRequest } from "../../services/loginService.ts";
7
import { getInventory2 } from "../../services/inventoryService.ts";
8
9
export const guildVaultBonusRewardsController: RequestHandler = async (req, res) => {
10
if (req.query.gvbMode == "r") {
11
const accountId = await getAccountIdForRequest(req);
12
const payload = JSON.parse(String(req.body)) as IRollGuildVaultBonusRequest;
13
14
const inventory = await getInventory2(accountId, "WeeklyGuildVaultBonusInfo");
15
if (inventory.WeeklyGuildVaultBonusInfo?.WeekCount != payload.WeekCount) {
16
const tierAReward = getRandomElement(tierARewards)!;
17
const tierBReward = getRandomElement(tierBRewards)!;
18
const tierCReward = getRandomElement(tierCRewards)!;
19
const tierDReward = getRandomElement(tierDRewards)!;
20
inventory.WeeklyGuildVaultBonusInfo = {
21
Progress: 0,
22
WeekCount: payload.WeekCount,
23
BonusRegion: "/Lotus/Language/Locations/Earth", // TODO: Is this the correct format? What planets are eligible? Does the server need to handle anything for this "bonus"?
24
Rewards: [
25
{
26
RewardClaimed: false,
27
PointThreshold: 500,
28
ItemCount: tierAReward.ItemCount,
29
Reward: tierAReward.ItemType
30
},
31
{
32
RewardClaimed: false,
33
PointThreshold: 1000,
34
ItemCount: tierBReward.ItemCount,
35
Reward: tierBReward.ItemType
36
},
37
{
38
RewardClaimed: false,
39
PointThreshold: 1500,
40
ItemCount: tierCReward.ItemCount,
41
Reward: tierCReward.ItemType
42
},
43
{
44
RewardClaimed: false,
45
PointThreshold: 2000,
46
ItemCount: tierDReward.ItemCount,
47
Reward: tierDReward.ItemType
48
}
49
]
50
};
51
await inventory.save();
52
}
53
54
res.json({
55
NewRewards: inventory.WeeklyGuildVaultBonusInfo.Rewards,
56
BonusRegion: inventory.WeeklyGuildVaultBonusInfo.BonusRegion
57
} satisfies IRollGuildVaultBonusResponse);
58
} else {
59
logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
60
throw new Error(`unexpected guildVaultBonusRewards mode: ${req.query.gvbMode as string}`);
61
}
62
};
63
64
interface IRollGuildVaultBonusRequest {
65
WeekCount: number;
66
}
67
interface IRollGuildVaultBonusResponse {
68
NewRewards: IWeekGuildVaultBonusReward[];
69
BonusRegion: string;
70
}
71
72
// https://wiki.warframe.com/w/Clan_Weekly_Initiatives
73
74
const tierARewards: ITypeCount[] = [
75
// 50 Squad Energy Restore (Large)
76
{ ItemType: "/Lotus/StoreItems/Types/Restoratives/SyndicateTeamEnergyTotem", ItemCount: 50 },
77
78
// 50 Squad Health Restore (Large)
79
{ ItemType: "/Lotus/StoreItems/Types/Restoratives/SyndicateTeamHealTotem", ItemCount: 50 },
80
81
// 12 Neurodes
82
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/Neurode", ItemCount: 12 },
83
84
// 12 Neural Sensors
85
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/NeuralSensor", ItemCount: 12 },
86
87
// 12 Orokin Cell
88
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/OrokinCell", ItemCount: 12 },
89
90
// 1,000 Endo
91
{ ItemType: "/Lotus/StoreItems/Upgrades/Mods/FusionBundles/CircuitRepeatableSteelPathFusionBundle", ItemCount: 1 },
92
93
// 5 Mutagen Mass
94
{ ItemType: "/Lotus/StoreItems/Types/Items/Research/BioComponent", ItemCount: 5 },
95
96
// 5 Detonite Injector
97
{ ItemType: "/Lotus/StoreItems/Types/Items/Research/ChemComponent", ItemCount: 5 },
98
99
// 5 Fieldron
100
{ ItemType: "/Lotus/StoreItems/Types/Items/Research/EnergyComponent", ItemCount: 5 },
101
102
// 3 Aya
103
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/SchismKey", ItemCount: 3 },
104
105
// Ayatan Anasa Sculpture
106
{ ItemType: "/Lotus/StoreItems/Types/Items/FusionTreasures/OroFusexF", ItemCount: 1 }
107
];
108
109
const tierBRewards: ITypeCount[] = [
110
// 50,000 Credits
111
{ ItemType: "/Lotus/StoreItems/Types/PickUps/Credits/10000Credits", ItemCount: 5 },
112
113
// 2,000 Endo
114
{ ItemType: "/Lotus/StoreItems/Upgrades/Mods/FusionBundles/CircuitRepeatableSteelPathFusionBundle", ItemCount: 2 },
115
116
// 10x Cosmic Specter
117
{ ItemType: "/Lotus/StoreItems/Types/Restoratives/Consumable/PlatinumSpectre", ItemCount: 10 },
118
119
// 7,000 Kuva
120
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/Kuva", ItemCount: 7000 },
121
122
// 100 Vosfor
123
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/DistillPoints", ItemCount: 100 },
124
125
// 3 Aya
126
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/SchismKey", ItemCount: 3 },
127
128
// Forma Blueprint
129
{ ItemType: "/Lotus/StoreItems/Types/Recipes/Components/FormaBlueprint", ItemCount: 1 },
130
131
// Veiled Riven Mod (random type)
132
{ ItemType: "/Lotus/StoreItems/Upgrades/Mods/Randomized/RawMeleeRandomMod", ItemCount: 1 },
133
{ ItemType: "/Lotus/StoreItems/Upgrades/Mods/Randomized/RawRifleRandomMod", ItemCount: 1 },
134
{ ItemType: "/Lotus/StoreItems/Upgrades/Mods/Randomized/RawPistolRandomMod", ItemCount: 1 },
135
{ ItemType: "/Lotus/StoreItems/Upgrades/Mods/Randomized/RawModularMeleeRandomMod", ItemCount: 1 },
136
{ ItemType: "/Lotus/StoreItems/Upgrades/Mods/Randomized/RawModularPistolRandomMod", ItemCount: 1 }
137
];
138
139
const tierCRewards: ITypeCount[] = [
140
// 100,000 Credits
141
{ ItemType: "/Lotus/StoreItems/Types/PickUps/Credits/10000Credits", ItemCount: 10 },
142
143
// 3,000 Endo
144
{ ItemType: "/Lotus/StoreItems/Upgrades/Mods/FusionBundles/CircuitRepeatableSteelPathFusionBundle", ItemCount: 3 },
145
146
// 14,000 Kuva
147
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/Kuva", ItemCount: 14000 },
148
149
// 200 Vosfor
150
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/DistillPoints", ItemCount: 200 },
151
152
// 5 Aya
153
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/SchismKey", ItemCount: 5 },
154
155
// Orokin Reactor
156
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/OrokinReactor", ItemCount: 1 },
157
158
// Orokin Catalyst
159
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/OrokinCatalyst", ItemCount: 1 },
160
161
// 2 Relic Packs
162
{ ItemType: "/Lotus/StoreItems/Types/BoosterPacks/LoginRewardRandomProjection", ItemCount: 2 }
163
];
164
165
const tierDRewards: ITypeCount[] = [
166
// 5,000 Endo
167
{ ItemType: "/Lotus/StoreItems/Upgrades/Mods/FusionBundles/CircuitRepeatableSteelPathFusionBundle", ItemCount: 5 },
168
169
// 21,000 Kuva
170
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/Kuva", ItemCount: 21000 },
171
172
// 200 Vosfor
173
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/DistillPoints", ItemCount: 200 },
174
175
// Forma (Built)
176
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/Forma", ItemCount: 1 },
177
178
// Eidolon Lens Blueprint
179
{ ItemType: "/Lotus/StoreItems/Types/Recipes/Lens/GenericLensOstronBlueprint", ItemCount: 1 },
180
181
// Omni Forma (Built)
182
{ ItemType: "/Lotus/StoreItems/Types/Items/MiscItems/FormaAura", ItemCount: 1 }
183
];
@@ -644,6 +644,9 @@ export const getInventoryResponse = async (
644
644
inventoryResponse.Nemesis = undefined;
645
645
}
646
646
647
// On live, this is just empty in inventory response. Seems like the client sends a roll request request even with this given.
648
inventoryResponse.WeeklyGuildVaultBonusInfo = undefined;
649
647
650
// U42 migrated ability paths so translate them back for older versions
648
651
if (version_compare(buildLabel, gameToBuildVersion["42.0.0"]) >= 0) {
649
652
return inventoryResponse;
@@ -100,7 +100,9 @@ import type {
100
100
IParam,
101
101
IDialogueCounter,
102
102
ISketch,
103
IHybridFusionTreasure
103
IHybridFusionTreasure,
104
IWeeklyGuildVaultBonusInfo,
105
IWeekGuildVaultBonusReward
104
106
} from "../../types/inventoryTypes/inventoryTypes.ts";
105
107
import { equipmentKeys } from "../../types/inventoryTypes/inventoryTypes.ts";
106
108
import type { IOid, ITypeCount } from "../../types/commonTypes.ts";
@@ -1575,6 +1577,26 @@ const sketchSchema = new Schema<ISketch>(
1575
1577
{ _id: false }
1576
1578
);
1577
1579
1580
const weekGuildVaultBonusRewardSchema = new Schema<IWeekGuildVaultBonusReward>(
1581
{
1582
RewardClaimed: { type: Boolean, required: true },
1583
PointThreshold: { type: Number, required: true },
1584
ItemCount: { type: Number, required: true },
1585
Reward: { type: String, required: true }
1586
},
1587
{ _id: false }
1588
);
1589
1590
const weeklyGuildVaultBonusInfoSchema = new Schema<IWeeklyGuildVaultBonusInfo>(
1591
{
1592
Progress: { type: Number, required: true },
1593
WeekCount: { type: Number, required: true },
1594
BonusRegion: { type: String, required: true },
1595
Rewards: { type: [weekGuildVaultBonusRewardSchema], required: true }
1596
},
1597
{ _id: false }
1598
);
1599
1578
1600
const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
1579
1601
{
1580
1602
accountOwnerId: Schema.Types.ObjectId,
@@ -2037,7 +2059,9 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
2037
2059
RetroPlayAllConvos: Boolean,
2038
2060
RetroDisableKissInboxMessage: Boolean,
2039
2061
2040
Sketches: { type: [sketchSchema], default: undefined }
2062
Sketches: { type: [sketchSchema], default: undefined },
2063
2064
WeeklyGuildVaultBonusInfo: weeklyGuildVaultBonusInfoSchema
2041
2065
},
2042
2066
{ timestamps: { createdAt: "Created", updatedAt: false } }
2043
2067
);
@@ -93,6 +93,7 @@ import { giveShipDecoAndLoreFragmentController } from "../controllers/api/giveSh
93
93
import { giveStartingGearGetController, giveStartingGearPostController } from "../controllers/api/giveStartingGearController.ts";
94
94
import { goalsController } from "../controllers/api/goalsController.ts";
95
95
import { guildTechController } from "../controllers/api/guildTechController.ts";
96
import { guildVaultBonusRewardsController } from "../controllers/api/guildVaultBonusRewardsController.ts";
96
97
import { hostSessionController } from "../controllers/api/hostSessionController.ts";
97
98
import { hubBlessingController } from "../controllers/api/hubBlessingController.ts";
98
99
import { inboxController } from "../controllers/api/inboxController.ts";
@@ -345,6 +346,7 @@ apiRouter.post("/giveShipDecoAndLoreFragment.php", giveShipDecoAndLoreFragmentCo
345
346
apiRouter.post("/giveStartingGear.php", giveStartingGearPostController);
346
347
apiRouter.post("/goals.php", goalsController);
347
348
apiRouter.post("/guildTech.php", guildTechController);
349
apiRouter.post("/guildVaultBonusRewards.php", guildVaultBonusRewardsController); // U42+
348
350
apiRouter.post("/hostSession.php", hostSessionController);
349
351
apiRouter.post("/hubBlessing.php", hubBlessingController);
350
352
apiRouter.post("/inbox.php", inboxController); // from ~U15, don't know when they changed it to GET
@@ -596,6 +596,9 @@ export const importInventory = (db: TInventoryDatabaseDocument, client: Partial<
596
596
if (client.Sketches !== undefined) {
597
597
db.Sketches = client.Sketches;
598
598
}
599
if (typeof client.WeeklyGuildVaultBonusInfo == "object") {
600
db.WeeklyGuildVaultBonusInfo = client.WeeklyGuildVaultBonusInfo;
601
}
599
602
600
603
// Final sanity check over data
601
604
for (const pr of db.PendingRecipes) {
@@ -561,6 +561,7 @@ export interface IInventoryClient
561
561
RetroPlayAllConvos?: boolean;
562
562
RetroDisableKissInboxMessage?: boolean;
563
563
Sketches?: ISketch[];
564
WeeklyGuildVaultBonusInfo?: IWeeklyGuildVaultBonusInfo;
564
565
}
565
566
566
567
export interface IAffiliation {
@@ -1409,3 +1410,17 @@ export interface ISketch {
1409
1410
decoId: TSketches;
1410
1411
canvas?: string;
1411
1412
}
1413
1414
export interface IWeeklyGuildVaultBonusInfo {
1415
Progress: number;
1416
WeekCount: number;
1417
BonusRegion: string;
1418
Rewards: IWeekGuildVaultBonusReward[];
1419
}
1420
1421
export interface IWeekGuildVaultBonusReward {
1422
RewardClaimed: boolean;
1423
PointThreshold: number;
1424
ItemCount: number;
1425
Reward: string;
1426
}