返回提交历史
Modified
src/services/inventoryService.ts
+21
-0
Modified
src/services/itemDataService.ts
+82
-0
Modified
src/services/purchaseService.ts
+8
-4
Modified
src/services/serversideVendorsService.ts
+18
-3
Modified
src/types/purchaseTypes.ts
+1
-0
XFEstudio/SpaceNinjaServer
feat: railjack forge hub crafting (#4252)
Closes #4248 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/4252 Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com> Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
ff26ed60
代码差异
5 个文件
+130
-7
@@ -1267,6 +1267,27 @@ export const addItem = async (
1267
1267
break;
1268
1268
case "Weapons": {
1269
1269
if (typeName.substring(1).split("/")[4] == "MeleeTrees") break;
1270
if (typeName.substring(1).split("/")[2] == "CrewShip") {
1271
const itemTypeToCount: Record<string, number> = {
1272
"/Lotus/Weapons/CrewShip/MultitoolAmmoItem": 50,
1273
"/Lotus/Weapons/CrewShip/EnergyAmmoItem": 100,
1274
"/Lotus/Weapons/CrewShip/Missiles/MissileAmmoItem": 5,
1275
"/Lotus/Weapons/CrewShip/Laser/MegaLaserAmmoItem": 1
1276
};
1277
if (typeName in itemTypeToCount) {
1278
const inventoryChanges = {
1279
CrewShipAmmo: [
1280
{
1281
ItemType: typeName.replace("AmmoItem", "Ammo"),
1282
ItemCount: itemTypeToCount[typeName] * quantity
1283
}
1284
]
1285
};
1286
1287
addCrewShipAmmo(inventory, inventoryChanges.CrewShipAmmo);
1288
return inventoryChanges;
1289
}
1290
}
1270
1291
const productCategory = typeName.substring(1).split("/")[3];
1271
1292
switch (productCategory) {
1272
1293
case "Pistols":
@@ -11,6 +11,7 @@ import type {
11
11
IRegion,
12
12
ISyndicate,
13
13
IUpgrade,
14
IVendor,
14
15
TMissionDeck,
15
16
TRarity,
16
17
TReward
@@ -50,6 +51,7 @@ import {
50
51
ExportSentinels,
51
52
ExportSyndicates,
52
53
ExportUpgrades,
54
ExportVendors,
53
55
ExportWarframes,
54
56
ExportWeapons
55
57
} from "warframe-public-export-plus";
@@ -1468,6 +1470,82 @@ export const supplementalKeys: Record<string, IKey> = {
1468
1470
}
1469
1471
};
1470
1472
1473
export const supplementalVendors: Record<string, IVendor> = {
1474
"/Lotus/Types/Game/VendorManifests/Hubs/RailjackResourcesVendorManifest": {
1475
isDynamic: false,
1476
items: [
1477
{
1478
storeItem: "/Lotus/StoreItems/Weapons/CrewShip/MultitoolAmmoItem",
1479
quantity: 1,
1480
alwaysOffered: true,
1481
bin: 0,
1482
duplicates: 0,
1483
itemPrices: [
1484
{
1485
ItemType: "/Lotus/Types/Items/RailjackMiscItems/PustrelsRailjackItem",
1486
ItemCount: 5
1487
},
1488
{
1489
ItemType: "/Lotus/Types/Items/RailjackMiscItems/CubicsRailjackItem",
1490
ItemCount: 5
1491
}
1492
]
1493
},
1494
{
1495
storeItem: "/Lotus/StoreItems/Weapons/CrewShip/EnergyAmmoItem",
1496
quantity: 1,
1497
alwaysOffered: true,
1498
bin: 0,
1499
duplicates: 0,
1500
itemPrices: [
1501
{
1502
ItemType: "/Lotus/Types/Items/RailjackMiscItems/CopernicsRailjackItem",
1503
ItemCount: 15
1504
},
1505
{
1506
ItemType: "/Lotus/Types/Items/RailjackMiscItems/CubicsRailjackItem",
1507
ItemCount: 15
1508
}
1509
]
1510
},
1511
{
1512
storeItem: "/Lotus/StoreItems/Weapons/CrewShip/Missiles/MissileAmmoItem",
1513
quantity: 1,
1514
alwaysOffered: true,
1515
bin: 0,
1516
duplicates: 0,
1517
itemPrices: [
1518
{
1519
ItemType: "/Lotus/Types/Items/RailjackMiscItems/CarbidesRailjackItem",
1520
ItemCount: 10
1521
},
1522
{
1523
ItemType: "/Lotus/Types/Items/RailjackMiscItems/CopernicsRailjackItem",
1524
ItemCount: 10
1525
}
1526
]
1527
},
1528
{
1529
storeItem: "/Lotus/StoreItems/Weapons/CrewShip/Laser/MegaLaserAmmoItem",
1530
quantity: 1,
1531
alwaysOffered: true,
1532
bin: 0,
1533
duplicates: 0,
1534
itemPrices: [
1535
{
1536
ItemType: "/Lotus/Types/Items/RailjackMiscItems/PustrelsRailjackItem",
1537
ItemCount: 25
1538
},
1539
{
1540
ItemType: "/Lotus/Types/Items/RailjackMiscItems/CarbidesRailjackItem",
1541
ItemCount: 20
1542
}
1543
]
1544
}
1545
]
1546
}
1547
};
1548
1471
1549
interface IU5FingerprintData {
1472
1550
fits: { type: string; rarity: TRarity; statAtten?: number }[];
1473
1551
upgrades: IU5FingerprintUpgrade[];
@@ -3344,3 +3422,7 @@ export const getShipDecoByNameTag = (name: string): string => {
3344
3422
export const getUpgrade = (uniqueName: string): IUpgrade | undefined => {
3345
3423
return ExportUpgrades[uniqueName] ?? supplementalUpgrades[uniqueName];
3346
3424
};
3425
3426
export const getVendor = (uniqueName: string): IVendor | undefined => {
3427
return ExportVendors[uniqueName] ?? supplementalVendors[uniqueName];
3428
};
@@ -35,7 +35,9 @@ import {
35
35
getBundle,
36
36
getPrice,
37
37
getSyndicate,
38
getVendor,
38
39
slotPurchaseData,
40
supplementalVendors,
39
41
toStoreItem
40
42
} from "./itemDataService.ts";
41
43
import { DailyDeal } from "../models/worldStateModel.ts";
@@ -210,8 +212,7 @@ export const handlePurchase = async (
210
212
}
211
213
purchaseRequest.PurchaseParams.Quantity *= offer.QuantityMultiplier;
212
214
} else {
213
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
214
if (!ExportVendors[purchaseRequest.PurchaseParams.SourceId!]) {
215
if (!getVendor(purchaseRequest.PurchaseParams.SourceId!)) {
215
216
throw new Error(`unknown vendor: ${purchaseRequest.PurchaseParams.SourceId!}`);
216
217
}
217
218
}
@@ -329,8 +330,11 @@ export const handlePurchase = async (
329
330
if (purchaseRequest.PurchaseParams.ExpectedPrice) {
330
331
throw new Error(`vendor purchase should not have an expected price`);
331
332
}
332
if (purchaseRequest.PurchaseParams.SourceId! in ExportVendors) {
333
const vendor = ExportVendors[purchaseRequest.PurchaseParams.SourceId!];
333
if (
334
purchaseRequest.PurchaseParams.SourceId! in ExportVendors ||
335
purchaseRequest.PurchaseParams.SourceId! in supplementalVendors
336
) {
337
const vendor = getVendor(purchaseRequest.PurchaseParams.SourceId!)!;
334
338
const offer = vendor.items.find(x => x.storeItem == purchaseRequest.PurchaseParams.StoreItem);
335
339
if (offer) {
336
340
if (typeof offer.credits == "number" && !inventory.dontSubtractPurchaseCreditCost) {
@@ -10,6 +10,7 @@ import type { IAffiliation } from "../types/inventoryTypes/inventoryTypes.ts";
10
10
import { getNightwaveSyndicateTag, nightwaveTagToSeason } from "./worldStateService.ts";
11
11
import { legacyNightwaveVendorManifest } from "../constants/legacyNightwaveVendorManifest.ts";
12
12
import { BL_LATEST } from "../constants/gameVersions.ts";
13
import { getVendor, supplementalVendors } from "./itemDataService.ts";
13
14
14
15
interface IGeneratableVendorInfo extends Omit<IVendorInfo, "ItemManifest" | "Expiry"> {
15
16
cycleOffset?: number;
@@ -92,8 +93,8 @@ export const getVendorManifestByTypeName = (
92
93
);
93
94
}
94
95
}
95
if (typeName in ExportVendors) {
96
const manifest = ExportVendors[typeName];
96
if (typeName in ExportVendors || typeName in supplementalVendors) {
97
const manifest = getVendor(typeName)!;
97
98
return generateVendorManifest(
98
99
{
99
100
_id: { $oid: getVendorOid(typeName) },
@@ -127,6 +128,20 @@ export const getVendorManifestByOid = (oid: string, buildLabel: string): IVendor
127
128
);
128
129
}
129
130
}
131
for (const [typeName, manifest] of Object.entries(supplementalVendors)) {
132
const typeNameOid = getVendorOid(typeName);
133
if (typeNameOid == oid) {
134
return generateVendorManifest(
135
{
136
_id: { $oid: typeNameOid },
137
TypeName: typeName,
138
RandomSeedType: manifest.randomSeedType,
139
cycleDuration: getCycleDuration(manifest)
140
},
141
config.fullyStockedVendors
142
);
143
}
144
}
130
145
{
131
146
const manifestType = getLegacyNightwaveManifestType(buildLabel);
132
147
if (manifestType) {
@@ -266,7 +281,7 @@ const generateVendorManifest = (
266
281
}
267
282
const cacheEntry = vendorManifestCache[vendorInfo.TypeName];
268
283
const info = cacheEntry.VendorInfo;
269
if (!manifest) manifest = ExportVendors[vendorInfo.TypeName];
284
if (!manifest) manifest = getVendor(vendorInfo.TypeName)!;
270
285
const cycleDurationRange = getCycleDurationRange(manifest);
271
286
let now = Date.now();
272
287
if (cycleDurationRange && cycleDurationRange.minValue != cycleDurationRange.maxValue) {
@@ -94,6 +94,7 @@ export type IInventoryChanges = {
94
94
ShipDecorations?: ITypeCount[];
95
95
EmailItems?: ITypeCount[];
96
96
CrewShipRawSalvage?: ITypeCount[];
97
CrewShipAmmo?: ITypeCount[];
97
98
Nemesis?: Partial<INemesisClient>;
98
99
NewVendorPurchase?: IRecentVendorPurchaseClient; // >= 38.5.0
99
100
RecentVendorPurchases?: IRecentVendorPurchaseClient; // < 38.5.0