XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

SpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 1 Star 0
返回提交历史

XFEstudio/SpaceNinjaServer

feat: autogenerate mask vendor (#2216)

Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2216 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>

3619bdfd
Sainan <63328889+Sainan@users.noreply.github.com>
提交于

代码差异

2 个文件 +37 -313
Modified src/services/serversideVendorsService.ts +37 -12
@@ -18,7 +18,6 @@ import DeimosPetVendorManifest from "@/static/fixed_responses/getVendorInfo/Deim
18 18 import DuviriAcrithisVendorManifest from "@/static/fixed_responses/getVendorInfo/DuviriAcrithisVendorManifest.json";
19 19 import EntratiLabsEntratiLabsCommisionsManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabsCommisionsManifest.json";
20 20 import EntratiLabsEntratiLabVendorManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabVendorManifest.json";
21 import MaskSalesmanManifest from "@/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json";
22 21 import Nova1999ConquestShopManifest from "@/static/fixed_responses/getVendorInfo/Nova1999ConquestShopManifest.json";
23 22 import OstronPetVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronPetVendorManifest.json";
24 23 import SolarisDebtTokenVendorRepossessionsManifest from "@/static/fixed_responses/getVendorInfo/SolarisDebtTokenVendorRepossessionsManifest.json";
@@ -35,7 +34,6 @@ const rawVendorManifests: IVendorManifest[] = [
35 34 DuviriAcrithisVendorManifest,
36 35 EntratiLabsEntratiLabsCommisionsManifest,
37 36 EntratiLabsEntratiLabVendorManifest,
38 MaskSalesmanManifest,
39 37 Nova1999ConquestShopManifest,
40 38 OstronPetVendorManifest,
41 39 SolarisDebtTokenVendorRepossessionsManifest
@@ -277,6 +275,7 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
277 275
278 276 // Add permanent offers
279 277 let numUncountedOffers = 0;
278 let numCountedOffers = 0;
280 279 let offset = 0;
281 280 for (const item of manifest.items) {
282 281 if (item.alwaysOffered || item.rotatedWeekly) {
@@ -287,11 +286,16 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
287 286 offersToAdd.push(item);
288 287 ++offset;
289 288 }
289 } else {
290 numCountedOffers += 1 + item.duplicates;
290 291 }
291 292 }
292 293
293 294 // Add counted offers
294 const useRng = manifest.numItems && manifest.numItems.minValue != manifest.numItems.maxValue;
295 const useRng =
296 manifest.numItems &&
297 (manifest.numItems.minValue != manifest.numItems.maxValue ||
298 manifest.numItems.minValue != numCountedOffers);
295 299 const numItemsTarget = manifest.numItems
296 300 ? numUncountedOffers +
297 301 (useRng
@@ -299,10 +303,13 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
299 303 : manifest.numItems.minValue)
300 304 : manifest.items.length;
301 305 let i = 0;
306 const rollableOffers = manifest.items.filter(x => x.probability !== undefined) as (Omit<
307 IVendorOffer,
308 "probability"
309 > & { probability: number })[];
302 310 while (info.ItemManifest.length + offersToAdd.length < numItemsTarget) {
303 const item = useRng ? rng.randomElement(manifest.items)! : manifest.items[i++];
311 const item = useRng ? rng.randomReward(rollableOffers)! : rollableOffers[i++];
304 312 if (
305 !item.alwaysOffered &&
306 313 remainingItemCapacity[getOfferId(item)] != 0 &&
307 314 (numOffersThatNeedToMatchABin == 0 || missingItemsPerBin[item.bin])
308 315 ) {
@@ -313,7 +320,7 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
313 320 }
314 321 offersToAdd.splice(offset, 0, item);
315 322 }
316 if (i == manifest.items.length) {
323 if (i == rollableOffers.length) {
317 324 i = 0;
318 325 }
319 326 }
@@ -351,7 +358,7 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
351 358 }
352 359 };
353 360 if (rawItem.numRandomItemPrices) {
354 item.ItemPrices = [];
361 item.ItemPrices ??= [];
355 362 for (let i = 0; i != rawItem.numRandomItemPrices; ++i) {
356 363 let itemPrice: { type: string; count: IRange };
357 364 do {
@@ -391,11 +398,13 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
391 398 info.ItemManifest.push(item);
392 399 }
393 400
394 info.ItemManifest.sort((a, b) => {
395 const aBin = parseInt(a.Bin.substring(4));
396 const bBin = parseInt(b.Bin.substring(4));
397 return aBin == bBin ? 0 : aBin < bBin ? +1 : -1;
398 });
401 if (manifest.numItemsPerBin) {
402 info.ItemManifest.sort((a, b) => {
403 const aBin = parseInt(a.Bin.substring(4));
404 const bBin = parseInt(b.Bin.substring(4));
405 return aBin == bBin ? 0 : aBin < bBin ? +1 : -1;
406 });
407 }
399 408
400 409 // Update vendor expiry
401 410 let soonestOfferExpiry: number = Number.MAX_SAFE_INTEGER;
@@ -464,4 +473,20 @@ if (isDev) {
464 473 if (!temple.find(x => x.StoreItem == "/Lotus/StoreItems/Types/Items/MiscItems/Kuva")) {
465 474 logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/TheHex/Temple1999VendorManifest`);
466 475 }
476
477 const nakak = getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest")!
478 .VendorInfo.ItemManifest;
479 if (
480 nakak.length != 10 ||
481 nakak[0].StoreItem != "/Lotus/StoreItems/Upgrades/Skins/Ostron/RevenantMask" ||
482 nakak[1].StoreItem != "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumper" ||
483 nakak[1].ItemPrices?.length != 4 ||
484 nakak[2].StoreItem != "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperMedium" ||
485 nakak[2].ItemPrices?.length != 4 ||
486 nakak[3].StoreItem != "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperLarge" ||
487 nakak[3].ItemPrices?.length != 4
488 // The remaining offers should be computed by weighted RNG.
489 ) {
490 logger.warn(`self test failed for /Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest`);
491 }
467 492 }
Deleted static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json +0 -301
@@ -1,301 +0,0 @@
1 {
2 "VendorInfo": {
3 "_id": {
4 "$oid": "598a090d9a4a313746fd1f24"
5 },
6 "TypeName": "/Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest",
7 "ItemManifest": [
8 {
9 "StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/RevenantMask",
10 "ItemPrices": [
11 {
12 "ItemCount": 1,
13 "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem",
14 "ProductCategory": "MiscItems"
15 }
16 ],
17 "Bin": "BIN_0",
18 "QuantityMultiplier": 1,
19 "Expiry": {
20 "$date": {
21 "$numberLong": "9999999000000"
22 }
23 },
24 "AllowMultipurchase": true,
25 "Id": {
26 "$oid": "63ed01ef4c37f93d0b797674"
27 }
28 },
29 {
30 "StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumper",
31 "ItemPrices": [
32 {
33 "ItemCount": 2,
34 "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem",
35 "ProductCategory": "MiscItems"
36 },
37 {
38 "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishBPartItem",
39 "ItemCount": 10,
40 "ProductCategory": "MiscItems"
41 },
42 {
43 "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/NistlebrushItem",
44 "ItemCount": 10,
45 "ProductCategory": "MiscItems"
46 },
47 {
48 "ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreAAlloyAItem",
49 "ItemCount": 32,
50 "ProductCategory": "MiscItems"
51 }
52 ],
53 "Bin": "BIN_0",
54 "QuantityMultiplier": 1,
55 "Expiry": {
56 "$date": {
57 "$numberLong": "9999999000000"
58 }
59 },
60 "AllowMultipurchase": true,
61 "Id": {
62 "$oid": "63ed01ef4c37f93d0b797675"
63 }
64 },
65 {
66 "StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperMedium",
67 "ItemPrices": [
68 {
69 "ItemCount": 4,
70 "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem",
71 "ProductCategory": "MiscItems"
72 },
73 {
74 "ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonGemBCutAItem",
75 "ItemCount": 24,
76 "ProductCategory": "MiscItems"
77 },
78 {
79 "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishAPartItem",
80 "ItemCount": 18,
81 "ProductCategory": "MiscItems"
82 },
83 {
84 "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishBPartItem",
85 "ItemCount": 27,
86 "ProductCategory": "MiscItems"
87 }
88 ],
89 "Bin": "BIN_1",
90 "QuantityMultiplier": 1,
91 "Expiry": {
92 "$date": {
93 "$numberLong": "9999999000000"
94 }
95 },
96 "AllowMultipurchase": true,
97 "Id": {
98 "$oid": "63ed01ef4c37f93d0b797676"
99 }
100 },
101 {
102 "StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperLarge",
103 "ItemPrices": [
104 {
105 "ItemCount": 6,
106 "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem",
107 "ProductCategory": "MiscItems"
108 },
109 {
110 "ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonGemACutAItem",
111 "ItemCount": 35,
112 "ProductCategory": "MiscItems"
113 },
114 {
115 "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothCommonFishAPartItem",
116 "ItemCount": 95,
117 "ProductCategory": "MiscItems"
118 },
119 {
120 "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/NistlebrushItem",
121 "ItemCount": 60,
122 "ProductCategory": "MiscItems"
123 }
124 ],
125 "Bin": "BIN_0",
126 "QuantityMultiplier": 1,
127 "Expiry": {
128 "$date": {
129 "$numberLong": "9999999000000"
130 }
131 },
132 "AllowMultipurchase": true,
133 "Id": {
134 "$oid": "63ed01ef4c37f93d0b797677"
135 }
136 },
137 {
138 "StoreItem": "/Lotus/StoreItems/Types/Recipes/SynthicatorRecipes/FlareBlueBlueprint",
139 "ItemPrices": [
140 {
141 "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishBPartItem",
142 "ItemCount": 10,
143 "ProductCategory": "MiscItems"
144 },
145 {
146 "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/DayCommonFishCPartItem",
147 "ItemCount": 10,
148 "ProductCategory": "MiscItems"
149 }
150 ],
151 "Bin": "BIN_0",
152 "QuantityMultiplier": 1,
153 "Expiry": {
154 "$date": {
155 "$numberLong": "9999999000000"
156 }
157 },
158 "AllowMultipurchase": true,
159 "Id": {
160 "$oid": "6651291214e90115b91b50a1"
161 }
162 },
163 {
164 "StoreItem": "/Lotus/StoreItems/Types/Recipes/SynthicatorRecipes/FlareRedBlueprint",
165 "ItemPrices": [
166 {
167 "ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreAAlloyAItem",
168 "ItemCount": 37,
169 "ProductCategory": "MiscItems"
170 },
171 {
172 "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishAPartItem",
173 "ItemCount": 7,
174 "ProductCategory": "MiscItems"
175 }
176 ],
177 "Bin": "BIN_0",
178 "QuantityMultiplier": 1,
179 "Expiry": {
180 "$date": {
181 "$numberLong": "9999999000000"
182 }
183 },
184 "AllowMultipurchase": true,
185 "Id": {
186 "$oid": "6651291214e90115b91b50a2"
187 }
188 },
189 {
190 "StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/VoltMask",
191 "ItemPrices": [
192 {
193 "ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreBAlloyBItem",
194 "ItemCount": 34,
195 "ProductCategory": "MiscItems"
196 },
197 {
198 "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/GrokdrulItem",
199 "ItemCount": 17,
200 "ProductCategory": "MiscItems"
201 }
202 ],
203 "Bin": "BIN_0",
204 "QuantityMultiplier": 1,
205 "Expiry": {
206 "$date": {
207 "$numberLong": "9999999000000"
208 }
209 },
210 "AllowMultipurchase": true,
211 "Id": {
212 "$oid": "6651291214e90115b91b50a3"
213 }
214 },
215 {
216 "StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/MagMask",
217 "ItemPrices": [
218 {
219 "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/DayCommonFishBPartItem",
220 "ItemCount": 16,
221 "ProductCategory": "MiscItems"
222 },
223 {
224 "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/ForestRodentPartItem",
225 "ItemCount": 5,
226 "ProductCategory": "MiscItems"
227 }
228 ],
229 "Bin": "BIN_0",
230 "QuantityMultiplier": 1,
231 "Expiry": {
232 "$date": {
233 "$numberLong": "9999999000000"
234 }
235 },
236 "AllowMultipurchase": true,
237 "Id": {
238 "$oid": "6651291214e90115b91b50a4"
239 }
240 },
241 {
242 "StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/ExcaliburMask",
243 "ItemPrices": [
244 {
245 "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/BirdOfPreyPartItem",
246 "ItemCount": 5,
247 "ProductCategory": "MiscItems"
248 },
249 {
250 "ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/GrokdrulItem",
251 "ItemCount": 20,
252 "ProductCategory": "MiscItems"
253 }
254 ],
255 "Bin": "BIN_0",
256 "QuantityMultiplier": 1,
257 "Expiry": {
258 "$date": {
259 "$numberLong": "9999999000000"
260 }
261 },
262 "AllowMultipurchase": true,
263 "Id": {
264 "$oid": "6651291214e90115b91b50a5"
265 }
266 },
267 {
268 "StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/GrineerMask",
269 "ItemPrices": [
270 {
271 "ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/DayCommonFishBPartItem",
272 "ItemCount": 20,
273 "ProductCategory": "MiscItems"
274 },
275 {
276 "ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreAAlloyAItem",
277 "ItemCount": 31,
278 "ProductCategory": "MiscItems"
279 }
280 ],
281 "Bin": "BIN_1",
282 "QuantityMultiplier": 1,
283 "Expiry": {
284 "$date": {
285 "$numberLong": "9999999000000"
286 }
287 },
288 "AllowMultipurchase": true,
289 "Id": {
290 "$oid": "6651291214e90115b91b50a6"
291 }
292 }
293 ],
294 "PropertyTextHash": "6AACA376DA34B35B5C16F1B40DBC017D",
295 "Expiry": {
296 "$date": {
297 "$numberLong": "9999999000000"
298 }
299 }
300 }
301 }