hacknet nodes in mui

This commit is contained in:
Olivier Gagnon 2021-09-26 21:26:25 -04:00
parent 514b467e27
commit b5abbbc240
5 changed files with 119 additions and 84 deletions

@ -36,11 +36,11 @@ export const HacknetNodeConstants: {
}; };
export const PurchaseMultipliers: { export const PurchaseMultipliers: {
[key: string]: number | string | undefined; [key: string]: number | "MAX" | undefined;
x1: number; x1: number;
x5: number; x5: number;
x10: number; x10: number;
MAX: string; MAX: "MAX";
} = { } = {
x1: 1, x1: 1,
x5: 5, x5: 5,

@ -20,9 +20,18 @@ import { HacknetNode } from "../HacknetNode";
import { Money } from "../../ui/React/Money"; import { Money } from "../../ui/React/Money";
import { MoneyRate } from "../../ui/React/MoneyRate"; import { MoneyRate } from "../../ui/React/MoneyRate";
import Typography from "@mui/material/Typography";
import Grid from "@mui/material/Grid";
import Paper from "@mui/material/Paper";
import Button from "@mui/material/Button";
import { TableCell } from "../../ui/React/Table";
import TableBody from "@mui/material/TableBody";
import Table from "@mui/material/Table";
import TableRow from "@mui/material/TableRow";
interface IProps { interface IProps {
node: HacknetNode; node: HacknetNode;
purchaseMultiplier: number | string; purchaseMultiplier: number | "MAX";
rerender: () => void; rerender: () => void;
player: IPlayer; player: IPlayer;
} }
@ -33,10 +42,9 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
const rerender = props.rerender; const rerender = props.rerender;
// Upgrade Level Button // Upgrade Level Button
let upgradeLevelContent, upgradeLevelClass; let upgradeLevelContent;
if (node.level >= HacknetNodeConstants.MaxLevel) { if (node.level >= HacknetNodeConstants.MaxLevel) {
upgradeLevelContent = <>MAX LEVEL</>; upgradeLevelContent = <>MAX LEVEL</>;
upgradeLevelClass = "std-button-disabled";
} else { } else {
let multiplier = 0; let multiplier = 0;
if (purchaseMult === "MAX") { if (purchaseMult === "MAX") {
@ -49,28 +57,23 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, props.player.hacknet_node_level_cost_mult); const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, props.player.hacknet_node_level_cost_mult);
upgradeLevelContent = ( upgradeLevelContent = (
<> <>
Upgrade x{multiplier} - <Money money={upgradeLevelCost} player={props.player} /> +{multiplier} -&nbsp;
<Money money={upgradeLevelCost} player={props.player} />
</> </>
); );
if (props.player.money.lt(upgradeLevelCost)) {
upgradeLevelClass = "std-button-disabled";
} else {
upgradeLevelClass = "std-button";
}
} }
function upgradeLevelOnClick(): void { function upgradeLevelOnClick(): void {
let numUpgrades = purchaseMult; const numUpgrades =
if (purchaseMult === "MAX") { purchaseMult === "MAX"
numUpgrades = getMaxNumberLevelUpgrades(props.player, node, HacknetNodeConstants.MaxLevel); ? getMaxNumberLevelUpgrades(props.player, node, HacknetNodeConstants.MaxLevel)
} : purchaseMult;
purchaseLevelUpgrade(props.player, node, numUpgrades as number); purchaseLevelUpgrade(props.player, node, numUpgrades);
rerender(); rerender();
} }
let upgradeRamContent, upgradeRamClass; let upgradeRamContent;
if (node.ram >= HacknetNodeConstants.MaxRam) { if (node.ram >= HacknetNodeConstants.MaxRam) {
upgradeRamContent = <>MAX RAM</>; upgradeRamContent = <>MAX RAM</>;
upgradeRamClass = "std-button-disabled";
} else { } else {
let multiplier = 0; let multiplier = 0;
if (purchaseMult === "MAX") { if (purchaseMult === "MAX") {
@ -83,28 +86,21 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, props.player.hacknet_node_ram_cost_mult); const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, props.player.hacknet_node_ram_cost_mult);
upgradeRamContent = ( upgradeRamContent = (
<> <>
Upgrade x{multiplier} - <Money money={upgradeRamCost} player={props.player} /> +{multiplier} -&nbsp;
<Money money={upgradeRamCost} player={props.player} />
</> </>
); );
if (props.player.money.lt(upgradeRamCost)) {
upgradeRamClass = "std-button-disabled";
} else {
upgradeRamClass = "std-button";
}
} }
function upgradeRamOnClick(): void { function upgradeRamOnClick(): void {
let numUpgrades = purchaseMult; const numUpgrades =
if (purchaseMult === "MAX") { purchaseMult === "MAX" ? getMaxNumberRamUpgrades(props.player, node, HacknetNodeConstants.MaxRam) : purchaseMult;
numUpgrades = getMaxNumberRamUpgrades(props.player, node, HacknetNodeConstants.MaxRam); purchaseRamUpgrade(props.player, node, numUpgrades);
}
purchaseRamUpgrade(props.player, node, numUpgrades as number);
rerender(); rerender();
} }
let upgradeCoresContent, upgradeCoresClass; let upgradeCoresContent;
if (node.cores >= HacknetNodeConstants.MaxCores) { if (node.cores >= HacknetNodeConstants.MaxCores) {
upgradeCoresContent = <>MAX CORES</>; upgradeCoresContent = <>MAX CORES</>;
upgradeCoresClass = "std-button-disabled";
} else { } else {
let multiplier = 0; let multiplier = 0;
if (purchaseMult === "MAX") { if (purchaseMult === "MAX") {
@ -117,59 +113,75 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, props.player.hacknet_node_core_cost_mult); const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, props.player.hacknet_node_core_cost_mult);
upgradeCoresContent = ( upgradeCoresContent = (
<> <>
Upgrade x{multiplier} - <Money money={upgradeCoreCost} player={props.player} /> +{multiplier} -&nbsp;
<Money money={upgradeCoreCost} player={props.player} />
</> </>
); );
if (props.player.money.lt(upgradeCoreCost)) {
upgradeCoresClass = "std-button-disabled";
} else {
upgradeCoresClass = "std-button";
}
} }
function upgradeCoresOnClick(): void { function upgradeCoresOnClick(): void {
let numUpgrades = purchaseMult; const numUpgrades =
if (purchaseMult === "MAX") { purchaseMult === "MAX"
numUpgrades = getMaxNumberCoreUpgrades(props.player, node, HacknetNodeConstants.MaxCores); ? getMaxNumberCoreUpgrades(props.player, node, HacknetNodeConstants.MaxCores)
} : purchaseMult;
purchaseCoreUpgrade(props.player, node, numUpgrades as number); purchaseCoreUpgrade(props.player, node, numUpgrades);
rerender(); rerender();
} }
return ( return (
<li className={"hacknet-node"}> <Grid item component={Paper} p={1}>
<div className={"hacknet-node-container"}> <Table size="small">
<div className={"row"}> <TableBody>
<h1 style={{ fontSize: "1em" }}>{node.name}</h1> <TableRow>
</div> <TableCell>
<div className={"row"}> <Typography>{node.name}</Typography>
<p>Production:</p> </TableCell>
<span className={"text money-gold"}> </TableRow>
<Money money={node.totalMoneyGenerated} player={props.player} /> ( <TableRow>
<MoneyRate money={node.moneyGainRatePerSecond} />) <TableCell>
</span> <Typography>Production:</Typography>
</div> </TableCell>
<div className={"row"}> <TableCell colSpan={2}>
<p>Level:</p> <Typography>
<span className={"text upgradable-info"}>{node.level}</span> <Money money={node.totalMoneyGenerated} player={props.player} /> (
<button className={upgradeLevelClass} onClick={upgradeLevelOnClick}> <MoneyRate money={node.moneyGainRatePerSecond} />)
{upgradeLevelContent} </Typography>
</button> </TableCell>
</div> </TableRow>
<div className={"row"}> <TableRow>
<p>RAM:</p> <TableCell>
<span className={"text upgradable-info"}>{node.ram}GB</span> <Typography>Level:</Typography>
<button className={upgradeRamClass} onClick={upgradeRamOnClick}> </TableCell>
{upgradeRamContent} <TableCell>
</button> <Typography>{node.level}</Typography>
</div> </TableCell>
<div className={"row"}> <TableCell>
<p>Cores:</p> <Button onClick={upgradeLevelOnClick}>{upgradeLevelContent}</Button>
<span className={"text upgradable-info"}>{node.cores}</span> </TableCell>
<button className={upgradeCoresClass} onClick={upgradeCoresOnClick}> </TableRow>
{upgradeCoresContent} <TableRow>
</button> <TableCell>
</div> <Typography>RAM:</Typography>
</div> </TableCell>
</li> <TableCell>
<Typography>{node.ram}GB</Typography>
</TableCell>
<TableCell>
<Button onClick={upgradeRamOnClick}>{upgradeRamContent}</Button>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Typography>Cores:</Typography>
</TableCell>
<TableCell>
<Typography>{node.cores}</Typography>
</TableCell>
<TableCell>
<Button onClick={upgradeCoresOnClick}>{upgradeCoresContent}</Button>
</TableCell>
</TableRow>
</TableBody>
</Table>
</Grid>
); );
} }

@ -38,7 +38,7 @@ export function HacknetRoot(props: IProps): React.ReactElement {
function rerender(): void { function rerender(): void {
setRerender((old) => !old); setRerender((old) => !old);
} }
const [purchaseMultiplier, setPurchaseMultiplier] = useState<number | string>(PurchaseMultipliers.x1); const [purchaseMultiplier, setPurchaseMultiplier] = useState<number | "MAX">(PurchaseMultipliers.x1);
useEffect(() => { useEffect(() => {
const id = setInterval(rerender, 200); const id = setInterval(rerender, 200);

@ -29,14 +29,16 @@ export function PurchaseButton(props: IProps): React.ReactElement {
} else { } else {
text = ( text = (
<> <>
Purchase Hacknet Server - <Money money={cost} player={Player} /> Purchase Hacknet Server -&nbsp;
<Money money={cost} player={Player} />
</> </>
); );
} }
} else { } else {
text = ( text = (
<> <>
Purchase Hacknet Node - <Money money={cost} player={Player} /> Purchase Hacknet Node -&nbsp;
<Money money={cost} player={Player} />
</> </>
); );
} }

@ -211,6 +211,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
<List> <List>
<ListItem> <ListItem>
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
The minimum number of milliseconds it takes to execute an operation in Netscript. Setting this too The minimum number of milliseconds it takes to execute an operation in Netscript. Setting this too
@ -231,6 +232,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
</ListItem> </ListItem>
<ListItem> <ListItem>
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
The maximum number of lines a script's logs can hold. Setting this too high can cause the game to The maximum number of lines a script's logs can hold. Setting this too high can cause the game to
@ -251,6 +253,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
</ListItem> </ListItem>
<ListItem> <ListItem>
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
The maximum number of entries that can be written to a port using Netscript's write() function. The maximum number of entries that can be written to a port using Netscript's write() function.
@ -271,6 +274,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
</ListItem> </ListItem>
<ListItem> <ListItem>
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
The maximum number of entries that can be written to a the terminal. Setting this too high can cause The maximum number of entries that can be written to a the terminal. Setting this too high can cause
@ -292,6 +296,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
</ListItem> </ListItem>
<ListItem> <ListItem>
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography>The time (in seconds) between each autosave. Set to 0 to disable autosave.</Typography> <Typography>The time (in seconds) between each autosave. Set to 0 to disable autosave.</Typography>
} }
@ -313,6 +318,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
control={<Switch checked={suppressMessages} onChange={handleSuppressMessagesChange} />} control={<Switch checked={suppressMessages} onChange={handleSuppressMessagesChange} />}
label={ label={
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
If this is set, then any messages you receive will not appear as popups on the screen. They will If this is set, then any messages you receive will not appear as popups on the screen. They will
@ -331,6 +337,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
control={<Switch checked={suppressFactionInvites} onChange={handleSuppressFactionInvitesChange} />} control={<Switch checked={suppressFactionInvites} onChange={handleSuppressFactionInvitesChange} />}
label={ label={
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
If this is set, then any faction invites you receive will not appear as popups on the screen. If this is set, then any faction invites you receive will not appear as popups on the screen.
@ -350,6 +357,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
} }
label={ label={
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
If this is set, the confirmation message before traveling will not show up. You will If this is set, the confirmation message before traveling will not show up. You will
@ -372,6 +380,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
} }
label={ label={
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
If this is set, the confirmation message before buying augmentation will not show up. If this is set, the confirmation message before buying augmentation will not show up.
@ -390,6 +399,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
} }
label={ label={
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
If this is set, a popup message will no longer be shown when you are hospitalized after taking If this is set, a popup message will no longer be shown when you are hospitalized after taking
@ -410,6 +420,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
} }
label={ label={
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
If this is set, then having your Bladeburner actions interrupted by being busy with something If this is set, then having your Bladeburner actions interrupted by being busy with something
@ -428,6 +439,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
control={<Switch checked={disableHotkeys} onChange={handleDisableHotkeysChange} />} control={<Switch checked={disableHotkeys} onChange={handleDisableHotkeysChange} />}
label={ label={
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
If this is set, then most hotkeys (keyboard shortcuts) in the game are disabled. This includes If this is set, then most hotkeys (keyboard shortcuts) in the game are disabled. This includes
@ -445,7 +457,10 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
<FormControlLabel <FormControlLabel
control={<Switch checked={disableASCIIArt} onChange={handleDisableASCIIArtChange} />} control={<Switch checked={disableASCIIArt} onChange={handleDisableASCIIArtChange} />}
label={ label={
<Tooltip title={<Typography>If this is set all ASCII art will be disabled.</Typography>}> <Tooltip
disableInteractive
title={<Typography>If this is set all ASCII art will be disabled.</Typography>}
>
<Typography>Disable ascii art</Typography> <Typography>Disable ascii art</Typography>
</Tooltip> </Tooltip>
} }
@ -456,6 +471,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
control={<Switch checked={disableTextEffects} onChange={handleDisableTextEffectsChange} />} control={<Switch checked={disableTextEffects} onChange={handleDisableTextEffectsChange} />}
label={ label={
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
If this is set, text effects will not be displayed. This can help if text is difficult to read If this is set, text effects will not be displayed. This can help if text is difficult to read
@ -474,6 +490,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
control={<Switch checked={enableBashHotkeys} onChange={handleEnableBashHotkeysChange} />} control={<Switch checked={enableBashHotkeys} onChange={handleEnableBashHotkeysChange} />}
label={ label={
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
Improved Bash emulation mode. Setting this to 1 enables several new Terminal shortcuts and Improved Bash emulation mode. Setting this to 1 enables several new Terminal shortcuts and
@ -492,6 +509,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
control={<Switch checked={enableTimestamps} onChange={handleEnableTimestampsChange} />} control={<Switch checked={enableTimestamps} onChange={handleEnableTimestampsChange} />}
label={ label={
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
Terminal commands and log entries will be timestamped. The timestamp will have the format: M/D Terminal commands and log entries will be timestamped. The timestamp will have the format: M/D
@ -506,7 +524,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
</ListItem> </ListItem>
<ListItem> <ListItem>
<Tooltip title={<Typography>Sets the locale for displaying numbers.</Typography>}> <Tooltip disableInteractive title={<Typography>Sets the locale for displaying numbers.</Typography>}>
<Typography>Locale&nbsp;</Typography> <Typography>Locale&nbsp;</Typography>
</Tooltip> </Tooltip>
<Select value={locale} onChange={handleLocaleChange}> <Select value={locale} onChange={handleLocaleChange}>
@ -551,13 +569,13 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
<Button onClick={() => setDeleteOpen(true)}>Delete Game</Button> <Button onClick={() => setDeleteOpen(true)}>Delete Game</Button>
</Box> </Box>
<Box> <Box>
<Tooltip title={<Typography>export</Typography>}> <Tooltip disableInteractive title={<Typography>export</Typography>}>
<Button onClick={() => props.export()}> <Button onClick={() => props.export()}>
<DownloadIcon color="primary" /> <DownloadIcon color="primary" />
Export Export
</Button> </Button>
</Tooltip> </Tooltip>
<Tooltip title={<Typography>import</Typography>}> <Tooltip disableInteractive title={<Typography>import</Typography>}>
<Button onClick={startImport}> <Button onClick={startImport}>
<UploadIcon color="primary" /> <UploadIcon color="primary" />
Import Import
@ -567,6 +585,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
</Box> </Box>
<Box> <Box>
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
Forcefully kill all active running scripts, in case there is a bug or some unexpected issue with the Forcefully kill all active running scripts, in case there is a bug or some unexpected issue with the
@ -582,6 +601,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
</Box> </Box>
<Box> <Box>
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
Perform a soft reset. Resets everything as if you had just purchased an Augmentation. Perform a soft reset. Resets everything as if you had just purchased an Augmentation.
@ -593,6 +613,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
</Box> </Box>
<Box> <Box>
<Tooltip <Tooltip
disableInteractive
title={ title={
<Typography> <Typography>
If your save file is extremely big you can use this button to view a map of all the files on every If your save file is extremely big you can use this button to view a map of all the files on every