Nemesis cheats code and webUI adaption

Nemesis Henchmen Kills Multiplier

Nemesis Hint Progress Multiplier

Nemesis Weapon Fusion Multiplier

Nemesis Gain Extra Rank

Nemesis Always Correct

code fix

webUI updates

Live Heart Multiplier
This commit is contained in:
AlexisinGit 2025-08-30 16:18:58 +08:00
parent 31e121ab22
commit 90cb433f10
5 changed files with 140 additions and 18 deletions

View File

@ -18,7 +18,7 @@ import {
import { getJSONfromString } from "../../helpers/stringHelpers.ts"; import { getJSONfromString } from "../../helpers/stringHelpers.ts";
import type { TInventoryDatabaseDocument } from "../../models/inventoryModels/inventoryModel.ts"; import type { TInventoryDatabaseDocument } from "../../models/inventoryModels/inventoryModel.ts";
import { Loadout } from "../../models/inventoryModels/loadoutModel.ts"; import { Loadout } from "../../models/inventoryModels/loadoutModel.ts";
import { addMods, freeUpSlot, getInventory } from "../../services/inventoryService.ts"; import { addMods, freeUpSlot, getInventory, getAccountCheats } from "../../services/inventoryService.ts";
import { getAccountForRequest } from "../../services/loginService.ts"; import { getAccountForRequest } from "../../services/loginService.ts";
import { SRng } from "../../services/rngService.ts"; import { SRng } from "../../services/rngService.ts";
import type { IMongoDate, IOid } from "../../types/commonTypes.ts"; import type { IMongoDate, IOid } from "../../types/commonTypes.ts";
@ -39,6 +39,7 @@ import { Types } from "mongoose";
export const nemesisController: RequestHandler = async (req, res) => { export const nemesisController: RequestHandler = async (req, res) => {
const account = await getAccountForRequest(req); const account = await getAccountForRequest(req);
const accountCheats = await getAccountCheats(account._id.toString());
if ((req.query.mode as string) == "f") { if ((req.query.mode as string) == "f") {
const body = getJSONfromString<IValenceFusionRequest>(String(req.body)); const body = getJSONfromString<IValenceFusionRequest>(String(req.body));
const inventory = await getInventory(account._id.toString(), body.Category + " WeaponBin"); const inventory = await getInventory(account._id.toString(), body.Category + " WeaponBin");
@ -55,7 +56,8 @@ export const nemesisController: RequestHandler = async (req, res) => {
// Upgrade destination damage value // Upgrade destination damage value
const destDamage = 0.25 + (destFingerprint.buffs[0].Value / 0x3fffffff) * (0.6 - 0.25); const destDamage = 0.25 + (destFingerprint.buffs[0].Value / 0x3fffffff) * (0.6 - 0.25);
const sourceDamage = 0.25 + (sourceFingerprint.buffs[0].Value / 0x3fffffff) * (0.6 - 0.25); const sourceDamage = 0.25 + (sourceFingerprint.buffs[0].Value / 0x3fffffff) * (0.6 - 0.25);
let newDamage = Math.max(destDamage, sourceDamage) * 1.1; const WeaponFusionMultiplier = accountCheats.nemesisWeaponFusionMultiplier ?? 1;
let newDamage = Math.max(destDamage, sourceDamage) * 1.1 * WeaponFusionMultiplier;
if (newDamage >= 0.5794998) { if (newDamage >= 0.5794998) {
newDamage = 0.6; newDamage = 0.6;
} }
@ -82,14 +84,18 @@ export const nemesisController: RequestHandler = async (req, res) => {
let guessResult = 0; let guessResult = 0;
if (inventory.Nemesis!.Faction == "FC_INFESTATION") { if (inventory.Nemesis!.Faction == "FC_INFESTATION") {
for (let i = 0; i != 3; ++i) { for (let i = 0; i != 3; ++i) {
if (body.guess[i] == passcode[0]) { if (body.guess[i] == passcode[0] || accountCheats.nemesisAlwaysCorrect) {
guessResult = 1 + i; guessResult = 1 + i;
break; break;
} }
} }
} else { } else {
for (let i = 0; i != 3; ++i) { for (let i = 0; i != 3; ++i) {
if (body.guess[i] == passcode[i] || body.guess[i] == GUESS_WILDCARD) { if (
body.guess[i] == passcode[i] ||
body.guess[i] == GUESS_WILDCARD ||
accountCheats.nemesisAlwaysCorrect
) {
++guessResult; ++guessResult;
} }
} }
@ -100,6 +106,7 @@ export const nemesisController: RequestHandler = async (req, res) => {
account._id.toString(), account._id.toString(),
"Nemesis LoadOutPresets CurrentLoadOutIds DataKnives Upgrades RawUpgrades" "Nemesis LoadOutPresets CurrentLoadOutIds DataKnives Upgrades RawUpgrades"
); );
const body = getJSONfromString<INemesisRequiemRequest>(String(req.body)); const body = getJSONfromString<INemesisRequiemRequest>(String(req.body));
if (inventory.Nemesis!.Faction == "FC_INFESTATION") { if (inventory.Nemesis!.Faction == "FC_INFESTATION") {
const guess: number[] = [body.guess & 0xf, (body.guess >> 4) & 0xf, (body.guess >> 8) & 0xf]; const guess: number[] = [body.guess & 0xf, (body.guess >> 4) & 0xf, (body.guess >> 8) & 0xf];
@ -111,22 +118,27 @@ export const nemesisController: RequestHandler = async (req, res) => {
encodeNemesisGuess([ encodeNemesisGuess([
{ {
symbol: guess[0], symbol: guess[0],
result: result1 result: accountCheats.nemesisAlwaysCorrect ? GUESS_CORRECT : result1
}, },
{ {
symbol: guess[1], symbol: guess[1],
result: result2 result: accountCheats.nemesisAlwaysCorrect ? GUESS_CORRECT : result2
}, },
{ {
symbol: guess[2], symbol: guess[2],
result: result3 result: accountCheats.nemesisAlwaysCorrect ? GUESS_CORRECT : result3
} }
]) ])
); );
// Increase antivirus if correct antivirus mod is installed // Increase antivirus if correct antivirus mod is installed
const response: IKnifeResponse = {}; const response: IKnifeResponse = {};
if (result1 == GUESS_CORRECT || result2 == GUESS_CORRECT || result3 == GUESS_CORRECT) { if (
result1 == GUESS_CORRECT ||
result2 == GUESS_CORRECT ||
result3 == GUESS_CORRECT ||
accountCheats.nemesisAlwaysCorrect
) {
let antivirusGain = 5; let antivirusGain = 5;
const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!; const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
const dataknifeLoadout = loadout.DATAKNIFE.id( const dataknifeLoadout = loadout.DATAKNIFE.id(
@ -149,7 +161,8 @@ export const nemesisController: RequestHandler = async (req, res) => {
break; break;
} }
} }
inventory.Nemesis!.HenchmenKilled += antivirusGain; inventory.Nemesis!.HenchmenKilled +=
antivirusGain * (accountCheats.nemesisHenchmenKillsMultiplierInfestation ?? 1);
if (inventory.Nemesis!.HenchmenKilled >= 100) { if (inventory.Nemesis!.HenchmenKilled >= 100) {
inventory.Nemesis!.HenchmenKilled = 100; inventory.Nemesis!.HenchmenKilled = 100;
@ -192,10 +205,15 @@ export const nemesisController: RequestHandler = async (req, res) => {
]) ])
); );
} }
if (accountCheats.nemesisAlwaysCorrect) {
body.guess = GUESS_WILDCARD | (GUESS_WILDCARD << 4) | (GUESS_WILDCARD << 8);
}
// Evaluate guess // Evaluate guess
const correct = const correct =
body.guess == GUESS_WILDCARD || getNemesisPasscode(inventory.Nemesis!)[body.position] == body.guess; body.guess == GUESS_WILDCARD ||
getNemesisPasscode(inventory.Nemesis!)[body.position] == body.guess ||
accountCheats.nemesisAlwaysCorrect;
// Update entry // Update entry
const guess = decodeNemesisGuess( const guess = decodeNemesisGuess(
@ -232,9 +250,13 @@ export const nemesisController: RequestHandler = async (req, res) => {
} }
} else { } else {
// Guess was incorrect, increase rank // Guess was incorrect, increase rank
const nemesisExtraRank = Math.floor(Math.random() * ((inventory.nemesisGainExtraRank ?? 0) + 1));
response.RankIncrease = 1; response.RankIncrease = 1;
const manifest = getNemesisManifest(inventory.Nemesis!.manifest); const manifest = getNemesisManifest(inventory.Nemesis!.manifest);
inventory.Nemesis!.Rank = Math.min(inventory.Nemesis!.Rank + 1, manifest.systemIndexes.length - 1); inventory.Nemesis!.Rank = Math.min(
inventory.Nemesis!.Rank + 1 + nemesisExtraRank,
manifest.systemIndexes.length - 1
);
inventory.Nemesis!.InfNodes = getInfNodes(manifest, inventory.Nemesis!.Rank); inventory.Nemesis!.InfNodes = getInfNodes(manifest, inventory.Nemesis!.Rank);
} }
await inventory.save(); await inventory.save();

View File

@ -26,7 +26,8 @@ import type {
INemesisWeaponTargetFingerprint, INemesisWeaponTargetFingerprint,
INemesisPetTargetFingerprint, INemesisPetTargetFingerprint,
IDialogueDatabase, IDialogueDatabase,
IKubrowPetPrintClient IKubrowPetPrintClient,
IAccountCheats
} from "../types/inventoryTypes/inventoryTypes.ts"; } from "../types/inventoryTypes/inventoryTypes.ts";
import { InventorySlot, equipmentKeys } from "../types/inventoryTypes/inventoryTypes.ts"; import { InventorySlot, equipmentKeys } from "../types/inventoryTypes/inventoryTypes.ts";
import type { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate.ts"; import type { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate.ts";
@ -266,6 +267,13 @@ export const getInventory = async (
return inventory; return inventory;
}; };
export const getAccountCheats = async (accountOwnerId: string): Promise<Partial<IAccountCheats>> => {
const cheatProperties = Object.keys({} as IAccountCheats) as Array<keyof IAccountCheats>;
const inventoryWithCheats = await getInventory(accountOwnerId, cheatProperties.join(" "));
return inventoryWithCheats;
};
export const productCategoryToInventoryBin = (productCategory: string): InventorySlot | undefined => { export const productCategoryToInventoryBin = (productCategory: string): InventorySlot | undefined => {
switch (productCategory) { switch (productCategory) {
case "Suits": case "Suits":

View File

@ -35,6 +35,7 @@ import {
addStanding, addStanding,
applyClientEquipmentUpdates, applyClientEquipmentUpdates,
combineInventoryChanges, combineInventoryChanges,
getAccountCheats,
getDialogue, getDialogue,
giveNemesisPetRecipe, giveNemesisPetRecipe,
giveNemesisWeaponRecipe, giveNemesisWeaponRecipe,
@ -201,10 +202,33 @@ export const addMissionInventoryUpdates = async (
inventory.NemesisAbandonedRewards = inventoryUpdates.RewardInfo.NemesisAbandonedRewards; inventory.NemesisAbandonedRewards = inventoryUpdates.RewardInfo.NemesisAbandonedRewards;
} }
if (inventoryUpdates.RewardInfo.NemesisHenchmenKills && inventory.Nemesis) { if (inventoryUpdates.RewardInfo.NemesisHenchmenKills && inventory.Nemesis) {
inventory.Nemesis.HenchmenKilled += inventoryUpdates.RewardInfo.NemesisHenchmenKills; let NemesisHenchmenKillsMultiplier = 1;
switch (inventory.Nemesis.Faction) {
case "FC_GRINEER":
NemesisHenchmenKillsMultiplier = inventory.nemesisHenchmenKillsMultiplierGrineer ?? 1;
break;
case "FC_CORPUS":
NemesisHenchmenKillsMultiplier = inventory.nemesisHenchmenKillsMultiplierCorpus ?? 1;
break;
case "FC_INFESTATION":
//antivirus progess is controlled in nemesisController
break;
}
inventory.Nemesis.HenchmenKilled +=
inventoryUpdates.RewardInfo.NemesisHenchmenKills * NemesisHenchmenKillsMultiplier;
} }
if (inventoryUpdates.RewardInfo.NemesisHintProgress && inventory.Nemesis) { if (inventoryUpdates.RewardInfo.NemesisHintProgress && inventory.Nemesis) {
inventory.Nemesis.HintProgress += inventoryUpdates.RewardInfo.NemesisHintProgress; let NemesisHintProgressMultiplier = 1;
switch (inventory.Nemesis.Faction) {
case "FC_GRINEER":
NemesisHintProgressMultiplier = inventory.nemesisHintProgressMultiplierGrineer ?? 1;
break;
case "FC_CORPUS":
NemesisHintProgressMultiplier = inventory.nemesisHintProgressMultiplierCorpus ?? 1;
break;
}
inventory.Nemesis.HintProgress +=
inventoryUpdates.RewardInfo.NemesisHintProgress * NemesisHintProgressMultiplier;
if (inventory.Nemesis.Faction != "FC_INFESTATION" && inventory.Nemesis.Hints.length != 3) { if (inventory.Nemesis.Faction != "FC_INFESTATION" && inventory.Nemesis.Hints.length != 3) {
const progressNeeded = [35, 60, 100][inventory.Nemesis.Hints.length]; const progressNeeded = [35, 60, 100][inventory.Nemesis.Hints.length];
if (inventory.Nemesis.HintProgress >= progressNeeded) { if (inventory.Nemesis.HintProgress >= progressNeeded) {
@ -891,10 +915,11 @@ export const addMissionInventoryUpdates = async (
att.push(rotBReward); att.push(rotBReward);
if (value.killed) { if (value.killed) {
const tokenMultiplier = Math.max(1, inventory.nemesisExtraWeaponOnKill ?? 1);
countedAtt = [ countedAtt = [
{ {
ItemType: "/Lotus/Types/Items/MiscItems/CodaWeaponBucks", ItemType: "/Lotus/Types/Items/MiscItems/CodaWeaponBucks",
ItemCount: getKillTokenRewardCount(inventory.Nemesis.fp) ItemCount: getKillTokenRewardCount(inventory.Nemesis.fp) * tokenMultiplier
} }
]; ];
addMiscItems(inventory, countedAtt); addMiscItems(inventory, countedAtt);

View File

@ -787,6 +787,68 @@
<input class="form-check-input" type="checkbox" id="finishInvasionsInOneMission" /> <input class="form-check-input" type="checkbox" id="finishInvasionsInOneMission" />
<label class="form-check-label" for="finishInvasionsInOneMission" data-loc="cheats_finishInvasionsInOneMission"></label> <label class="form-check-label" for="finishInvasionsInOneMission" data-loc="cheats_finishInvasionsInOneMission"></label>
</div> </div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="nemesisAlwaysCorrect" />
<label class="form-check-label" for="nemesisAlwaysCorrect" data-loc="cheats_nemesisAlwaysCorrect"></label>
</div>
<form class="form-group mt-2">
<label class="form-label" for="nemesisHenchmenKillsMultiplierGrineer" data-loc="cheats_nemesisHenchmenKillsMultiplierGrineer"></label>
<div class="input-group">
<input class="form-control" id="nemesisHenchmenKillsMultiplierGrineer" type="number" min="-1" max="65535" data-default="1" />
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
</div>
</form>
<form class="form-group mt-2">
<label class="form-label" for="nemesisHenchmenKillsMultiplierCorpus" data-loc="cheats_nemesisHenchmenKillsMultiplierCorpus"></label>
<div class="input-group">
<input class="form-control" id="nemesisHenchmenKillsMultiplierCorpus" type="number" min="-1" max="65535" data-default="1" />
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
</div>
</form>
<form class="form-group mt-2">
<label class="form-label" for="nemesisHenchmenKillsMultiplierInfestation" data-loc="cheats_nemesisHenchmenKillsMultiplierInfestation"></label>
<div class="input-group">
<input class="form-control" id="nemesisHenchmenKillsMultiplierInfestation" type="number" min="-1" max="65535" data-default="1" />
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
</div>
</form>
<form class="form-group mt-2">
<label class="form-label" for="nemesisHintProgressMultiplierGrineer" data-loc="cheats_nemesisHintProgressMultiplierGrineer"></label>
<div class="input-group">
<input class="form-control" id="nemesisHintProgressMultiplierGrineer" type="number" min="-1" max="65535" data-default="1" />
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
</div>
</form>
<form class="form-group mt-2">
<label class="form-label" for="nemesisHintProgressMultiplierCorpus" data-loc="cheats_nemesisHintProgressMultiplierCorpus"></label>
<div class="input-group">
<input class="form-control" id="nemesisHintProgressMultiplierCorpus" type="number" min="-1" max="65535" data-default="1" />
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
</div>
</form>
<form class="form-group mt-2">
<label class="form-label" for="nemesisWeaponFusionMultiplier" data-loc="cheats_nemesisWeaponFusionMultiplier"></label>
<div class="input-group">
<input class="form-control" id="nemesisWeaponFusionMultiplier" type="number" min="-1" max="65535" data-default="1" />
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
</div>
</form>
<form class="form-group mt-2">
<label class="form-label" for="nemesisGainExtraRank" data-loc="cheats_nemesisGainExtraRank"></label>
<abbr data-loc-info="cheats_nemesisGainExtraRank_information"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
<div class="input-group">
<input class="form-control" id="nemesisGainExtraRank" type="number" min="0" max="65535" data-default="0" />
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
</div>
</form>
<form class="form-group mt-2">
<label class="form-label" for="nemesisExtraWeaponOnKill" data-loc="cheats_nemesisExtraWeaponOnKill"></label>
<abbr data-loc-info="cheats_nemesisExtraWeaponOnKill_information"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
<div class="input-group">
<input class="form-control" id="nemesisExtraWeaponOnKill" type="number" min="0" max="65535" data-default="0" />
<button class="btn btn-secondary" type="button" data-loc="cheats_save"></button>
</div>
</form>
<div class="mt-2 mb-2 d-flex flex-wrap gap-2"> <div class="mt-2 mb-2 d-flex flex-wrap gap-2">
<button class="btn btn-primary" onclick="debounce(doUnlockAllMissions);" data-loc="cheats_unlockAllMissions"></button> <button class="btn btn-primary" onclick="debounce(doUnlockAllMissions);" data-loc="cheats_unlockAllMissions"></button>
<button class="btn btn-primary" onclick="debounce(markAllAsRead);" data-loc="cheats_markAllAsRead"></button> <button class="btn btn-primary" onclick="debounce(markAllAsRead);" data-loc="cheats_markAllAsRead"></button>

View File

@ -1502,7 +1502,11 @@ function updateInventory() {
}); });
for (const elm of accountCheats) { for (const elm of accountCheats) {
elm.checked = !!data[elm.id]; if (elm.type === "checkbox") {
elm.checked = !!data[elm.id];
} else if (elm.type === "number" || elm.type === "text") {
elm.value = data[elm.id] !== undefined ? data[elm.id] : elm.getAttribute("data-default") || "";
}
} }
}); });
}); });
@ -2337,15 +2341,16 @@ function doIntrinsicsUnlockAll() {
}); });
} }
document.querySelectorAll("#account-cheats input[type=checkbox]").forEach(elm => { document.querySelectorAll("#account-cheats input[type=checkbox], #account-cheats input[type=number]").forEach(elm => {
elm.onchange = function () { elm.onchange = function () {
revalidateAuthz().then(() => { revalidateAuthz().then(() => {
const value = elm.type === "checkbox" ? elm.checked : elm.value;
$.post({ $.post({
url: "/custom/setAccountCheat?" + window.authz /*+ "&wsid=" + wsid*/, url: "/custom/setAccountCheat?" + window.authz /*+ "&wsid=" + wsid*/,
contentType: "application/json", contentType: "application/json",
data: JSON.stringify({ data: JSON.stringify({
key: elm.id, key: elm.id,
value: elm.checked value: value
}) })
}); });
}); });