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

XFESpaceNinjaServer

A simple server for a small space ninja game

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

XFEstudio/XFESpaceNinjaServer

feat: railjack valence fusion (#2194)

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

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

代码差异

2 个文件 +109 -0
Added src/controllers/api/crewShipFusionController.ts +107 -0
@@ -0,0 +1,107 @@
1 import { getJSONfromString } from "@/src/helpers/stringHelpers";
2 import { addMiscItems, freeUpSlot, getInventory, updateCurrency } from "@/src/services/inventoryService";
3 import { getAccountIdForRequest } from "@/src/services/loginService";
4 import { IOid } from "@/src/types/commonTypes";
5 import { ICrewShipComponentFingerprint, InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
6 import { IInventoryChanges } from "@/src/types/purchaseTypes";
7 import { RequestHandler } from "express";
8 import { ExportCustoms, ExportDojoRecipes } from "warframe-public-export-plus";
9
10 export const crewShipFusionController: RequestHandler = async (req, res) => {
11 const accountId = await getAccountIdForRequest(req);
12 const inventory = await getInventory(accountId);
13 const payload = getJSONfromString<ICrewShipFusionRequest>(String(req.body));
14
15 const isWeapon = inventory.CrewShipWeapons.id(payload.PartA.$oid);
16 const itemA = isWeapon ?? inventory.CrewShipWeaponSkins.id(payload.PartA.$oid)!;
17 const category = isWeapon ? "CrewShipWeapons" : "CrewShipWeaponSkins";
18 const salvageCategory = isWeapon ? "CrewShipSalvagedWeapons" : "CrewShipSalvagedWeaponSkins";
19 const itemB = inventory[payload.SourceRecipe ? salvageCategory : category].id(payload.PartB.$oid)!;
20 const tierA = itemA.ItemType.charCodeAt(itemA.ItemType.length - 1) - 65;
21 const tierB = itemB.ItemType.charCodeAt(itemB.ItemType.length - 1) - 65;
22
23 const inventoryChanges: IInventoryChanges = {};
24
25 // Charge partial repair cost if fusing with an identified but unrepaired part
26 if (payload.SourceRecipe) {
27 const recipe = ExportDojoRecipes.research[payload.SourceRecipe];
28 updateCurrency(inventory, Math.round(recipe.price * 0.4), false, inventoryChanges);
29 const miscItemChanges = recipe.ingredients.map(x => ({ ...x, ItemCount: Math.round(x.ItemCount * -0.4) }));
30 addMiscItems(inventory, miscItemChanges);
31 inventoryChanges.MiscItems = miscItemChanges;
32 }
33
34 // Remove inferior item
35 if (payload.SourceRecipe) {
36 inventory[salvageCategory].pull({ _id: payload.PartB.$oid });
37 inventoryChanges.RemovedIdItems = [{ ItemId: payload.PartB }];
38 } else {
39 const inferiorId = tierA < tierB ? payload.PartA : payload.PartB;
40 inventory[category].pull({ _id: inferiorId.$oid });
41 inventoryChanges.RemovedIdItems = [{ ItemId: inferiorId }];
42 freeUpSlot(inventory, InventorySlot.RJ_COMPONENT_AND_ARMAMENTS);
43 inventoryChanges[InventorySlot.RJ_COMPONENT_AND_ARMAMENTS] = { count: -1, platinum: 0, Slots: 1 };
44 }
45
46 // Upgrade superior item
47 const superiorItem = tierA < tierB ? itemB : itemA;
48 const inferiorItem = tierA < tierB ? itemA : itemB;
49 const fingerprint: ICrewShipComponentFingerprint = JSON.parse(
50 superiorItem.UpgradeFingerprint!
51 ) as ICrewShipComponentFingerprint;
52 const inferiorFingerprint: ICrewShipComponentFingerprint = inferiorItem.UpgradeFingerprint
53 ? (JSON.parse(inferiorItem.UpgradeFingerprint) as ICrewShipComponentFingerprint)
54 : { compat: "", buffs: [] };
55 if (isWeapon) {
56 for (let i = 0; i != fingerprint.buffs.length; ++i) {
57 const buffA = fingerprint.buffs[i];
58 const buffB = i < inferiorFingerprint.buffs.length ? inferiorFingerprint.buffs[i] : undefined;
59 const fvalA = buffA.Value / 0x3fffffff;
60 const fvalB = (buffB?.Value ?? 0) / 0x3fffffff;
61 const percA = 0.3 + fvalA * (0.6 - 0.3);
62 const percB = 0.3 + fvalB * (0.6 - 0.3);
63 const newPerc = Math.min(0.6, Math.max(percA, percB) * FUSE_MULTIPLIERS[Math.abs(tierA - tierB)]);
64 const newFval = (newPerc - 0.3) / (0.6 - 0.3);
65 buffA.Value = Math.trunc(newFval * 0x3fffffff);
66 }
67 } else {
68 const superiorMeta = ExportCustoms[superiorItem.ItemType].randomisedUpgrades ?? [];
69 const inferiorMeta = ExportCustoms[inferiorItem.ItemType].randomisedUpgrades ?? [];
70 for (let i = 0; i != inferiorFingerprint.buffs.length; ++i) {
71 const buffA = fingerprint.buffs[i];
72 const buffB = inferiorFingerprint.buffs[i];
73 const fvalA = buffA.Value / 0x3fffffff;
74 const fvalB = buffB.Value / 0x3fffffff;
75 const rangeA = superiorMeta[i].range;
76 const rangeB = inferiorMeta[i].range;
77 const percA = rangeA[0] + fvalA * (rangeA[1] - rangeA[0]);
78 const percB = rangeB[0] + fvalB * (rangeB[1] - rangeB[0]);
79 const newPerc = Math.min(rangeA[1], Math.max(percA, percB) * FUSE_MULTIPLIERS[Math.abs(tierA - tierB)]);
80 const newFval = (newPerc - rangeA[0]) / (rangeA[1] - rangeA[0]);
81 buffA.Value = Math.trunc(newFval * 0x3fffffff);
82 }
83 if (inferiorFingerprint.SubroutineIndex) {
84 const useSuperiorSubroutine = tierA < tierB ? !payload.UseSubroutineA : payload.UseSubroutineA;
85 if (!useSuperiorSubroutine) {
86 fingerprint.SubroutineIndex = inferiorFingerprint.SubroutineIndex;
87 }
88 }
89 }
90 superiorItem.UpgradeFingerprint = JSON.stringify(fingerprint);
91 // eslint-disable-next-line @typescript-eslint/no-explicit-any
92 inventoryChanges[category] = [superiorItem.toJSON() as any];
93
94 await inventory.save();
95 res.json({
96 InventoryChanges: inventoryChanges
97 });
98 };
99
100 interface ICrewShipFusionRequest {
101 PartA: IOid;
102 PartB: IOid;
103 SourceRecipe: string;
104 UseSubroutineA: boolean;
105 }
106
107 const FUSE_MULTIPLIERS = [1.1, 1.05, 1.02];
Modified src/routes/api.ts +2 -0
@@ -33,6 +33,7 @@ import { createAllianceController } from "@/src/controllers/api/createAllianceCo
33 33 import { createGuildController } from "@/src/controllers/api/createGuildController";
34 34 import { creditsController } from "@/src/controllers/api/creditsController";
35 35 import { crewMembersController } from "@/src/controllers/api/crewMembersController";
36 import { crewShipFusionController } from "@/src/controllers/api/crewShipFusionController";
36 37 import { crewShipIdentifySalvageController } from "@/src/controllers/api/crewShipIdentifySalvageController";
37 38 import { customizeGuildRanksController } from "@/src/controllers/api/customizeGuildRanksController";
38 39 import { customObstacleCourseLeaderboardController } from "@/src/controllers/api/customObstacleCourseLeaderboardController";
@@ -247,6 +248,7 @@ apiRouter.post("/contributeToVault.php", contributeToVaultController);
247 248 apiRouter.post("/createAlliance.php", createAllianceController);
248 249 apiRouter.post("/createGuild.php", createGuildController);
249 250 apiRouter.post("/crewMembers.php", crewMembersController);
251 apiRouter.post("/crewShipFusion.php", crewShipFusionController);
250 252 apiRouter.post("/crewShipIdentifySalvage.php", crewShipIdentifySalvageController);
251 253 apiRouter.post("/customizeGuildRanks.php", customizeGuildRanksController);
252 254 apiRouter.post("/customObstacleCourseLeaderboard.php", customObstacleCourseLeaderboardController);