XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 0 Star 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
Sainan <63328889+Sainan@users.noreply.github.com>
提交于

代码差异

6 个文件 +232 -2
Added src/controllers/api/guildVaultBonusRewardsController.ts +183 -0
@@ -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 ];
Modified src/controllers/api/inventoryController.ts +3 -0
@@ -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;
Modified src/models/inventoryModels/inventoryModel.ts +26 -2
@@ -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 );
Modified src/routes/api.ts +2 -0
@@ -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
Modified src/services/importService.ts +3 -0
@@ -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) {
Modified src/types/inventoryTypes/inventoryTypes.ts +15 -0
@@ -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 }