diff --git a/package-lock.json b/package-lock.json index 492c6357..7db27a72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "copyfiles": "^2.4.1", "express": "^5", "mongoose": "^8.9.4", - "warframe-public-export-plus": "^0.5.23", + "warframe-public-export-plus": "^0.5.24", "warframe-riven-info": "^0.1.2", "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0" @@ -3778,9 +3778,9 @@ } }, "node_modules/warframe-public-export-plus": { - "version": "0.5.23", - "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.23.tgz", - "integrity": "sha512-AJLivzXpon+UDm+SYq3wIXiP4OXCDOgXvCG1VLawJrHW3VDff+NpsUJApBPA4S8oZ8N8NPyBVKBvuoF2Pplaeg==" + "version": "0.5.24", + "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.24.tgz", + "integrity": "sha512-GHjOxFcfPaLbhs/1Adgk6y3qPJ7ptBO/sW2oQ4aSdDj68oETkDjHwDQrn4eFjaYKGOmVwAzVDPMgLKWaD/fmKg==" }, "node_modules/warframe-riven-info": { "version": "0.1.2", diff --git a/package.json b/package.json index f0408d92..b9b1aef3 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "copyfiles": "^2.4.1", "express": "^5", "mongoose": "^8.9.4", - "warframe-public-export-plus": "^0.5.23", + "warframe-public-export-plus": "^0.5.24", "warframe-riven-info": "^0.1.2", "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0" diff --git a/src/controllers/api/rerollRandomModController.ts b/src/controllers/api/rerollRandomModController.ts index 0a3bff22..42fdf337 100644 --- a/src/controllers/api/rerollRandomModController.ts +++ b/src/controllers/api/rerollRandomModController.ts @@ -1,9 +1,102 @@ -import { logger } from "@/src/utils/logger"; import { RequestHandler } from "express"; +import { getAccountIdForRequest } from "@/src/services/loginService"; +import { addMiscItems, getInventory } from "@/src/services/inventoryService"; +import { getJSONfromString } from "@/src/helpers/stringHelpers"; +import { ExportUpgrades } from "warframe-public-export-plus"; +import { getRandomElement } from "@/src/services/rngService"; -const rerollRandomModController: RequestHandler = (_req, res) => { - logger.debug("RerollRandomMod Request", { info: _req.body.toString("hex").replace(/(.)(.)/g, "$1$2 ") }); - res.json({}); +export const rerollRandomModController: RequestHandler = async (req, res) => { + const accountId = await getAccountIdForRequest(req); + const request = getJSONfromString(String(req.body)) as RerollRandomModRequest; + if ("ItemIds" in request) { + const inventory = await getInventory(accountId, "Upgrades MiscItems"); + const upgrade = inventory.Upgrades.id(request.ItemIds[0])!; + const fingerprint = JSON.parse(upgrade.UpgradeFingerprint!) as IUnveiledRivenFingerprint; + + fingerprint.rerolls ??= 0; + const kuvaCost = fingerprint.rerolls < rerollCosts.length ? rerollCosts[fingerprint.rerolls] : 3500; + addMiscItems(inventory, [ + { + ItemType: "/Lotus/Types/Items/MiscItems/Kuva", + ItemCount: kuvaCost * -1 + } + ]); + + fingerprint.rerolls++; + upgrade.UpgradeFingerprint = JSON.stringify(fingerprint); + + randomiseStats(upgrade.ItemType, fingerprint); + upgrade.PendingRerollFingerprint = JSON.stringify(fingerprint); + + await inventory.save(); + + res.json({ + changes: [ + { + ItemId: { $oid: request.ItemIds[0] }, + UpgradeFingerprint: upgrade.UpgradeFingerprint, + PendingRerollFingerprint: upgrade.PendingRerollFingerprint + } + ], + cost: kuvaCost + }); + } else { + const inventory = await getInventory(accountId, "Upgrades"); + const upgrade = inventory.Upgrades.id(request.ItemId)!; + if (request.CommitReroll && upgrade.PendingRerollFingerprint) { + upgrade.UpgradeFingerprint = upgrade.PendingRerollFingerprint; + } + upgrade.PendingRerollFingerprint = undefined; + await inventory.save(); + res.send(upgrade.UpgradeFingerprint); + } }; -export { rerollRandomModController }; +const randomiseStats = (randomModType: string, fingerprint: IUnveiledRivenFingerprint): void => { + const meta = ExportUpgrades[randomModType]; + + fingerprint.buffs = []; + const numBuffs = 2 + Math.trunc(Math.random() * 2); // 2 or 3 + const buffEntries = meta.upgradeEntries!.filter(x => x.canBeBuff); + for (let i = 0; i != numBuffs; ++i) { + const buffIndex = Math.trunc(Math.random() * buffEntries.length); + const entry = buffEntries[buffIndex]; + fingerprint.buffs.push({ Tag: entry.tag, Value: Math.trunc(Math.random() * 0x40000000) }); + buffEntries.splice(buffIndex, 1); + } + + fingerprint.curses = []; + if (Math.random() < 0.5) { + const entry = getRandomElement(meta.upgradeEntries!.filter(x => x.canBeCurse)); + fingerprint.curses.push({ Tag: entry.tag, Value: Math.trunc(Math.random() * 0x40000000) }); + } +}; + +type RerollRandomModRequest = LetsGoGamblingRequest | AwDangitRequest; + +interface LetsGoGamblingRequest { + ItemIds: string[]; +} + +interface AwDangitRequest { + ItemId: string; + CommitReroll: boolean; +} + +interface IUnveiledRivenFingerprint { + compat: string; + lim: number; + lvl: number; + lvlReq: 0; + rerolls?: number; + pol: string; + buffs: IRivenStat[]; + curses: IRivenStat[]; +} + +interface IRivenStat { + Tag: string; + Value: number; +} + +const rerollCosts = [900, 1000, 1200, 1400, 1700, 2000, 2350, 2750, 3150]; diff --git a/src/models/inventoryModels/inventoryModel.ts b/src/models/inventoryModels/inventoryModel.ts index 82fefab4..d3b6b33b 100644 --- a/src/models/inventoryModels/inventoryModel.ts +++ b/src/models/inventoryModels/inventoryModel.ts @@ -288,10 +288,10 @@ RawUpgrades.set("toJSON", { } }); -//TODO: find out what this is -const upgradesSchema = new Schema( +const upgradesSchema = new Schema( { UpgradeFingerprint: String, + PendingRerollFingerprint: { type: String, required: false }, ItemType: String }, { id: false } diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index e7567772..c58a17df 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -96,8 +96,11 @@ export const combineInventoryChanges = (InventoryChanges: IInventoryChanges, del } }; -export const getInventory = async (accountOwnerId: string): Promise => { - const inventory = await Inventory.findOne({ accountOwnerId: accountOwnerId }); +export const getInventory = async ( + accountOwnerId: string, + projection: string | undefined = undefined +): Promise => { + const inventory = await Inventory.findOne({ accountOwnerId: accountOwnerId }, projection); if (!inventory) { throw new Error(`Didn't find an inventory for ${accountOwnerId}`); diff --git a/src/types/inventoryTypes/inventoryTypes.ts b/src/types/inventoryTypes/inventoryTypes.ts index 23d06673..d0b0f06a 100644 --- a/src/types/inventoryTypes/inventoryTypes.ts +++ b/src/types/inventoryTypes/inventoryTypes.ts @@ -420,6 +420,7 @@ export interface ISlots { export interface ICrewShipSalvagedWeaponSkin { ItemType: string; UpgradeFingerprint?: string; + PendingRerollFingerprint?: string; ItemId?: IOid; _id?: Types.ObjectId; }