import { Paper, Table, TableBody, Box, IconButton, Typography, Container, Tooltip } from "@mui/material"; import { MoreHoriz, Info } from "@mui/icons-material"; import React, { useEffect, useState } from "react"; import { BitNodes } from "../BitNode/BitNode"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { HacknetServerConstants } from "../Hacknet/data/Constants"; import { getPurchaseServerLimit } from "../Server/ServerPurchases"; import { Settings } from "../Settings/Settings"; import { SourceFileFlags } from "../SourceFile/SourceFileFlags"; import { MoneySourceTracker } from "../utils/MoneySourceTracker"; import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions"; import { use } from "./Context"; import { numeralWrapper } from "./numeralFormat"; import { Modal } from "./React/Modal"; import { Money } from "./React/Money"; import { StatsRow } from "./React/StatsRow"; import { StatsTable } from "./React/StatsTable"; interface EmployersModalProps { open: boolean; onClose: () => void; } const EmployersModal = ({ open, onClose }: EmployersModalProps): React.ReactElement => { const player = use.Player(); return ( <> All Employers ); }; interface MultTableProps { rows: (string | number)[][]; color: string; noMargin?: boolean; } function MultiplierTable(props: MultTableProps): React.ReactElement { return ( {props.rows.map((data) => { const mult = data[0] as string, value = data[1] as number, modded = data[2] as number | null; if (modded && modded !== value && SourceFileFlags[5] > 0) { return ( <> {numeralWrapper.formatPercentage(value)}{" "} {numeralWrapper.formatPercentage(modded)} ); } return ( ); })}
); } function CurrentBitNode(): React.ReactElement { const player = use.Player(); if (player.sourceFiles.length > 0) { const index = "BitNode" + player.bitNodeN; const currentSourceFile = player.sourceFiles.find((sourceFile) => sourceFile.n == player.bitNodeN); const lvl = currentSourceFile ? currentSourceFile.lvl : 0; return ( BitNode {player.bitNodeN}: {BitNodes[index].name} (Level {lvl}) {BitNodes[index].info} ); } return <>; } interface IMoneyModalProps { open: boolean; onClose: () => void; } function MoneyModal({ open, onClose }: IMoneyModalProps): React.ReactElement { const player = use.Player(); function convertMoneySourceTrackerToString(src: MoneySourceTracker): React.ReactElement { const parts: any[][] = [[`Total:`, ]]; if (src.augmentations) { parts.push([`Augmentations:`, ]); } if (src.bladeburner) { parts.push([`Bladeburner:`, ]); } if (src.casino) { parts.push([`Casino:`, ]); } if (src.codingcontract) { parts.push([`Coding Contracts:`, ]); } if (src.work) { parts.push([`Company Work:`, ]); } if (src.class) { parts.push([`Class:`, ]); } if (src.corporation) { parts.push([`Corporation:`, ]); } if (src.crime) { parts.push([`Crimes:`, ]); } if (src.gang) { parts.push([`Gang:`, ]); } if (src.hacking) { parts.push([`Hacking:`, ]); } if (src.hacknet) { parts.push([`Hacknet Nodes:`, ]); } if (src.hacknet_expenses) { parts.push([`Hacknet Nodes Expenses:`, ]); } if (src.hospitalization) { parts.push([`Hospitalization:`, ]); } if (src.infiltration) { parts.push([`Infiltration:`, ]); } if (src.servers) { parts.push([`Servers:`, ]); } if (src.stock) { parts.push([`Stock Market:`, ]); } if (src.sleeves) { parts.push([`Sleeves:`, ]); } if (src.other) { parts.push([`Other:`, ]); } return ; } let content = ( <> Money earned since you last installed Augmentations
{convertMoneySourceTrackerToString(player.moneySourceA)} ); if (player.sourceFiles.length !== 0) { content = ( <> {content}

Money earned in this BitNode
{convertMoneySourceTrackerToString(player.moneySourceB)} ); } return ( {content} ); } export function CharacterStats(): React.ReactElement { const player = use.Player(); const [moneyOpen, setMoneyOpen] = useState(false); const [employersOpen, setEmployersOpen] = useState(false); const setRerender = useState(false)[1]; function rerender(): void { setRerender((old) => !old); } useEffect(() => { const id = setInterval(rerender, 200); return () => clearInterval(id); }, []); const timeRows = [ ["Since last Augmentation installation", convertTimeMsToTimeElapsedString(player.playtimeSinceLastAug)], ]; if (player.sourceFiles.length > 0) { timeRows.push(["Since last Bitnode destroyed", convertTimeMsToTimeElapsedString(player.playtimeSinceLastBitnode)]); } timeRows.push(["Total", convertTimeMsToTimeElapsedString(player.totalPlaytime)]); return ( Stats General <> setMoneyOpen(true)} sx={{ p: 0 }}> {player.companyName && ( <> )} {player.jobs && Object.keys(player.jobs).length !== 0 && ( <> {Object.keys(player.jobs).length} total setEmployersOpen(true)} sx={{ p: 0 }}> )} 0 ? "Servers" : "Nodes"} owned`} color={Settings.theme.primary} data={{ content: `${player.hacknetNodes.length}${ player.bitNodeN === 9 || SourceFileFlags[9] > 0 ? ` / ${HacknetServerConstants.MaxServers}` : "" }`, }} />
Skills {player.intelligence > 0 && (player.bitNodeN === 5 || SourceFileFlags[5] > 0) && ( )}
Multipliers {SourceFileFlags[5] > 0 && ( Displays your current multipliers.

When there is a dim number next to a multiplier, that means that the multiplier in question is being affected by BitNode multipliers.

The dim number is the raw multiplier, and the undimmed number is the effective multiplier, as dictated by the BitNode.
} > )} {player.canAccessBladeburner() && ( )}
Time Played {timeRows.map(([name, content]) => ( ))}
setMoneyOpen(false)} /> setEmployersOpen(false)} />
); }