From 01cdc094ab945b9265d77179894f1582fb0f3233 Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Fri, 20 Jun 2025 04:40:56 +0200 Subject: [PATCH] feat: autogenerate mask vendor --- src/services/serversideVendorsService.ts | 49 ++- .../getVendorInfo/MaskSalesmanManifest.json | 301 ------------------ 2 files changed, 37 insertions(+), 313 deletions(-) delete mode 100644 static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json diff --git a/src/services/serversideVendorsService.ts b/src/services/serversideVendorsService.ts index 6205060f..774180d6 100644 --- a/src/services/serversideVendorsService.ts +++ b/src/services/serversideVendorsService.ts @@ -18,7 +18,6 @@ import DeimosPetVendorManifest from "@/static/fixed_responses/getVendorInfo/Deim 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 MaskSalesmanManifest from "@/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json"; import Nova1999ConquestShopManifest from "@/static/fixed_responses/getVendorInfo/Nova1999ConquestShopManifest.json"; import OstronPetVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronPetVendorManifest.json"; import SolarisDebtTokenVendorRepossessionsManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorRepossessionsManifest.json"; @@ -35,7 +34,6 @@ const rawVendorManifests: IVendorManifest[] = [ DuviriAcrithisVendorManifest, EntratiLabsEntratiLabsCommisionsManifest, EntratiLabsEntratiLabVendorManifest, - MaskSalesmanManifest, Nova1999ConquestShopManifest, OstronPetVendorManifest, SolarisDebtTokenVendorRepossessionsManifest @@ -277,6 +275,7 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani // Add permanent offers let numUncountedOffers = 0; + let numCountedOffers = 0; let offset = 0; for (const item of manifest.items) { if (item.alwaysOffered || item.rotatedWeekly) { @@ -287,11 +286,16 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani offersToAdd.push(item); ++offset; } + } else { + numCountedOffers += 1 + item.duplicates; } } // Add counted offers - const useRng = manifest.numItems && manifest.numItems.minValue != manifest.numItems.maxValue; + const useRng = + manifest.numItems && + (manifest.numItems.minValue != manifest.numItems.maxValue || + manifest.numItems.minValue != numCountedOffers); const numItemsTarget = manifest.numItems ? numUncountedOffers + (useRng @@ -299,10 +303,13 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani : manifest.numItems.minValue) : manifest.items.length; let i = 0; + const rollableOffers = manifest.items.filter(x => x.probability !== undefined) as (Omit< + IVendorOffer, + "probability" + > & { probability: number })[]; while (info.ItemManifest.length + offersToAdd.length < numItemsTarget) { - const item = useRng ? rng.randomElement(manifest.items)! : manifest.items[i++]; + const item = useRng ? rng.randomReward(rollableOffers)! : rollableOffers[i++]; if ( - !item.alwaysOffered && remainingItemCapacity[getOfferId(item)] != 0 && (numOffersThatNeedToMatchABin == 0 || missingItemsPerBin[item.bin]) ) { @@ -313,7 +320,7 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani } offersToAdd.splice(offset, 0, item); } - if (i == manifest.items.length) { + if (i == rollableOffers.length) { i = 0; } } @@ -351,7 +358,7 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani } }; if (rawItem.numRandomItemPrices) { - item.ItemPrices = []; + item.ItemPrices ??= []; for (let i = 0; i != rawItem.numRandomItemPrices; ++i) { let itemPrice: { type: string; count: IRange }; do { @@ -391,11 +398,13 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani info.ItemManifest.push(item); } - info.ItemManifest.sort((a, b) => { - const aBin = parseInt(a.Bin.substring(4)); - const bBin = parseInt(b.Bin.substring(4)); - return aBin == bBin ? 0 : aBin < bBin ? +1 : -1; - }); + if (manifest.numItemsPerBin) { + info.ItemManifest.sort((a, b) => { + const aBin = parseInt(a.Bin.substring(4)); + const bBin = parseInt(b.Bin.substring(4)); + return aBin == bBin ? 0 : aBin < bBin ? +1 : -1; + }); + } // Update vendor expiry let soonestOfferExpiry: number = Number.MAX_SAFE_INTEGER; @@ -464,4 +473,20 @@ if (isDev) { if (!temple.find(x => x.StoreItem == "/Lotus/StoreItems/Types/Items/MiscItems/Kuva")) { logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/TheHex/Temple1999VendorManifest`); } + + const nakak = getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest")! + .VendorInfo.ItemManifest; + if ( + nakak.length != 10 || + nakak[0].StoreItem != "/Lotus/StoreItems/Upgrades/Skins/Ostron/RevenantMask" || + nakak[1].StoreItem != "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumper" || + nakak[1].ItemPrices?.length != 4 || + nakak[2].StoreItem != "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperMedium" || + nakak[2].ItemPrices?.length != 4 || + nakak[3].StoreItem != "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperLarge" || + nakak[3].ItemPrices?.length != 4 + // The remaining offers should be computed by weighted RNG. + ) { + logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest`); + } } diff --git a/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json b/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json deleted file mode 100644 index 85aa7eac..00000000 --- a/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json +++ /dev/null @@ -1,301 +0,0 @@ -{ - "VendorInfo": { - "_id": { - "$oid": "598a090d9a4a313746fd1f24" - }, - "TypeName": "/Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest", - "ItemManifest": [ - { - "StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/RevenantMask", - "ItemPrices": [ - { - "ItemCount": 1, - "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem", - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_0", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "9999999000000" - } - }, - "AllowMultipurchase": true, - "Id": { - "$oid": "63ed01ef4c37f93d0b797674" - } - }, - { - "StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumper", - "ItemPrices": [ - { - "ItemCount": 2, - "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem", - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishBPartItem", - "ItemCount": 10, - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/NistlebrushItem", - "ItemCount": 10, - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreAAlloyAItem", - "ItemCount": 32, - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_0", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "9999999000000" - } - }, - "AllowMultipurchase": true, - "Id": { - "$oid": "63ed01ef4c37f93d0b797675" - } - }, - { - "StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperMedium", - "ItemPrices": [ - { - "ItemCount": 4, - "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem", - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonGemBCutAItem", - "ItemCount": 24, - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishAPartItem", - "ItemCount": 18, - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishBPartItem", - "ItemCount": 27, - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_1", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "9999999000000" - } - }, - "AllowMultipurchase": true, - "Id": { - "$oid": "63ed01ef4c37f93d0b797676" - } - }, - { - "StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperLarge", - "ItemPrices": [ - { - "ItemCount": 6, - "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem", - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonGemACutAItem", - "ItemCount": 35, - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothCommonFishAPartItem", - "ItemCount": 95, - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/NistlebrushItem", - "ItemCount": 60, - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_0", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "9999999000000" - } - }, - "AllowMultipurchase": true, - "Id": { - "$oid": "63ed01ef4c37f93d0b797677" - } - }, - { - "StoreItem": "/Lotus/StoreItems/Types/Recipes/SynthicatorRecipes/FlareBlueBlueprint", - "ItemPrices": [ - { - "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishBPartItem", - "ItemCount": 10, - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/DayCommonFishCPartItem", - "ItemCount": 10, - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_0", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "9999999000000" - } - }, - "AllowMultipurchase": true, - "Id": { - "$oid": "6651291214e90115b91b50a1" - } - }, - { - "StoreItem": "/Lotus/StoreItems/Types/Recipes/SynthicatorRecipes/FlareRedBlueprint", - "ItemPrices": [ - { - "ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreAAlloyAItem", - "ItemCount": 37, - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishAPartItem", - "ItemCount": 7, - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_0", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "9999999000000" - } - }, - "AllowMultipurchase": true, - "Id": { - "$oid": "6651291214e90115b91b50a2" - } - }, - { - "StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/VoltMask", - "ItemPrices": [ - { - "ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreBAlloyBItem", - "ItemCount": 34, - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/GrokdrulItem", - "ItemCount": 17, - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_0", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "9999999000000" - } - }, - "AllowMultipurchase": true, - "Id": { - "$oid": "6651291214e90115b91b50a3" - } - }, - { - "StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/MagMask", - "ItemPrices": [ - { - "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/DayCommonFishBPartItem", - "ItemCount": 16, - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/ForestRodentPartItem", - "ItemCount": 5, - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_0", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "9999999000000" - } - }, - "AllowMultipurchase": true, - "Id": { - "$oid": "6651291214e90115b91b50a4" - } - }, - { - "StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/ExcaliburMask", - "ItemPrices": [ - { - "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/BirdOfPreyPartItem", - "ItemCount": 5, - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/GrokdrulItem", - "ItemCount": 20, - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_0", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "9999999000000" - } - }, - "AllowMultipurchase": true, - "Id": { - "$oid": "6651291214e90115b91b50a5" - } - }, - { - "StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/GrineerMask", - "ItemPrices": [ - { - "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/DayCommonFishBPartItem", - "ItemCount": 20, - "ProductCategory": "MiscItems" - }, - { - "ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreAAlloyAItem", - "ItemCount": 31, - "ProductCategory": "MiscItems" - } - ], - "Bin": "BIN_1", - "QuantityMultiplier": 1, - "Expiry": { - "$date": { - "$numberLong": "9999999000000" - } - }, - "AllowMultipurchase": true, - "Id": { - "$oid": "6651291214e90115b91b50a6" - } - } - ], - "PropertyTextHash": "6AACA376DA34B35B5C16F1B40DBC017D", - "Expiry": { - "$date": { - "$numberLong": "9999999000000" - } - } - } -}