forked from OpenWF/SpaceNinjaServer
		
	feat: weaken nemesis (#1893)
Closes #1885 Reviewed-on: OpenWF/SpaceNinjaServer#1893 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									1e8f2fc766
								
							
						
					
					
						commit
						88d00eaaa1
					
				@ -2,9 +2,12 @@ import {
 | 
			
		||||
    consumeModCharge,
 | 
			
		||||
    encodeNemesisGuess,
 | 
			
		||||
    getInfNodes,
 | 
			
		||||
    getKnifeUpgrade,
 | 
			
		||||
    getNemesisPasscode,
 | 
			
		||||
    getNemesisPasscodeModTypes,
 | 
			
		||||
    getWeaponsForManifest,
 | 
			
		||||
    IKnifeResponse
 | 
			
		||||
    IKnifeResponse,
 | 
			
		||||
    showdownNodes
 | 
			
		||||
} from "@/src/helpers/nemesisHelpers";
 | 
			
		||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
			
		||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
 | 
			
		||||
@ -15,6 +18,8 @@ import { IMongoDate, IOid } from "@/src/types/commonTypes";
 | 
			
		||||
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
			
		||||
import {
 | 
			
		||||
    IInnateDamageFingerprint,
 | 
			
		||||
    IInventoryClient,
 | 
			
		||||
    INemesisClient,
 | 
			
		||||
    InventorySlot,
 | 
			
		||||
    IUpgradeClient,
 | 
			
		||||
    IWeaponSkinClient,
 | 
			
		||||
@ -100,13 +105,14 @@ export const nemesisController: RequestHandler = async (req, res) => {
 | 
			
		||||
                encodeNemesisGuess(guess[0], result1, guess[1], result2, guess[2], result3)
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Increase antivirus
 | 
			
		||||
            // Increase antivirus if correct antivirus mod is installed
 | 
			
		||||
            const response: IKnifeResponse = {};
 | 
			
		||||
            if (result1 == 0 || result2 == 0 || result3 == 0) {
 | 
			
		||||
                let antivirusGain = 5;
 | 
			
		||||
                const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
 | 
			
		||||
                const dataknifeLoadout = loadout.DATAKNIFE.id(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid);
 | 
			
		||||
                const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
 | 
			
		||||
                const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
 | 
			
		||||
            const response: IKnifeResponse = {};
 | 
			
		||||
                for (const upgrade of body.knife!.AttachedUpgrades) {
 | 
			
		||||
                    switch (upgrade.ItemType) {
 | 
			
		||||
                        case "/Lotus/Upgrades/Mods/DataSpike/Potency/GainAntivirusAndSpeedOnUseMod":
 | 
			
		||||
@ -132,18 +138,12 @@ export const nemesisController: RequestHandler = async (req, res) => {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                inventory.Nemesis!.HenchmenKilled += antivirusGain;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (inventory.Nemesis!.HenchmenKilled >= 100) {
 | 
			
		||||
                inventory.Nemesis!.HenchmenKilled = 100;
 | 
			
		||||
                inventory.Nemesis!.InfNodes = [
 | 
			
		||||
                    {
 | 
			
		||||
                        Node: "CrewBattleNode559",
 | 
			
		||||
                        Influence: 1
 | 
			
		||||
            }
 | 
			
		||||
                ];
 | 
			
		||||
                inventory.Nemesis!.Weakened = true;
 | 
			
		||||
            } else {
 | 
			
		||||
            inventory.Nemesis!.InfNodes = getInfNodes("FC_INFESTATION", 0);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await inventory.save();
 | 
			
		||||
            res.json(response);
 | 
			
		||||
@ -213,6 +213,38 @@ export const nemesisController: RequestHandler = async (req, res) => {
 | 
			
		||||
        res.json({
 | 
			
		||||
            target: inventory.toJSON().Nemesis
 | 
			
		||||
        });
 | 
			
		||||
    } else if ((req.query.mode as string) == "w") {
 | 
			
		||||
        const inventory = await getInventory(
 | 
			
		||||
            accountId,
 | 
			
		||||
            "Nemesis LoadOutPresets CurrentLoadOutIds DataKnives Upgrades RawUpgrades"
 | 
			
		||||
        );
 | 
			
		||||
        //const body = getJSONfromString<INemesisWeakenRequest>(String(req.body));
 | 
			
		||||
 | 
			
		||||
        inventory.Nemesis!.InfNodes = [
 | 
			
		||||
            {
 | 
			
		||||
                Node: showdownNodes[inventory.Nemesis!.Faction],
 | 
			
		||||
                Influence: 1
 | 
			
		||||
            }
 | 
			
		||||
        ];
 | 
			
		||||
        inventory.Nemesis!.Weakened = true;
 | 
			
		||||
 | 
			
		||||
        const response: IKnifeResponse & { target: INemesisClient } = {
 | 
			
		||||
            target: inventory.toJSON<IInventoryClient>().Nemesis!
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // Consume charge of the correct requiem mod(s)
 | 
			
		||||
        const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
 | 
			
		||||
        const dataknifeLoadout = loadout.DATAKNIFE.id(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid);
 | 
			
		||||
        const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
 | 
			
		||||
        const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
 | 
			
		||||
        const modTypes = getNemesisPasscodeModTypes(inventory.Nemesis!);
 | 
			
		||||
        for (const modType of modTypes) {
 | 
			
		||||
            const upgrade = getKnifeUpgrade(inventory, dataknifeUpgrades, modType);
 | 
			
		||||
            consumeModCharge(response, inventory, upgrade, dataknifeUpgrades);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await inventory.save();
 | 
			
		||||
        res.json(response);
 | 
			
		||||
    } else {
 | 
			
		||||
        logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
 | 
			
		||||
        throw new Error(`unknown nemesis mode: ${String(req.query.mode)}`);
 | 
			
		||||
@ -264,12 +296,19 @@ interface INemesisRequiemRequest {
 | 
			
		||||
    guess: number; // grn/crp: 4 bits | coda: 3x 4 bits
 | 
			
		||||
    position: number; // grn/crp: 0-2 | coda: 0
 | 
			
		||||
    // knife field provided for coda only
 | 
			
		||||
    knife?: {
 | 
			
		||||
    knife?: IKnife;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// interface INemesisWeakenRequest {
 | 
			
		||||
//     target: INemesisClient;
 | 
			
		||||
//     knife: IKnife;
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
interface IKnife {
 | 
			
		||||
    Item: IEquipmentClient;
 | 
			
		||||
    Skins: IWeaponSkinClient[];
 | 
			
		||||
    ModSlot: number;
 | 
			
		||||
    CustSlot: number;
 | 
			
		||||
    AttachedUpgrades: IUpgradeClient[];
 | 
			
		||||
    HiddenWhenHolstered: boolean;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -38,17 +38,59 @@ const systemIndexes: Record<string, number[]> = {
 | 
			
		||||
    FC_INFESTATION: [23]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const showdownNodes: Record<string, string> = {
 | 
			
		||||
    FC_GRINEER: "CrewBattleNode557",
 | 
			
		||||
    FC_CORPUS: "CrewBattleNode558",
 | 
			
		||||
    FC_INFESTATION: "CrewBattleNode559"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Get a parazon 'passcode' based on the nemesis fingerprint so it's always the same for the same nemesis.
 | 
			
		||||
export const getNemesisPasscode = (nemesis: { fp: bigint; Faction: string }): number[] => {
 | 
			
		||||
    const rng = new SRng(nemesis.fp);
 | 
			
		||||
    const passcode = [rng.randomInt(0, 7)];
 | 
			
		||||
    const choices = [0, 1, 2, 3, 5, 6, 7];
 | 
			
		||||
    let choiceIndex = rng.randomInt(0, choices.length - 1);
 | 
			
		||||
    const passcode = [choices[choiceIndex]];
 | 
			
		||||
    if (nemesis.Faction != "FC_INFESTATION") {
 | 
			
		||||
        passcode.push(rng.randomInt(0, 7));
 | 
			
		||||
        passcode.push(rng.randomInt(0, 7));
 | 
			
		||||
        choices.splice(choiceIndex, 1);
 | 
			
		||||
        choiceIndex = rng.randomInt(0, choices.length - 1);
 | 
			
		||||
        passcode.push(choices[choiceIndex]);
 | 
			
		||||
 | 
			
		||||
        choices.splice(choiceIndex, 1);
 | 
			
		||||
        choiceIndex = rng.randomInt(0, choices.length - 1);
 | 
			
		||||
        passcode.push(choices[choiceIndex]);
 | 
			
		||||
    }
 | 
			
		||||
    return passcode;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const reqiuemMods: readonly string[] = [
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/ImmortalOneMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/ImmortalTwoMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/ImmortalThreeMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/ImmortalFourMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/ImmortalFiveMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/ImmortalSixMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/ImmortalSevenMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/ImmortalEightMod"
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const antivirusMods: readonly string[] = [
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/AntivirusOneMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/AntivirusTwoMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/AntivirusThreeMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/AntivirusFourMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/AntivirusFiveMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/AntivirusSixMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/AntivirusSevenMod",
 | 
			
		||||
    "/Lotus/Upgrades/Mods/Immortal/AntivirusEightMod"
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export const getNemesisPasscodeModTypes = (nemesis: { fp: bigint; Faction: string }): string[] => {
 | 
			
		||||
    const passcode = getNemesisPasscode(nemesis);
 | 
			
		||||
    return nemesis.Faction == "FC_INFESTATION"
 | 
			
		||||
        ? passcode.map(i => antivirusMods[i])
 | 
			
		||||
        : passcode.map(i => reqiuemMods[i]);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const encodeNemesisGuess = (
 | 
			
		||||
    symbol1: number,
 | 
			
		||||
    result1: number,
 | 
			
		||||
@ -79,6 +121,31 @@ export interface IKnifeResponse {
 | 
			
		||||
    HasKnife?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getKnifeUpgrade = (
 | 
			
		||||
    inventory: TInventoryDatabaseDocument,
 | 
			
		||||
    dataknifeUpgrades: string[],
 | 
			
		||||
    type: string
 | 
			
		||||
): { ItemId: IOid; ItemType: string } => {
 | 
			
		||||
    if (dataknifeUpgrades.indexOf(type) != -1) {
 | 
			
		||||
        return {
 | 
			
		||||
            ItemId: { $oid: "000000000000000000000000" },
 | 
			
		||||
            ItemType: type
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
    for (const upgradeId of dataknifeUpgrades) {
 | 
			
		||||
        if (upgradeId.length == 24) {
 | 
			
		||||
            const upgrade = inventory.Upgrades.id(upgradeId);
 | 
			
		||||
            if (upgrade && upgrade.ItemType == type) {
 | 
			
		||||
                return {
 | 
			
		||||
                    ItemId: { $oid: upgradeId },
 | 
			
		||||
                    ItemType: type
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    throw new Error(`${type} does not seem to be installed on parazon?!`);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const consumeModCharge = (
 | 
			
		||||
    response: IKnifeResponse,
 | 
			
		||||
    inventory: TInventoryDatabaseDocument,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user