返回提交历史
Modified
src/controllers/api/nemesisController.ts
+86
-47
Modified
src/helpers/nemesisHelpers.ts
+70
-3
XFEstudio/SpaceNinjaServer
feat: weaken nemesis (#1893)
Closes #1885 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1893 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
88d00eaa
代码差异
2 个文件
+156
-50
@@ -2,9 +2,12 @@ import {
2
2
consumeModCharge,
3
3
encodeNemesisGuess,
4
4
getInfNodes,
5
getKnifeUpgrade,
5
6
getNemesisPasscode,
7
getNemesisPasscodeModTypes,
6
8
getWeaponsForManifest,
7
IKnifeResponse
9
IKnifeResponse,
10
showdownNodes
8
11
} from "@/src/helpers/nemesisHelpers";
9
12
import { getJSONfromString } from "@/src/helpers/stringHelpers";
10
13
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
@@ -15,6 +18,8 @@ import { IMongoDate, IOid } from "@/src/types/commonTypes";
15
18
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
16
19
import {
17
20
IInnateDamageFingerprint,
21
IInventoryClient,
22
INemesisClient,
18
23
InventorySlot,
19
24
IUpgradeClient,
20
25
IWeaponSkinClient,
@@ -100,50 +105,45 @@ export const nemesisController: RequestHandler = async (req, res) => {
100
105
encodeNemesisGuess(guess[0], result1, guess[1], result2, guess[2], result3)
101
106
);
102
107
103
// Increase antivirus
104
let antivirusGain = 5;
105
const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
106
const dataknifeLoadout = loadout.DATAKNIFE.id(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid);
107
const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
108
const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
108
// Increase antivirus if correct antivirus mod is installed
109
109
const response: IKnifeResponse = {};
110
for (const upgrade of body.knife!.AttachedUpgrades) {
111
switch (upgrade.ItemType) {
112
case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusAndSpeedOnUseMod":
113
antivirusGain += 10;
114
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
115
break;
116
case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusAndWeaponDamageOnUseMod":
117
antivirusGain += 10;
118
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
119
break;
120
case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusLargeOnSingleUseMod": // Instant Secure
121
antivirusGain += 15;
122
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
123
break;
124
case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusOnUseMod": // Immuno Shield
125
antivirusGain += 15;
126
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
127
break;
128
case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusSmallOnSingleUseMod":
129
antivirusGain += 10;
130
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
131
break;
110
if (result1 == 0 || result2 == 0 || result3 == 0) {
111
let antivirusGain = 5;
112
const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
113
const dataknifeLoadout = loadout.DATAKNIFE.id(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid);
114
const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
115
const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
116
for (const upgrade of body.knife!.AttachedUpgrades) {
117
switch (upgrade.ItemType) {
118
case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusAndSpeedOnUseMod":
119
antivirusGain += 10;
120
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
121
break;
122
case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusAndWeaponDamageOnUseMod":
123
antivirusGain += 10;
124
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
125
break;
126
case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusLargeOnSingleUseMod": // Instant Secure
127
antivirusGain += 15;
128
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
129
break;
130
case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusOnUseMod": // Immuno Shield
131
antivirusGain += 15;
132
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
133
break;
134
case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusSmallOnSingleUseMod":
135
antivirusGain += 10;
136
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
137
break;
138
}
132
139
}
140
inventory.Nemesis!.HenchmenKilled += antivirusGain;
133
141
}
134
inventory.Nemesis!.HenchmenKilled += antivirusGain;
142
135
143
if (inventory.Nemesis!.HenchmenKilled >= 100) {
136
144
inventory.Nemesis!.HenchmenKilled = 100;
137
inventory.Nemesis!.InfNodes = [
138
{
139
Node: "CrewBattleNode559",
140
Influence: 1
141
}
142
];
143
inventory.Nemesis!.Weakened = true;
144
} else {
145
inventory.Nemesis!.InfNodes = getInfNodes("FC_INFESTATION", 0);
146
145
}
146
inventory.Nemesis!.InfNodes = getInfNodes("FC_INFESTATION", 0);
147
147
148
148
await inventory.save();
149
149
res.json(response);
@@ -213,6 +213,38 @@ export const nemesisController: RequestHandler = async (req, res) => {
213
213
res.json({
214
214
target: inventory.toJSON().Nemesis
215
215
});
216
} else if ((req.query.mode as string) == "w") {
217
const inventory = await getInventory(
218
accountId,
219
"Nemesis LoadOutPresets CurrentLoadOutIds DataKnives Upgrades RawUpgrades"
220
);
221
//const body = getJSONfromString<INemesisWeakenRequest>(String(req.body));
222
223
inventory.Nemesis!.InfNodes = [
224
{
225
Node: showdownNodes[inventory.Nemesis!.Faction],
226
Influence: 1
227
}
228
];
229
inventory.Nemesis!.Weakened = true;
230
231
const response: IKnifeResponse & { target: INemesisClient } = {
232
target: inventory.toJSON<IInventoryClient>().Nemesis!
233
};
234
235
// Consume charge of the correct requiem mod(s)
236
const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
237
const dataknifeLoadout = loadout.DATAKNIFE.id(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid);
238
const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
239
const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
240
const modTypes = getNemesisPasscodeModTypes(inventory.Nemesis!);
241
for (const modType of modTypes) {
242
const upgrade = getKnifeUpgrade(inventory, dataknifeUpgrades, modType);
243
consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
244
}
245
246
await inventory.save();
247
res.json(response);
216
248
} else {
217
249
logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
218
250
throw new Error(`unknown nemesis mode: ${String(req.query.mode)}`);
@@ -264,12 +296,19 @@ interface INemesisRequiemRequest {
264
296
guess: number; // grn/crp: 4 bits | coda: 3x 4 bits
265
297
position: number; // grn/crp: 0-2 | coda: 0
266
298
// knife field provided for coda only
267
knife?: {
268
Item: IEquipmentClient;
269
Skins: IWeaponSkinClient[];
270
ModSlot: number;
271
CustSlot: number;
272
AttachedUpgrades: IUpgradeClient[];
273
HiddenWhenHolstered: boolean;
274
};
299
knife?: IKnife;
300
}
301
302
// interface INemesisWeakenRequest {
303
// target: INemesisClient;
304
// knife: IKnife;
305
// }
306
307
interface IKnife {
308
Item: IEquipmentClient;
309
Skins: IWeaponSkinClient[];
310
ModSlot: number;
311
CustSlot: number;
312
AttachedUpgrades: IUpgradeClient[];
313
HiddenWhenHolstered: boolean;
275
314
}
@@ -38,17 +38,59 @@ const systemIndexes: Record<string, number[]> = {
38
38
FC_INFESTATION: [23]
39
39
};
40
40
41
export const showdownNodes: Record<string, string> = {
42
FC_GRINEER: "CrewBattleNode557",
43
FC_CORPUS: "CrewBattleNode558",
44
FC_INFESTATION: "CrewBattleNode559"
45
};
46
41
47
// Get a parazon 'passcode' based on the nemesis fingerprint so it's always the same for the same nemesis.
42
48
export const getNemesisPasscode = (nemesis: { fp: bigint; Faction: string }): number[] => {
43
49
const rng = new SRng(nemesis.fp);
44
const passcode = [rng.randomInt(0, 7)];
50
const choices = [0, 1, 2, 3, 5, 6, 7];
51
let choiceIndex = rng.randomInt(0, choices.length - 1);
52
const passcode = [choices[choiceIndex]];
45
53
if (nemesis.Faction != "FC_INFESTATION") {
46
passcode.push(rng.randomInt(0, 7));
47
passcode.push(rng.randomInt(0, 7));
54
choices.splice(choiceIndex, 1);
55
choiceIndex = rng.randomInt(0, choices.length - 1);
56
passcode.push(choices[choiceIndex]);
57
58
choices.splice(choiceIndex, 1);
59
choiceIndex = rng.randomInt(0, choices.length - 1);
60
passcode.push(choices[choiceIndex]);
48
61
}
49
62
return passcode;
50
63
};
51
64
65
const reqiuemMods: readonly string[] = [
66
"/Lotus/Upgrades/Mods/Immortal/ImmortalOneMod",
67
"/Lotus/Upgrades/Mods/Immortal/ImmortalTwoMod",
68
"/Lotus/Upgrades/Mods/Immortal/ImmortalThreeMod",
69
"/Lotus/Upgrades/Mods/Immortal/ImmortalFourMod",
70
"/Lotus/Upgrades/Mods/Immortal/ImmortalFiveMod",
71
"/Lotus/Upgrades/Mods/Immortal/ImmortalSixMod",
72
"/Lotus/Upgrades/Mods/Immortal/ImmortalSevenMod",
73
"/Lotus/Upgrades/Mods/Immortal/ImmortalEightMod"
74
];
75
76
const antivirusMods: readonly string[] = [
77
"/Lotus/Upgrades/Mods/Immortal/AntivirusOneMod",
78
"/Lotus/Upgrades/Mods/Immortal/AntivirusTwoMod",
79
"/Lotus/Upgrades/Mods/Immortal/AntivirusThreeMod",
80
"/Lotus/Upgrades/Mods/Immortal/AntivirusFourMod",
81
"/Lotus/Upgrades/Mods/Immortal/AntivirusFiveMod",
82
"/Lotus/Upgrades/Mods/Immortal/AntivirusSixMod",
83
"/Lotus/Upgrades/Mods/Immortal/AntivirusSevenMod",
84
"/Lotus/Upgrades/Mods/Immortal/AntivirusEightMod"
85
];
86
87
export const getNemesisPasscodeModTypes = (nemesis: { fp: bigint; Faction: string }): string[] => {
88
const passcode = getNemesisPasscode(nemesis);
89
return nemesis.Faction == "FC_INFESTATION"
90
? passcode.map(i => antivirusMods[i])
91
: passcode.map(i => reqiuemMods[i]);
92
};
93
52
94
export const encodeNemesisGuess = (
53
95
symbol1: number,
54
96
result1: number,
@@ -79,6 +121,31 @@ export interface IKnifeResponse {
79
121
HasKnife?: boolean;
80
122
}
81
123
124
export const getKnifeUpgrade = (
125
inventory: TInventoryDatabaseDocument,
126
dataknifeUpgrades: string[],
127
type: string
128
): { ItemId: IOid; ItemType: string } => {
129
if (dataknifeUpgrades.indexOf(type) != -1) {
130
return {
131
ItemId: { $oid: "000000000000000000000000" },
132
ItemType: type
133
};
134
}
135
for (const upgradeId of dataknifeUpgrades) {
136
if (upgradeId.length == 24) {
137
const upgrade = inventory.Upgrades.id(upgradeId);
138
if (upgrade && upgrade.ItemType == type) {
139
return {
140
ItemId: { $oid: upgradeId },
141
ItemType: type
142
};
143
}
144
}
145
}
146
throw new Error(`${type} does not seem to be installed on parazon?!`);
147
};
148
82
149
export const consumeModCharge = (
83
150
response: IKnifeResponse,
84
151
inventory: TInventoryDatabaseDocument,