feat: stripped rewards (#1123)
Some checks are pending
Build / build (18) (push) Waiting to run
Build / build (22) (push) Waiting to run
Build Docker image / docker (push) Waiting to run
Build / build (20) (push) Waiting to run

Closes #683

Reviewed-on: #1123
This commit is contained in:
Sainan 2025-03-09 07:42:55 -07:00
parent 6b35408144
commit 1c276ce133
9 changed files with 56 additions and 17 deletions

8
package-lock.json generated
View File

@ -12,7 +12,7 @@
"copyfiles": "^2.4.1", "copyfiles": "^2.4.1",
"express": "^5", "express": "^5",
"mongoose": "^8.11.0", "mongoose": "^8.11.0",
"warframe-public-export-plus": "^0.5.41", "warframe-public-export-plus": "^0.5.42",
"warframe-riven-info": "^0.1.2", "warframe-riven-info": "^0.1.2",
"winston": "^3.17.0", "winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0" "winston-daily-rotate-file": "^5.0.0"
@ -4083,9 +4083,9 @@
} }
}, },
"node_modules/warframe-public-export-plus": { "node_modules/warframe-public-export-plus": {
"version": "0.5.41", "version": "0.5.42",
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.41.tgz", "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.42.tgz",
"integrity": "sha512-qVOUY4UjF1cyBrBbMwD25xHSdSf9q57/CJgjHsfSE7NUu/6pBDSZzwS0iAetAukws/1V2kDvsuy8AGtOec2L1w==" "integrity": "sha512-up3P5bLKD42Xkr3o7TX9WUwvpJzK88aQTLZ2bB6QWUHdsJxl/Z3TBn+HSd3eouIDTMVUzbTDeDPosSw7TcLegA=="
}, },
"node_modules/warframe-riven-info": { "node_modules/warframe-riven-info": {
"version": "0.1.2", "version": "0.1.2",

View File

@ -21,7 +21,7 @@
"mongoose": "^8.11.0", "mongoose": "^8.11.0",
"morgan": "^1.10.0", "morgan": "^1.10.0",
"typescript": ">=4.7.4 <5.6.0", "typescript": ">=4.7.4 <5.6.0",
"warframe-public-export-plus": "^0.5.41", "warframe-public-export-plus": "^0.5.42",
"warframe-riven-info": "^0.1.2", "warframe-riven-info": "^0.1.2",
"winston": "^3.17.0", "winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0" "winston-daily-rotate-file": "^5.0.0"

View File

@ -1,6 +1,7 @@
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers"; import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
import { config } from "@/src/services/configService"; import { config } from "@/src/services/configService";
import { addMiscItems, getInventory } from "@/src/services/inventoryService"; import { addMiscItems, getInventory } from "@/src/services/inventoryService";
import { fromStoreItem } from "@/src/services/itemDataService";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { getRandomInt, getRandomWeightedRewardUc } from "@/src/services/rngService"; import { getRandomInt, getRandomWeightedRewardUc } from "@/src/services/rngService";
import { IMongoDate, IOid } from "@/src/types/commonTypes"; import { IMongoDate, IOid } from "@/src/types/commonTypes";
@ -58,7 +59,7 @@ export const dronesController: RequestHandler = async (req, res) => {
: 0; : 0;
const resource = getRandomWeightedRewardUc(system.resources, droneMeta.probabilities)!; const resource = getRandomWeightedRewardUc(system.resources, droneMeta.probabilities)!;
//logger.debug(`drone rolled`, resource); //logger.debug(`drone rolled`, resource);
drone.ResourceType = "/Lotus/" + resource.StoreItem.substring(18); drone.ResourceType = fromStoreItem(resource.StoreItem);
const resourceMeta = ExportResources[drone.ResourceType]; const resourceMeta = ExportResources[drone.ResourceType];
if (resourceMeta.pickupQuantity) { if (resourceMeta.pickupQuantity) {
const pickupsToCollect = droneMeta.binCapacity * droneMeta.capacityMultipliers[resource.Rarity]; const pickupsToCollect = droneMeta.binCapacity * droneMeta.capacityMultipliers[resource.Rarity];

View File

@ -35,7 +35,7 @@ import {
IUpdateChallengeProgressRequest IUpdateChallengeProgressRequest
} from "../types/requestTypes"; } from "../types/requestTypes";
import { logger } from "@/src/utils/logger"; import { logger } from "@/src/utils/logger";
import { convertInboxMessage, getExalted, getKeyChainItems } from "@/src/services/itemDataService"; import { convertInboxMessage, fromStoreItem, getExalted, getKeyChainItems } from "@/src/services/itemDataService";
import { import {
EquipmentFeatures, EquipmentFeatures,
IEquipmentClient, IEquipmentClient,
@ -1260,7 +1260,7 @@ export const addKeyChainItems = async (
`adding key chain items ${keyChainItems.join()} for ${keyChainData.KeyChain} at stage ${keyChainData.ChainStage}` `adding key chain items ${keyChainItems.join()} for ${keyChainData.KeyChain} at stage ${keyChainData.ChainStage}`
); );
const nonStoreItems = keyChainItems.map(item => item.replace("StoreItems/", "")); const nonStoreItems = keyChainItems.map(item => fromStoreItem(item));
//TODO: inventoryChanges is not typed correctly //TODO: inventoryChanges is not typed correctly
const inventoryChanges = {}; const inventoryChanges = {};

View File

@ -244,3 +244,11 @@ export const convertInboxMessage = (message: IInboxMessage): IMessage => {
r: false r: false
} satisfies IMessage; } satisfies IMessage;
}; };
export const toStoreItem = (type: string): string => {
return "/Lotus/StoreItems/" + type.substring("/Lotus/".length);
};
export const fromStoreItem = (type: string): string => {
return "/Lotus/" + type.substring("/Lotus/StoreItems/".length);
};

View File

@ -1,4 +1,5 @@
import { import {
ExportEnemies,
ExportFusionBundles, ExportFusionBundles,
ExportRegions, ExportRegions,
ExportRewards, ExportRewards,
@ -18,6 +19,7 @@ import {
addFocusXpIncreases, addFocusXpIncreases,
addFusionTreasures, addFusionTreasures,
addGearExpByCategory, addGearExpByCategory,
addItem,
addMiscItems, addMiscItems,
addMissionComplete, addMissionComplete,
addMods, addMods,
@ -28,7 +30,7 @@ import {
import { updateQuestKey } from "@/src/services/questService"; import { updateQuestKey } from "@/src/services/questService";
import { HydratedDocument } from "mongoose"; import { HydratedDocument } from "mongoose";
import { IInventoryChanges } from "@/src/types/purchaseTypes"; import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { getLevelKeyRewards, getNode } from "@/src/services/itemDataService"; import { getLevelKeyRewards, getNode, toStoreItem } from "@/src/services/itemDataService";
import { InventoryDocumentProps, TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel"; import { InventoryDocumentProps, TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
import { getEntriesUnsafe } from "@/src/utils/ts-utils"; import { getEntriesUnsafe } from "@/src/utils/ts-utils";
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes"; import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
@ -319,7 +321,8 @@ export const addMissionRewards = async (
LevelKeyName: levelKeyName, LevelKeyName: levelKeyName,
Missions: missions, Missions: missions,
RegularCredits: creditDrops, RegularCredits: creditDrops,
VoidTearParticipantsCurrWave: voidTearWave VoidTearParticipantsCurrWave: voidTearWave,
StrippedItems: strippedItems
}: IMissionInventoryUpdateRequest }: IMissionInventoryUpdateRequest
) => { ) => {
if (!rewardInfo) { if (!rewardInfo) {
@ -406,6 +409,29 @@ export const addMissionRewards = async (
MissionRewards.push({ StoreItem: reward.type, ItemCount: reward.itemCount }); MissionRewards.push({ StoreItem: reward.type, ItemCount: reward.itemCount });
} }
if (strippedItems) {
for (const si of strippedItems) {
const droptable = ExportEnemies.droptables[si.DropTable];
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!droptable) {
logger.error(`unknown droptable ${si.DropTable}`);
} else {
for (let i = 0; i != si.DROP_MOD.length; ++i) {
for (const pool of droptable) {
const reward = getRandomReward(pool.items)!;
logger.debug(`stripped droptable rolled`, reward);
await addItem(inventory, reward.type);
MissionRewards.push({
StoreItem: toStoreItem(reward.type),
ItemCount: 1,
FromEnemyCache: true // to show "identified"
});
}
}
}
}
}
return { inventoryChanges, MissionRewards, credits }; return { inventoryChanges, MissionRewards, credits };
}; };

View File

@ -27,6 +27,7 @@ import {
} from "warframe-public-export-plus"; } from "warframe-public-export-plus";
import { config } from "./configService"; import { config } from "./configService";
import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel"; import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel";
import { fromStoreItem, toStoreItem } from "./itemDataService";
export const getStoreItemCategory = (storeItem: string): string => { export const getStoreItemCategory = (storeItem: string): string => {
const storeItemString = getSubstringFromKeyword(storeItem, "StoreItems/"); const storeItemString = getSubstringFromKeyword(storeItem, "StoreItems/");
@ -240,7 +241,7 @@ export const handleStoreItemAcquisition = async (
await handleBundleAcqusition(storeItemName, inventory, quantity, purchaseResponse.InventoryChanges); await handleBundleAcqusition(storeItemName, inventory, quantity, purchaseResponse.InventoryChanges);
} else { } else {
const storeCategory = getStoreItemCategory(storeItemName); const storeCategory = getStoreItemCategory(storeItemName);
const internalName = storeItemName.replace("/StoreItems", ""); const internalName = fromStoreItem(storeItemName);
logger.debug(`store category ${storeCategory}`); logger.debug(`store category ${storeCategory}`);
if (!ignorePurchaseQuantity) { if (!ignorePurchaseQuantity) {
if (internalName in ExportGear) { if (internalName in ExportGear) {
@ -328,8 +329,7 @@ const handleBoosterPackPurchase = async (
const result = getRandomWeightedRewardUc(pack.components, weights); const result = getRandomWeightedRewardUc(pack.components, weights);
if (result) { if (result) {
logger.debug(`booster pack rolled`, result); logger.debug(`booster pack rolled`, result);
purchaseResponse.BoosterPackItems += purchaseResponse.BoosterPackItems += toStoreItem(result.Item) + ',{"lvl":0};';
result.Item.split("/Lotus/").join("/Lotus/StoreItems/") + ',{"lvl":0};';
combineInventoryChanges( combineInventoryChanges(
purchaseResponse.InventoryChanges, purchaseResponse.InventoryChanges,
(await addItem(inventory, result.Item, 1)).InventoryChanges (await addItem(inventory, result.Item, 1)).InventoryChanges

View File

@ -3,7 +3,7 @@ import { isEmptyObject } from "@/src/helpers/general";
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel"; import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
import { createMessage } from "@/src/services/inboxService"; import { createMessage } from "@/src/services/inboxService";
import { addItem, addKeyChainItems } from "@/src/services/inventoryService"; import { addItem, addKeyChainItems } from "@/src/services/inventoryService";
import { getKeyChainMessage, getLevelKeyRewards } from "@/src/services/itemDataService"; import { fromStoreItem, getKeyChainMessage, getLevelKeyRewards } from "@/src/services/itemDataService";
import { import {
IInventoryDatabase, IInventoryDatabase,
IQuestKeyClient, IQuestKeyClient,
@ -157,7 +157,7 @@ export const completeQuest = async (inventory: TInventoryDatabaseDocument, quest
addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, inventory, missionRewards); addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, inventory, missionRewards);
for (const reward of missionRewards) { for (const reward of missionRewards) {
await addItem(inventory, reward.StoreItem.replace("StoreItems/", ""), reward.ItemCount); await addItem(inventory, fromStoreItem(reward.StoreItem), reward.ItemCount);
} }
} else if (fixedLevelRewards.levelKeyRewards2) { } else if (fixedLevelRewards.levelKeyRewards2) {
for (const reward of fixedLevelRewards.levelKeyRewards2) { for (const reward of fixedLevelRewards.levelKeyRewards2) {
@ -166,9 +166,9 @@ export const completeQuest = async (inventory: TInventoryDatabaseDocument, quest
continue; continue;
} }
if (reward.rewardType == "RT_RESOURCE") { if (reward.rewardType == "RT_RESOURCE") {
await addItem(inventory, reward.itemType.replace("StoreItems/", ""), reward.amount); await addItem(inventory, fromStoreItem(reward.itemType), reward.amount);
} else { } else {
await addItem(inventory, reward.itemType.replace("StoreItems/", "")); await addItem(inventory, fromStoreItem(reward.itemType));
} }
} }
} }

View File

@ -103,6 +103,10 @@ export type IMissionInventoryUpdateRequest = {
}[]; }[];
CollectibleScans?: ICollectibleEntry[]; CollectibleScans?: ICollectibleEntry[];
Upgrades?: IUpgradeClient[]; // riven challenge progress Upgrades?: IUpgradeClient[]; // riven challenge progress
StrippedItems?: {
DropTable: string;
DROP_MOD: number[];
}[];
} & { } & {
[K in TEquipmentKey]?: IEquipmentClient[]; [K in TEquipmentKey]?: IEquipmentClient[];
}; };