import ExpandLess from "@mui/icons-material/ExpandLess"; import ExpandMore from "@mui/icons-material/ExpandMore"; import { Box, Collapse, ListItemButton, ListItemText, Paper, Table, TableBody, Typography } from "@mui/material"; import { uniqueId } from "lodash"; import React from "react"; import { SpecialServers } from "../../Server/data/SpecialServers"; import { Settings } from "../../Settings/Settings"; import { use } from "../../ui/Context"; import { StatsRow } from "../../ui/React/StatsRow"; import { defaultMultipliers, getBitNodeMultipliers } from "../BitNode"; import { IBitNodeMultipliers } from "../BitNodeMultipliers"; interface IProps { n: number; level?: number; } export function BitnodeMultiplierDescription({ n, level }: IProps): React.ReactElement { const [open, setOpen] = React.useState(false); if (n === 1) return <>; return ( setOpen((old) => !old)}> Bitnode Multipliers} /> {open ? : } ); } export const BitNodeMultipliersDisplay = ({ n, level }: IProps): React.ReactElement => { const player = use.Player(); // If a level argument has been provided, use that as the multiplier level // If not, then we have to assume that we want the next level up from the // current node's source file, so we get the min of that, the SF's max level, // or if it's BN12, ∞ const maxSfLevel = n === 12 ? Infinity : 3; const mults = getBitNodeMultipliers(n, level ?? Math.min(player.sourceFileLvl(n) + 1, maxSfLevel)); return ( ); }; interface IBNMultRows { [mult: string]: { name: string; content?: string; color?: string; }; } interface IBNMultTableProps { sectionName: string; rowData: IBNMultRows; mults: IBitNodeMultipliers; } const BNMultTable = (props: IBNMultTableProps): React.ReactElement => { const rowsArray = Object.entries(props.rowData) .filter(([key, _value]) => props.mults[key] !== defaultMultipliers[key]) .map(([key, value]) => ( )); return rowsArray.length > 0 ? ( {props.sectionName} {rowsArray}
) : ( <> ); }; interface IMultsProps { n: number; mults: IBitNodeMultipliers; } function GeneralMults({ mults }: IMultsProps): React.ReactElement { const rows: IBNMultRows = { WorldDaemonDifficulty: { name: `${SpecialServers.WorldDaemon} Difficulty` }, DaedalusAugsRequirement: { name: "Daedalus Augs Requirement", content: String(mults.DaedalusAugsRequirement), }, HacknetNodeMoney: { name: "Hacknet Production" }, CodingContractMoney: { name: "Coding Contract Reward" }, ClassGymExpGain: { name: "Class/Gym Exp" }, }; return ; } function AugmentationMults({ mults }: IMultsProps): React.ReactElement { const rows: IBNMultRows = { AugmentationMoneyCost: { name: "Money Cost" }, AugmentationRepCost: { name: "Reputation Cost", color: Settings.theme.rep, }, }; return ; } function CompanyMults({ mults }: IMultsProps): React.ReactElement { const rows: IBNMultRows = { CompanyWorkMoney: { name: "Work Money", color: Settings.theme.money, }, CompanyWorkExpGain: { name: "Work Exp" }, }; return ; } function StockMults({ mults }: IMultsProps): React.ReactElement { const rows: IBNMultRows = { FourSigmaMarketDataCost: { name: "Market Data Cost" }, FourSigmaMarketDataApiCost: { name: "Market Data API Cost" }, }; return ; } function FactionMults({ mults }: IMultsProps): React.ReactElement { const rows: IBNMultRows = { RepToDonateToFaction: { name: "Favor to Donate" }, FactionWorkRepGain: { name: "Work Reputation", color: Settings.theme.rep, }, FactionWorkExpGain: { name: "Work Exp" }, FactionPassiveRepGain: { name: "Passive Rep", color: Settings.theme.rep, }, }; return ; } function CrimeMults({ mults }: IMultsProps): React.ReactElement { const rows: IBNMultRows = { CrimeExpGain: { name: "Crime Exp", color: Settings.theme.combat, }, CrimeMoney: { name: "Crime Money", color: Settings.theme.combat, }, }; return ; } function SkillMults({ mults }: IMultsProps): React.ReactElement { const rows: IBNMultRows = { HackingLevelMultiplier: { name: "Hacking Level", color: Settings.theme.hack, }, StrengthLevelMultiplier: { name: "Strength Level", color: Settings.theme.combat, }, DefenseLevelMultiplier: { name: "Defense Level", color: Settings.theme.combat, }, DexterityLevelMultiplier: { name: "Dexterity Level", color: Settings.theme.combat, }, CharismaLevelMultiplier: { name: "Charisma Level", color: Settings.theme.cha, }, }; return ; } function HackingMults({ mults }: IMultsProps): React.ReactElement { const rows: IBNMultRows = { HackExpGain: { name: "Hacking Exp", color: Settings.theme.hack, }, ServerGrowthRate: { name: "Server Growth Rate" }, ServerMaxMoney: { name: "Server Max Money" }, ServerStartingMoney: { name: "Server Starting Money" }, ServerStartingSecurity: { name: "Server Starting Security" }, ServerWeakenRate: { name: "Server Weaken Rate" }, ManualHackMoney: { name: "Manual Hack Money", color: Settings.theme.money, }, ScriptHackMoney: { name: "Script Hack Money", color: Settings.theme.money, }, ScriptHackMoneyGain: { name: "Money Gained From Hack", color: Settings.theme.money, }, }; return ; } function PurchasedServersMults({ mults }: IMultsProps): React.ReactElement { const rows: IBNMultRows = { PurchasedServerCost: { name: "Base Cost", content: mults.PurchasedServerCost.toFixed(3), }, PurchasedServerSoftcap: { name: "Softcap Cost", content: mults.PurchasedServerSoftcap.toFixed(3), }, PurchasedServerLimit: { name: "Server Limit" }, PurchasedServerMaxRam: { name: "Max RAM" }, HomeComputerRamCost: { name: "Home RAM Cost" }, }; return ; } function InfiltrationMults({ mults }: IMultsProps): React.ReactElement { const rows: IBNMultRows = { InfiltrationMoney: { name: "Infiltration Money", color: Settings.theme.money, }, InfiltrationRep: { name: "Infiltration Reputation", color: Settings.theme.rep, }, }; return ; } function BladeburnerMults({ mults }: IMultsProps): React.ReactElement { const player = use.Player(); if (!player.canAccessBladeburner()) return <>; const rows: IBNMultRows = { BladeburnerRank: { name: "Rank Gain" }, BladeburnerSkillCost: { name: "Skill Cost" }, }; return ; } function StanekMults({ mults }: IMultsProps): React.ReactElement { const player = use.Player(); if (!player.canAccessCotMG()) return <>; const extraSize = mults.StaneksGiftExtraSize.toFixed(3); const rows: IBNMultRows = { StnakesGiftPowerMultiplier: { name: "Gift Power" }, StaneksGiftExtraSize: { name: "Base Size Modifier", content: `${mults.StaneksGiftExtraSize > defaultMultipliers.StaneksGiftExtraSize ? `+${extraSize}` : extraSize}`, }, }; return ; } function GangMults({ mults }: IMultsProps): React.ReactElement { const player = use.Player(); if (player.bitNodeN !== 2 && player.sourceFileLvl(2) <= 0) return <>; const rows: IBNMultRows = { GangSoftcap: { name: "Gang Softcap", content: mults.GangSoftcap.toFixed(3), }, GangUniqueAugs: { name: "Unique Augmentations" }, }; return ; } function CorporationMults({ mults }: IMultsProps): React.ReactElement { const player = use.Player(); if (!player.canAccessCorporation()) return <>; const rows: IBNMultRows = { CorporationSoftCap: { name: "Corporation Softcap", content: mults.CorporationSoftCap.toFixed(3), }, CorporationValuation: { name: "Valuation" }, }; return ; }