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: stripped rewards (#1123)

Closes #683 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1123

1c276ce1
Sainan <sainan@calamity.inc>
提交于

代码差异

9 个文件 +56 -17
Modified package-lock.json +4 -4
@@ -12,7 +12,7 @@
12 12 "copyfiles": "^2.4.1",
13 13 "express": "^5",
14 14 "mongoose": "^8.11.0",
15 "warframe-public-export-plus": "^0.5.41",
15 "warframe-public-export-plus": "^0.5.42",
16 16 "warframe-riven-info": "^0.1.2",
17 17 "winston": "^3.17.0",
18 18 "winston-daily-rotate-file": "^5.0.0"
@@ -4083,9 +4083,9 @@
4083 4083 }
4084 4084 },
4085 4085 "node_modules/warframe-public-export-plus": {
4086 "version": "0.5.41",
4087 "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.41.tgz",
4088 "integrity": "sha512-qVOUY4UjF1cyBrBbMwD25xHSdSf9q57/CJgjHsfSE7NUu/6pBDSZzwS0iAetAukws/1V2kDvsuy8AGtOec2L1w=="
4086 "version": "0.5.42",
4087 "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.42.tgz",
4088 "integrity": "sha512-up3P5bLKD42Xkr3o7TX9WUwvpJzK88aQTLZ2bB6QWUHdsJxl/Z3TBn+HSd3eouIDTMVUzbTDeDPosSw7TcLegA=="
4089 4089 },
4090 4090 "node_modules/warframe-riven-info": {
4091 4091 "version": "0.1.2",
Modified package.json +1 -1
@@ -21,7 +21,7 @@
21 21 "mongoose": "^8.11.0",
22 22 "morgan": "^1.10.0",
23 23 "typescript": ">=4.7.4 <5.6.0",
24 "warframe-public-export-plus": "^0.5.41",
24 "warframe-public-export-plus": "^0.5.42",
25 25 "warframe-riven-info": "^0.1.2",
26 26 "winston": "^3.17.0",
27 27 "winston-daily-rotate-file": "^5.0.0"
Modified src/controllers/api/dronesController.ts +2 -1
@@ -1,6 +1,7 @@
1 1 import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
2 2 import { config } from "@/src/services/configService";
3 3 import { addMiscItems, getInventory } from "@/src/services/inventoryService";
4 import { fromStoreItem } from "@/src/services/itemDataService";
4 5 import { getAccountIdForRequest } from "@/src/services/loginService";
5 6 import { getRandomInt, getRandomWeightedRewardUc } from "@/src/services/rngService";
6 7 import { IMongoDate, IOid } from "@/src/types/commonTypes";
@@ -58,7 +59,7 @@ export const dronesController: RequestHandler = async (req, res) => {
58 59 : 0;
59 60 const resource = getRandomWeightedRewardUc(system.resources, droneMeta.probabilities)!;
60 61 //logger.debug(`drone rolled`, resource);
61 drone.ResourceType = "/Lotus/" + resource.StoreItem.substring(18);
62 drone.ResourceType = fromStoreItem(resource.StoreItem);
62 63 const resourceMeta = ExportResources[drone.ResourceType];
63 64 if (resourceMeta.pickupQuantity) {
64 65 const pickupsToCollect = droneMeta.binCapacity * droneMeta.capacityMultipliers[resource.Rarity];
Modified src/services/inventoryService.ts +2 -2
@@ -35,7 +35,7 @@ import {
35 35 IUpdateChallengeProgressRequest
36 36 } from "../types/requestTypes";
37 37 import { logger } from "@/src/utils/logger";
38 import { convertInboxMessage, getExalted, getKeyChainItems } from "@/src/services/itemDataService";
38 import { convertInboxMessage, fromStoreItem, getExalted, getKeyChainItems } from "@/src/services/itemDataService";
39 39 import {
40 40 EquipmentFeatures,
41 41 IEquipmentClient,
@@ -1260,7 +1260,7 @@ export const addKeyChainItems = async (
1260 1260 `adding key chain items ${keyChainItems.join()} for ${keyChainData.KeyChain} at stage ${keyChainData.ChainStage}`
1261 1261 );
1262 1262
1263 const nonStoreItems = keyChainItems.map(item => item.replace("StoreItems/", ""));
1263 const nonStoreItems = keyChainItems.map(item => fromStoreItem(item));
1264 1264
1265 1265 //TODO: inventoryChanges is not typed correctly
1266 1266 const inventoryChanges = {};
Modified src/services/itemDataService.ts +8 -0
@@ -244,3 +244,11 @@ export const convertInboxMessage = (message: IInboxMessage): IMessage => {
244 244 r: false
245 245 } satisfies IMessage;
246 246 };
247
248 export const toStoreItem = (type: string): string => {
249 return "/Lotus/StoreItems/" + type.substring("/Lotus/".length);
250 };
251
252 export const fromStoreItem = (type: string): string => {
253 return "/Lotus/" + type.substring("/Lotus/StoreItems/".length);
254 };
Modified src/services/missionInventoryUpdateService.ts +28 -2
@@ -1,4 +1,5 @@
1 1 import {
2 ExportEnemies,
2 3 ExportFusionBundles,
3 4 ExportRegions,
4 5 ExportRewards,
@@ -18,6 +19,7 @@ import {
18 19 addFocusXpIncreases,
19 20 addFusionTreasures,
20 21 addGearExpByCategory,
22 addItem,
21 23 addMiscItems,
22 24 addMissionComplete,
23 25 addMods,
@@ -28,7 +30,7 @@ import {
28 30 import { updateQuestKey } from "@/src/services/questService";
29 31 import { HydratedDocument } from "mongoose";
30 32 import { IInventoryChanges } from "@/src/types/purchaseTypes";
31 import { getLevelKeyRewards, getNode } from "@/src/services/itemDataService";
33 import { getLevelKeyRewards, getNode, toStoreItem } from "@/src/services/itemDataService";
32 34 import { InventoryDocumentProps, TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
33 35 import { getEntriesUnsafe } from "@/src/utils/ts-utils";
34 36 import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
@@ -319,7 +321,8 @@ export const addMissionRewards = async (
319 321 LevelKeyName: levelKeyName,
320 322 Missions: missions,
321 323 RegularCredits: creditDrops,
322 VoidTearParticipantsCurrWave: voidTearWave
324 VoidTearParticipantsCurrWave: voidTearWave,
325 StrippedItems: strippedItems
323 326 }: IMissionInventoryUpdateRequest
324 327 ) => {
325 328 if (!rewardInfo) {
@@ -406,6 +409,29 @@ export const addMissionRewards = async (
406 409 MissionRewards.push({ StoreItem: reward.type, ItemCount: reward.itemCount });
407 410 }
408 411
412 if (strippedItems) {
413 for (const si of strippedItems) {
414 const droptable = ExportEnemies.droptables[si.DropTable];
415 // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
416 if (!droptable) {
417 logger.error(`unknown droptable ${si.DropTable}`);
418 } else {
419 for (let i = 0; i != si.DROP_MOD.length; ++i) {
420 for (const pool of droptable) {
421 const reward = getRandomReward(pool.items)!;
422 logger.debug(`stripped droptable rolled`, reward);
423 await addItem(inventory, reward.type);
424 MissionRewards.push({
425 StoreItem: toStoreItem(reward.type),
426 ItemCount: 1,
427 FromEnemyCache: true // to show "identified"
428 });
429 }
430 }
431 }
432 }
433 }
434
409 435 return { inventoryChanges, MissionRewards, credits };
410 436 };
411 437
Modified src/services/purchaseService.ts +3 -3
@@ -27,6 +27,7 @@ import {
27 27 } from "warframe-public-export-plus";
28 28 import { config } from "./configService";
29 29 import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel";
30 import { fromStoreItem, toStoreItem } from "./itemDataService";
30 31
31 32 export const getStoreItemCategory = (storeItem: string): string => {
32 33 const storeItemString = getSubstringFromKeyword(storeItem, "StoreItems/");
@@ -240,7 +241,7 @@ export const handleStoreItemAcquisition = async (
240 241 await handleBundleAcqusition(storeItemName, inventory, quantity, purchaseResponse.InventoryChanges);
241 242 } else {
242 243 const storeCategory = getStoreItemCategory(storeItemName);
243 const internalName = storeItemName.replace("/StoreItems", "");
244 const internalName = fromStoreItem(storeItemName);
244 245 logger.debug(`store category ${storeCategory}`);
245 246 if (!ignorePurchaseQuantity) {
246 247 if (internalName in ExportGear) {
@@ -328,8 +329,7 @@ const handleBoosterPackPurchase = async (
328 329 const result = getRandomWeightedRewardUc(pack.components, weights);
329 330 if (result) {
330 331 logger.debug(`booster pack rolled`, result);
331 purchaseResponse.BoosterPackItems +=
332 result.Item.split("/Lotus/").join("/Lotus/StoreItems/") + ',{"lvl":0};';
332 purchaseResponse.BoosterPackItems += toStoreItem(result.Item) + ',{"lvl":0};';
333 333 combineInventoryChanges(
334 334 purchaseResponse.InventoryChanges,
335 335 (await addItem(inventory, result.Item, 1)).InventoryChanges
Modified src/services/questService.ts +4 -4
@@ -3,7 +3,7 @@ import { isEmptyObject } from "@/src/helpers/general";
3 3 import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
4 4 import { createMessage } from "@/src/services/inboxService";
5 5 import { addItem, addKeyChainItems } from "@/src/services/inventoryService";
6 import { getKeyChainMessage, getLevelKeyRewards } from "@/src/services/itemDataService";
6 import { fromStoreItem, getKeyChainMessage, getLevelKeyRewards } from "@/src/services/itemDataService";
7 7 import {
8 8 IInventoryDatabase,
9 9 IQuestKeyClient,
@@ -157,7 +157,7 @@ export const completeQuest = async (inventory: TInventoryDatabaseDocument, quest
157 157 addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, inventory, missionRewards);
158 158
159 159 for (const reward of missionRewards) {
160 await addItem(inventory, reward.StoreItem.replace("StoreItems/", ""), reward.ItemCount);
160 await addItem(inventory, fromStoreItem(reward.StoreItem), reward.ItemCount);
161 161 }
162 162 } else if (fixedLevelRewards.levelKeyRewards2) {
163 163 for (const reward of fixedLevelRewards.levelKeyRewards2) {
@@ -166,9 +166,9 @@ export const completeQuest = async (inventory: TInventoryDatabaseDocument, quest
166 166 continue;
167 167 }
168 168 if (reward.rewardType == "RT_RESOURCE") {
169 await addItem(inventory, reward.itemType.replace("StoreItems/", ""), reward.amount);
169 await addItem(inventory, fromStoreItem(reward.itemType), reward.amount);
170 170 } else {
171 await addItem(inventory, reward.itemType.replace("StoreItems/", ""));
171 await addItem(inventory, fromStoreItem(reward.itemType));
172 172 }
173 173 }
174 174 }
Modified src/types/requestTypes.ts +4 -0
@@ -103,6 +103,10 @@ export type IMissionInventoryUpdateRequest = {
103 103 }[];
104 104 CollectibleScans?: ICollectibleEntry[];
105 105 Upgrades?: IUpgradeClient[]; // riven challenge progress
106 StrippedItems?: {
107 DropTable: string;
108 DROP_MOD: number[];
109 }[];
106 110 } & {
107 111 [K in TEquipmentKey]?: IEquipmentClient[];
108 112 };