返回提交历史
Added
src/controllers/api/crewShipFusionController.ts
+107
-0
Modified
src/routes/api.ts
+2
-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
代码差异
2 个文件
+109
-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];
@@ -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);