diff --git a/src/controllers/api/nemesisController.ts b/src/controllers/api/nemesisController.ts index 1efd0023..8da8fe4d 100644 --- a/src/controllers/api/nemesisController.ts +++ b/src/controllers/api/nemesisController.ts @@ -1,12 +1,17 @@ import { version_compare } from "@/src/helpers/inventoryHelpers"; import { consumeModCharge, + decodeNemesisGuess, encodeNemesisGuess, getInfNodes, getKnifeUpgrade, getNemesisManifest, getNemesisPasscode, getNemesisPasscodeModTypes, + GUESS_CORRECT, + GUESS_INCORRECT, + GUESS_NEUTRAL, + GUESS_NONE, GUESS_WILDCARD, IKnifeResponse } from "@/src/helpers/nemesisHelpers"; @@ -98,18 +103,29 @@ export const nemesisController: RequestHandler = async (req, res) => { if (inventory.Nemesis!.Faction == "FC_INFESTATION") { const guess: number[] = [body.guess & 0xf, (body.guess >> 4) & 0xf, (body.guess >> 8) & 0xf]; const passcode = getNemesisPasscode(inventory.Nemesis!)[0]; - - // Add to GuessHistory - const result1 = passcode == guess[0] ? 0 : 1; - const result2 = passcode == guess[1] ? 0 : 1; - const result3 = passcode == guess[2] ? 0 : 1; + const result1 = passcode == guess[0] ? GUESS_CORRECT : GUESS_INCORRECT; + const result2 = passcode == guess[1] ? GUESS_CORRECT : GUESS_INCORRECT; + const result3 = passcode == guess[2] ? GUESS_CORRECT : GUESS_INCORRECT; inventory.Nemesis!.GuessHistory.push( - encodeNemesisGuess(guess[0], result1, guess[1], result2, guess[2], result3) + encodeNemesisGuess([ + { + symbol: guess[0], + result: result1 + }, + { + symbol: guess[1], + result: result2 + }, + { + symbol: guess[2], + result: result3 + } + ]) ); // Increase antivirus if correct antivirus mod is installed const response: IKnifeResponse = {}; - if (result1 == 0 || result2 == 0 || result3 == 0) { + if (result1 == GUESS_CORRECT || result2 == GUESS_CORRECT || result3 == GUESS_CORRECT) { let antivirusGain = 5; const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!; const dataknifeLoadout = loadout.DATAKNIFE.id(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid); @@ -150,19 +166,47 @@ export const nemesisController: RequestHandler = async (req, res) => { await inventory.save(); res.json(response); } else { - let RankIncrease: number | undefined; - if (body.guess != GUESS_WILDCARD) { - const passcode = getNemesisPasscode(inventory.Nemesis!); - if (passcode[body.position] != body.guess) { - const manifest = getNemesisManifest(inventory.Nemesis!.manifest); - if (inventory.Nemesis!.Rank + 1 < manifest.systemIndexes.length) { - inventory.Nemesis!.Rank += 1; - RankIncrease = 1; - } - inventory.Nemesis!.InfNodes = getInfNodes(manifest, inventory.Nemesis!.Rank); - await inventory.save(); - } + // For first guess, create a new entry. + if (body.position == 0) { + inventory.Nemesis!.GuessHistory.push( + encodeNemesisGuess([ + { + symbol: GUESS_NONE, + result: GUESS_NEUTRAL + }, + { + symbol: GUESS_NONE, + result: GUESS_NEUTRAL + }, + { + symbol: GUESS_NONE, + result: GUESS_NEUTRAL + } + ]) + ); } + + // Evaluate guess + const correct = + body.guess == GUESS_WILDCARD || getNemesisPasscode(inventory.Nemesis!)[body.position] == body.guess; + + // Update entry + const guess = decodeNemesisGuess( + inventory.Nemesis!.GuessHistory[inventory.Nemesis!.GuessHistory.length - 1] + ); + guess[body.position].symbol = body.guess; + guess[body.position].result = correct ? GUESS_CORRECT : GUESS_INCORRECT; + inventory.Nemesis!.GuessHistory[inventory.Nemesis!.GuessHistory.length - 1] = encodeNemesisGuess(guess); + + // Increase rank if incorrect + let RankIncrease: number | undefined; + if (!correct) { + RankIncrease = 1; + const manifest = getNemesisManifest(inventory.Nemesis!.manifest); + inventory.Nemesis!.Rank = Math.min(inventory.Nemesis!.Rank + 1, manifest.systemIndexes.length - 1); + inventory.Nemesis!.InfNodes = getInfNodes(manifest, inventory.Nemesis!.Rank); + } + await inventory.save(); res.json({ RankIncrease }); } } else if ((req.query.mode as string) == "rs") { diff --git a/src/helpers/nemesisHelpers.ts b/src/helpers/nemesisHelpers.ts index 0c2eebbe..8d0d8527 100644 --- a/src/helpers/nemesisHelpers.ts +++ b/src/helpers/nemesisHelpers.ts @@ -237,7 +237,7 @@ export const getNemesisPasscode = (nemesis: { fp: bigint; Faction: TNemesisFacti return passcode; }; -const reqiuemMods: readonly string[] = [ +const requiemMods: readonly string[] = [ "/Lotus/Upgrades/Mods/Immortal/ImmortalOneMod", "/Lotus/Upgrades/Mods/Immortal/ImmortalTwoMod", "/Lotus/Upgrades/Mods/Immortal/ImmortalThreeMod", @@ -263,32 +263,51 @@ export const getNemesisPasscodeModTypes = (nemesis: { fp: bigint; Faction: TNeme const passcode = getNemesisPasscode(nemesis); return nemesis.Faction == "FC_INFESTATION" ? passcode.map(i => antivirusMods[i]) - : passcode.map(i => reqiuemMods[i]); + : passcode.map(i => requiemMods[i]); }; +// Symbols; 0-7 are the normal requiem mods. export const GUESS_NONE = 8; export const GUESS_WILDCARD = 9; -export const encodeNemesisGuess = ( - symbol1: number, - result1: number, - symbol2: number, - result2: number, - symbol3: number, - result3: number -): number => { +// Results; there are 3, 4, 5 as well which are more muted versions but unused afaik. +export const GUESS_NEUTRAL = 0; +export const GUESS_INCORRECT = 1; +export const GUESS_CORRECT = 2; + +interface NemesisPositionGuess { + symbol: number; + result: number; +} + +export type NemesisGuess = [NemesisPositionGuess, NemesisPositionGuess, NemesisPositionGuess]; + +export const encodeNemesisGuess = (guess: NemesisGuess): number => { return ( - (symbol1 & 0xf) | - ((result1 & 3) << 12) | - ((symbol2 << 4) & 0xff) | - ((result2 << 14) & 0xffff) | - ((symbol3 & 0xf) << 8) | - ((result3 & 3) << 16) + (guess[0].symbol & 0xf) | + ((guess[0].result & 3) << 12) | + ((guess[1].symbol << 4) & 0xff) | + ((guess[1].result << 14) & 0xffff) | + ((guess[2].symbol & 0xf) << 8) | + ((guess[2].result & 3) << 16) ); }; -export const decodeNemesisGuess = (val: number): number[] => { - return [val & 0xf, (val >> 12) & 3, (val & 0xff) >> 4, (val & 0xffff) >> 14, (val >> 8) & 0xf, (val >> 16) & 3]; +export const decodeNemesisGuess = (val: number): NemesisGuess => { + return [ + { + symbol: val & 0xf, + result: (val >> 12) & 3 + }, + { + symbol: (val & 0xff) >> 4, + result: (val & 0xffff) >> 14 + }, + { + symbol: (val >> 8) & 0xf, + result: (val >> 16) & 3 + } + ]; }; export interface IKnifeResponse { diff --git a/src/services/missionInventoryUpdateService.ts b/src/services/missionInventoryUpdateService.ts index 9c7dc93a..21aff3b1 100644 --- a/src/services/missionInventoryUpdateService.ts +++ b/src/services/missionInventoryUpdateService.ts @@ -1182,14 +1182,12 @@ export const addMissionRewards = async ( if (nodeIndex !== -1) inventory.Nemesis.InfNodes.splice(nodeIndex, 1); if (inventory.Nemesis.InfNodes.length <= 0) { + const manifest = getNemesisManifest(inventory.Nemesis.manifest); if (inventory.Nemesis.Faction != "FC_INFESTATION") { - inventory.Nemesis.Rank = Math.min(inventory.Nemesis.Rank + 1, 4); + inventory.Nemesis.Rank = Math.min(inventory.Nemesis.Rank + 1, manifest.systemIndexes.length - 1); inventoryChanges.Nemesis.Rank = inventory.Nemesis.Rank; } - inventory.Nemesis.InfNodes = getInfNodes( - getNemesisManifest(inventory.Nemesis.manifest), - inventory.Nemesis.Rank - ); + inventory.Nemesis.InfNodes = getInfNodes(manifest, inventory.Nemesis.Rank); } if (inventory.Nemesis.Faction == "FC_INFESTATION") {