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: classic lich guess history (#2129)

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

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

代码差异

3 个文件 +102 -41
Modified src/controllers/api/nemesisController.ts +62 -18
@@ -1,12 +1,17 @@
1 1 import { version_compare } from "@/src/helpers/inventoryHelpers";
2 2 import {
3 3 consumeModCharge,
4 decodeNemesisGuess,
4 5 encodeNemesisGuess,
5 6 getInfNodes,
6 7 getKnifeUpgrade,
7 8 getNemesisManifest,
8 9 getNemesisPasscode,
9 10 getNemesisPasscodeModTypes,
11 GUESS_CORRECT,
12 GUESS_INCORRECT,
13 GUESS_NEUTRAL,
14 GUESS_NONE,
10 15 GUESS_WILDCARD,
11 16 IKnifeResponse
12 17 } from "@/src/helpers/nemesisHelpers";
@@ -98,18 +103,29 @@ export const nemesisController: RequestHandler = async (req, res) => {
98 103 if (inventory.Nemesis!.Faction == "FC_INFESTATION") {
99 104 const guess: number[] = [body.guess & 0xf, (body.guess >> 4) & 0xf, (body.guess >> 8) & 0xf];
100 105 const passcode = getNemesisPasscode(inventory.Nemesis!)[0];
101
102 // Add to GuessHistory
103 const result1 = passcode == guess[0] ? 0 : 1;
104 const result2 = passcode == guess[1] ? 0 : 1;
105 const result3 = passcode == guess[2] ? 0 : 1;
106 const result1 = passcode == guess[0] ? GUESS_CORRECT : GUESS_INCORRECT;
107 const result2 = passcode == guess[1] ? GUESS_CORRECT : GUESS_INCORRECT;
108 const result3 = passcode == guess[2] ? GUESS_CORRECT : GUESS_INCORRECT;
106 109 inventory.Nemesis!.GuessHistory.push(
107 encodeNemesisGuess(guess[0], result1, guess[1], result2, guess[2], result3)
110 encodeNemesisGuess([
111 {
112 symbol: guess[0],
113 result: result1
114 },
115 {
116 symbol: guess[1],
117 result: result2
118 },
119 {
120 symbol: guess[2],
121 result: result3
122 }
123 ])
108 124 );
109 125
110 126 // Increase antivirus if correct antivirus mod is installed
111 127 const response: IKnifeResponse = {};
112 if (result1 == 0 || result2 == 0 || result3 == 0) {
128 if (result1 == GUESS_CORRECT || result2 == GUESS_CORRECT || result3 == GUESS_CORRECT) {
113 129 let antivirusGain = 5;
114 130 const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
115 131 const dataknifeLoadout = loadout.DATAKNIFE.id(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid);
@@ -150,19 +166,47 @@ export const nemesisController: RequestHandler = async (req, res) => {
150 166 await inventory.save();
151 167 res.json(response);
152 168 } else {
169 // For first guess, create a new entry.
170 if (body.position == 0) {
171 inventory.Nemesis!.GuessHistory.push(
172 encodeNemesisGuess([
173 {
174 symbol: GUESS_NONE,
175 result: GUESS_NEUTRAL
176 },
177 {
178 symbol: GUESS_NONE,
179 result: GUESS_NEUTRAL
180 },
181 {
182 symbol: GUESS_NONE,
183 result: GUESS_NEUTRAL
184 }
185 ])
186 );
187 }
188
189 // Evaluate guess
190 const correct =
191 body.guess == GUESS_WILDCARD || getNemesisPasscode(inventory.Nemesis!)[body.position] == body.guess;
192
193 // Update entry
194 const guess = decodeNemesisGuess(
195 inventory.Nemesis!.GuessHistory[inventory.Nemesis!.GuessHistory.length - 1]
196 );
197 guess[body.position].symbol = body.guess;
198 guess[body.position].result = correct ? GUESS_CORRECT : GUESS_INCORRECT;
199 inventory.Nemesis!.GuessHistory[inventory.Nemesis!.GuessHistory.length - 1] = encodeNemesisGuess(guess);
200
201 // Increase rank if incorrect
153 202 let RankIncrease: number | undefined;
154 if (body.guess != GUESS_WILDCARD) {
155 const passcode = getNemesisPasscode(inventory.Nemesis!);
156 if (passcode[body.position] != body.guess) {
157 const manifest = getNemesisManifest(inventory.Nemesis!.manifest);
158 if (inventory.Nemesis!.Rank + 1 < manifest.systemIndexes.length) {
159 inventory.Nemesis!.Rank += 1;
160 RankIncrease = 1;
161 }
162 inventory.Nemesis!.InfNodes = getInfNodes(manifest, inventory.Nemesis!.Rank);
163 await inventory.save();
164 }
203 if (!correct) {
204 RankIncrease = 1;
205 const manifest = getNemesisManifest(inventory.Nemesis!.manifest);
206 inventory.Nemesis!.Rank = Math.min(inventory.Nemesis!.Rank + 1, manifest.systemIndexes.length - 1);
207 inventory.Nemesis!.InfNodes = getInfNodes(manifest, inventory.Nemesis!.Rank);
165 208 }
209 await inventory.save();
166 210 res.json({ RankIncrease });
167 211 }
168 212 } else if ((req.query.mode as string) == "rs") {
Modified src/helpers/nemesisHelpers.ts +37 -18
@@ -237,7 +237,7 @@ export const getNemesisPasscode = (nemesis: { fp: bigint; Faction: TNemesisFacti
237 237 return passcode;
238 238 };
239 239
240 const reqiuemMods: readonly string[] = [
240 const requiemMods: readonly string[] = [
241 241 "/Lotus/Upgrades/Mods/Immortal/ImmortalOneMod",
242 242 "/Lotus/Upgrades/Mods/Immortal/ImmortalTwoMod",
243 243 "/Lotus/Upgrades/Mods/Immortal/ImmortalThreeMod",
@@ -263,32 +263,51 @@ export const getNemesisPasscodeModTypes = (nemesis: { fp: bigint; Faction: TNeme
263 263 const passcode = getNemesisPasscode(nemesis);
264 264 return nemesis.Faction == "FC_INFESTATION"
265 265 ? passcode.map(i => antivirusMods[i])
266 : passcode.map(i => reqiuemMods[i]);
266 : passcode.map(i => requiemMods[i]);
267 267 };
268 268
269 // Symbols; 0-7 are the normal requiem mods.
269 270 export const GUESS_NONE = 8;
270 271 export const GUESS_WILDCARD = 9;
271 272
272 export const encodeNemesisGuess = (
273 symbol1: number,
274 result1: number,
275 symbol2: number,
276 result2: number,
277 symbol3: number,
278 result3: number
279 ): number => {
273 // Results; there are 3, 4, 5 as well which are more muted versions but unused afaik.
274 export const GUESS_NEUTRAL = 0;
275 export const GUESS_INCORRECT = 1;
276 export const GUESS_CORRECT = 2;
277
278 interface NemesisPositionGuess {
279 symbol: number;
280 result: number;
281 }
282
283 export type NemesisGuess = [NemesisPositionGuess, NemesisPositionGuess, NemesisPositionGuess];
284
285 export const encodeNemesisGuess = (guess: NemesisGuess): number => {
280 286 return (
281 (symbol1 & 0xf) |
282 ((result1 & 3) << 12) |
283 ((symbol2 << 4) & 0xff) |
284 ((result2 << 14) & 0xffff) |
285 ((symbol3 & 0xf) << 8) |
286 ((result3 & 3) << 16)
287 (guess[0].symbol & 0xf) |
288 ((guess[0].result & 3) << 12) |
289 ((guess[1].symbol << 4) & 0xff) |
290 ((guess[1].result << 14) & 0xffff) |
291 ((guess[2].symbol & 0xf) << 8) |
292 ((guess[2].result & 3) << 16)
287 293 );
288 294 };
289 295
290 export const decodeNemesisGuess = (val: number): number[] => {
291 return [val & 0xf, (val >> 12) & 3, (val & 0xff) >> 4, (val & 0xffff) >> 14, (val >> 8) & 0xf, (val >> 16) & 3];
296 export const decodeNemesisGuess = (val: number): NemesisGuess => {
297 return [
298 {
299 symbol: val & 0xf,
300 result: (val >> 12) & 3
301 },
302 {
303 symbol: (val & 0xff) >> 4,
304 result: (val & 0xffff) >> 14
305 },
306 {
307 symbol: (val >> 8) & 0xf,
308 result: (val >> 16) & 3
309 }
310 ];
292 311 };
293 312
294 313 export interface IKnifeResponse {
Modified src/services/missionInventoryUpdateService.ts +3 -5
@@ -1182,14 +1182,12 @@ export const addMissionRewards = async (
1182 1182 if (nodeIndex !== -1) inventory.Nemesis.InfNodes.splice(nodeIndex, 1);
1183 1183
1184 1184 if (inventory.Nemesis.InfNodes.length <= 0) {
1185 const manifest = getNemesisManifest(inventory.Nemesis.manifest);
1185 1186 if (inventory.Nemesis.Faction != "FC_INFESTATION") {
1186 inventory.Nemesis.Rank = Math.min(inventory.Nemesis.Rank + 1, 4);
1187 inventory.Nemesis.Rank = Math.min(inventory.Nemesis.Rank + 1, manifest.systemIndexes.length - 1);
1187 1188 inventoryChanges.Nemesis.Rank = inventory.Nemesis.Rank;
1188 1189 }
1189 inventory.Nemesis.InfNodes = getInfNodes(
1190 getNemesisManifest(inventory.Nemesis.manifest),
1191 inventory.Nemesis.Rank
1192 );
1190 inventory.Nemesis.InfNodes = getInfNodes(manifest, inventory.Nemesis.Rank);
1193 1191 }
1194 1192
1195 1193 if (inventory.Nemesis.Faction == "FC_INFESTATION") {