diff --git a/src/services/serversideVendorsService.ts b/src/services/serversideVendorsService.ts index 0282c562..4ad670d2 100644 --- a/src/services/serversideVendorsService.ts +++ b/src/services/serversideVendorsService.ts @@ -6,7 +6,7 @@ import { mixSeeds, SRng } from "@/src/services/rngService"; import { IMongoDate } from "@/src/types/commonTypes"; import { IItemManifest, IVendorInfo, IVendorManifest } from "@/src/types/vendorTypes"; import { logger } from "@/src/utils/logger"; -import { ExportVendors, IRange, IVendor } from "warframe-public-export-plus"; +import { ExportVendors, IRange, IVendor, IVendorOffer } from "warframe-public-export-plus"; import ArchimedeanVendorManifest from "@/static/fixed_responses/getVendorInfo/ArchimedeanVendorManifest.json"; import DeimosEntratiFragmentVendorProductsManifest from "@/static/fixed_responses/getVendorInfo/DeimosEntratiFragmentVendorProductsManifest.json"; @@ -21,7 +21,6 @@ import DeimosProspectorVendorManifest from "@/static/fixed_responses/getVendorIn import DuviriAcrithisVendorManifest from "@/static/fixed_responses/getVendorInfo/DuviriAcrithisVendorManifest.json"; import EntratiLabsEntratiLabsCommisionsManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabsCommisionsManifest.json"; import EntratiLabsEntratiLabVendorManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabVendorManifest.json"; -import HubsIronwakeDondaVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsIronwakeDondaVendorManifest.json"; import HubsRailjackCrewMemberVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsRailjackCrewMemberVendorManifest.json"; import MaskSalesmanManifest from "@/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json"; import Nova1999ConquestShopManifest from "@/static/fixed_responses/getVendorInfo/Nova1999ConquestShopManifest.json"; @@ -47,7 +46,6 @@ const rawVendorManifests: IVendorManifest[] = [ DuviriAcrithisVendorManifest, EntratiLabsEntratiLabsCommisionsManifest, EntratiLabsEntratiLabVendorManifest, - HubsIronwakeDondaVendorManifest, // uses preprocessing HubsRailjackCrewMemberVendorManifest, MaskSalesmanManifest, Nova1999ConquestShopManifest, @@ -83,10 +81,6 @@ const generatableVendors: IGeneratableVendorInfo[] = [ cycleOffset: 1744934400_000, cycleDuration: 4 * unixTimesInMs.day } - // { - // _id: { $oid: "5dbb4c41e966f7886c3ce939" }, - // TypeName: "/Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest" - // } ]; const getVendorOid = (typeName: string): string => { @@ -261,13 +255,8 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani const cycleIndex = Math.trunc((Date.now() - cycleOffset) / cycleDuration); const rng = new SRng(mixSeeds(vendorSeed, cycleIndex)); const manifest = ExportVendors[vendorInfo.TypeName]; - const offersToAdd = []; - if ( - manifest.numItems && - (manifest.numItems.minValue != manifest.numItems.maxValue || - manifest.items.length != manifest.numItems.minValue) && - !manifest.isOneBinPerCycle - ) { + const offersToAdd: IVendorOffer[] = []; + if (!manifest.isOneBinPerCycle) { const remainingItemCapacity: Record = {}; for (const item of manifest.items) { remainingItemCapacity[item.storeItem] = 1 + item.duplicates; @@ -275,31 +264,48 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani for (const offer of info.ItemManifest) { remainingItemCapacity[offer.StoreItem] -= 1; } - const numItemsTarget = rng.randomInt(manifest.numItems.minValue, manifest.numItems.maxValue); - while (info.ItemManifest.length + offersToAdd.length < numItemsTarget) { - // TODO: Consider per-bin item limits - // TODO: Consider item probability weightings - const item = rng.randomElement(manifest.items)!; - if (remainingItemCapacity[item.storeItem] != 0) { - remainingItemCapacity[item.storeItem] -= 1; - offersToAdd.push(item); + if (manifest.numItems && manifest.items.length != manifest.numItems.minValue) { + const numItemsTarget = rng.randomInt(manifest.numItems.minValue, manifest.numItems.maxValue); + while (info.ItemManifest.length + offersToAdd.length < numItemsTarget) { + // TODO: Consider per-bin item limits + // TODO: Consider item probability weightings + const item = rng.randomElement(manifest.items)!; + if (remainingItemCapacity[item.storeItem] != 0) { + remainingItemCapacity[item.storeItem] -= 1; + offersToAdd.push(item); + } } + } else { + for (const item of manifest.items) { + if (!item.alwaysOffered && remainingItemCapacity[item.storeItem] != 0) { + remainingItemCapacity[item.storeItem] -= 1; + offersToAdd.push(item); + } + } + for (const e of Object.entries(remainingItemCapacity)) { + const item = manifest.items.find(x => x.storeItem == e[0])!; + if (!item.alwaysOffered) { + while (e[1] != 0) { + e[1] -= 1; + offersToAdd.push(item); + } + } + } + for (const item of manifest.items) { + if (item.alwaysOffered && remainingItemCapacity[item.storeItem] != 0) { + remainingItemCapacity[item.storeItem] -= 1; + offersToAdd.push(item); + } + } + offersToAdd.reverse(); } } else { - let binThisCycle; - if (manifest.isOneBinPerCycle) { - binThisCycle = cycleIndex % 2; // Note: May want to auto-compute the bin size, but this is only used for coda weapons right now. - } + const binThisCycle = cycleIndex % 2; // Note: May want to auto-compute the bin size, but this is only used for coda weapons right now. for (const rawItem of manifest.items) { - if (!manifest.isOneBinPerCycle || rawItem.bin == binThisCycle) { + if (rawItem.bin == binThisCycle) { offersToAdd.push(rawItem); } } - - // For most vendors, the offers seem to roughly be in reverse order from the manifest. Coda weapons are an odd exception. - if (!manifest.isOneBinPerCycle) { - offersToAdd.reverse(); - } } const cycleStart = cycleOffset + cycleIndex * cycleDuration; for (const rawItem of offersToAdd) { @@ -388,4 +394,17 @@ if (isDev) { ) { logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest`); } + + const pall = getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest")! + .VendorInfo.ItemManifest; + if ( + pall.length != 5 || + pall[0].StoreItem != "/Lotus/StoreItems/Types/Items/ShipDecos/HarrowQuestKeyOrnament" || + pall[1].StoreItem != "/Lotus/StoreItems/Types/BoosterPacks/RivenModPack" || + pall[2].StoreItem != "/Lotus/StoreItems/Types/StoreItems/CreditBundles/150000Credits" || + pall[3].StoreItem != "/Lotus/StoreItems/Types/Items/MiscItems/Kuva" || + pall[4].StoreItem != "/Lotus/StoreItems/Types/BoosterPacks/RivenModPack" + ) { + logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest`); + } } diff --git a/static/fixed_responses/getVendorInfo/HubsIronwakeDondaVendorManifest.json b/static/fixed_responses/getVendorInfo/HubsIronwakeDondaVendorManifest.json deleted file mode 100644 index bec20cc1..00000000 --- a/static/fixed_responses/getVendorInfo/HubsIronwakeDondaVendorManifest.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "VendorInfo": { - "_id": { - "$oid": "5dbb4c41e966f7886c3ce939" - }, - "TypeName": "/Lotus/Types/Game/VendorManifests/Hubs/IronwakeDondaVendorManifest", - "ItemManifest": [ - { - "StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/HarrowQuestKeyOrnament", - "ItemPrices": [ - { - "ItemCount": 25, - "ItemType": "/Lotus/Types/Items/MiscItems/PrimeBucks", - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_0", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "604800000" - } - }, - "AllowMultipurchase": true, - "Id": { - "$oid": "66fd60b20ba592c4c95e945f" - } - }, - { - "StoreItem": "/Lotus/StoreItems/Types/BoosterPacks/RivenModPack", - "ItemPrices": [ - { - "ItemCount": 10, - "ItemType": "/Lotus/Types/Items/MiscItems/RivenFragment", - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_0", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "604800000" - } - }, - "PurchaseQuantityLimit": 1, - "AllowMultipurchase": false, - "Id": { - "$oid": "66fd60b20ba592c4c95e9468" - } - }, - { - "StoreItem": "/Lotus/StoreItems/Types/StoreItems/CreditBundles/150000Credits", - "ItemPrices": [ - { - "ItemCount": 5, - "ItemType": "/Lotus/Types/Items/MiscItems/RivenFragment", - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_0", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "604800000" - } - }, - "PurchaseQuantityLimit": 1, - "AllowMultipurchase": false, - "Id": { - "$oid": "66fd60b20ba592c4c95e9469" - } - }, - { - "StoreItem": "/Lotus/StoreItems/Types/Items/MiscItems/Kuva", - "ItemPrices": [ - { - "ItemCount": 10, - "ItemType": "/Lotus/Types/Items/MiscItems/RivenFragment", - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_0", - "QuantityMultiplier": 35000, - "Expiry": { - "$date": { - "$numberLong": "604800000" - } - }, - "PurchaseQuantityLimit": 1, - "AllowMultipurchase": false, - "Id": { - "$oid": "66fd60b20ba592c4c95e946a" - } - }, - { - "StoreItem": "/Lotus/StoreItems/Types/BoosterPacks/RivenModPack", - "ItemPrices": [ - { - "ItemCount": 10, - "ItemType": "/Lotus/Types/Items/MiscItems/RivenFragment", - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_0", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "604800000" - } - }, - "PurchaseQuantityLimit": 1, - "AllowMultipurchase": false, - "Id": { - "$oid": "66fd60b20ba592c4c95e946b" - } - } - ], - "PropertyTextHash": "62B64A8065B7C0FA345895D4BC234621", - "Expiry": { - "$date": { - "$numberLong": "604800000" - } - } - } -}