BLADEBURNER: Add Stop button and refactor code (#1363)

This commit is contained in:
catloversg
2024-06-08 03:34:47 +07:00
committed by GitHub
parent d9efea0fe6
commit 8b3206e1c6
10 changed files with 104 additions and 158 deletions
+55
View File
@@ -0,0 +1,55 @@
import type { Bladeburner } from "../Bladeburner";
import type { Action } from "../Types";
import React from "react";
import { Box, Typography } from "@mui/material";
import { CopyableText } from "../../ui/React/CopyableText";
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
import { StartButton } from "./StartButton";
import { StopButton } from "./StopButton";
import { TeamSizeButton } from "./TeamSizeButton";
import { formatNumberNoSuffix } from "../../ui/formatNumber";
import { BlackOperation, Operation } from "../Actions";
interface ActionHeaderProps {
bladeburner: Bladeburner;
action: Action;
rerender: () => void;
}
export function ActionHeader({ bladeburner, action, rerender }: ActionHeaderProps): React.ReactElement {
const isActive = action.name === bladeburner.action?.name;
const computedActionTimeCurrent = Math.min(
bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow,
bladeburner.actionTimeToComplete,
);
const allowTeam = action instanceof Operation || action instanceof BlackOperation;
if (isActive) {
return (
<>
<Box display="flex" flexDirection="row" alignItems="center">
<CopyableText value={action.name} />
<StopButton bladeburner={bladeburner} rerender={rerender} />
</Box>
<Typography>
(IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)} /{" "}
{formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)})
</Typography>
<Typography>
{createProgressBarText({
progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete,
})}
</Typography>
</>
);
}
return (
<Box display="flex" flexDirection="row" alignItems="center">
<CopyableText value={action.name} />
<StartButton bladeburner={bladeburner} action={action} rerender={rerender} />
{allowTeam && <TeamSizeButton bladeburner={bladeburner} action={action} />}
</Box>
);
}
+12 -43
View File
@@ -7,72 +7,41 @@ import { Paper, Typography } from "@mui/material";
import { Player } from "@player"; import { Player } from "@player";
import { formatNumberNoSuffix } from "../../ui/formatNumber"; import { formatNumberNoSuffix } from "../../ui/formatNumber";
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
import { TeamSizeButton } from "./TeamSizeButton";
import { CopyableText } from "../../ui/React/CopyableText";
import { SuccessChance } from "./SuccessChance"; import { SuccessChance } from "./SuccessChance";
import { StartButton } from "./StartButton";
import { useRerender } from "../../ui/React/hooks"; import { useRerender } from "../../ui/React/hooks";
import { ActionHeader } from "./ActionHeader";
interface BlackOpElemProps { interface BlackOpElemProps {
bladeburner: Bladeburner; bladeburner: Bladeburner;
blackOp: BlackOperation; action: BlackOperation;
} }
export function BlackOpElem({ bladeburner, blackOp }: BlackOpElemProps): React.ReactElement { export function BlackOpElem({ bladeburner, action }: BlackOpElemProps): React.ReactElement {
const rerender = useRerender(); const rerender = useRerender();
const isCompleted = bladeburner.numBlackOpsComplete > blackOp.n; const isCompleted = bladeburner.numBlackOpsComplete > action.n;
if (isCompleted) { if (isCompleted) {
return ( return (
<Paper sx={{ my: 1, p: 1 }}> <Paper sx={{ my: 1, p: 1 }}>
<Typography>{blackOp.name} (COMPLETED)</Typography> <Typography>{action.name} (COMPLETED)</Typography>
</Paper> </Paper>
); );
} }
const isActive = bladeburner.action?.name === blackOp.name; const actionTime = action.getActionTime(bladeburner, Player);
const actionTime = blackOp.getActionTime(bladeburner, Player); const hasRequiredRank = bladeburner.rank >= action.reqdRank;
const hasReqdRank = bladeburner.rank >= blackOp.reqdRank;
const computedActionTimeCurrent = Math.min(
bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow,
bladeburner.actionTimeToComplete,
);
return ( return (
<Paper sx={{ my: 1, p: 1 }}> <Paper sx={{ my: 1, p: 1 }}>
{isActive ? ( <ActionHeader bladeburner={bladeburner} action={action} rerender={rerender}></ActionHeader>
<>
<CopyableText value={blackOp.name} />
<Typography>
(IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)} /{" "}
{formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)})
</Typography>
<Typography>
{createProgressBarText({
progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete,
})}
</Typography>
</>
) : (
<>
<CopyableText value={blackOp.name} />
<StartButton bladeburner={bladeburner} action={blackOp} rerender={rerender} />
<TeamSizeButton action={blackOp} bladeburner={bladeburner} />
</>
)}
<br /> <br />
<Typography whiteSpace={"pre-wrap"}>{action.desc}</Typography>
<br /> <br />
<Typography whiteSpace={"pre-wrap"}>{blackOp.desc}</Typography> <Typography color={hasRequiredRank ? "primary" : "error"}>
<br /> Required Rank: {formatNumberNoSuffix(action.reqdRank, 0)}
<br />
<Typography color={hasReqdRank ? "primary" : "error"}>
Required Rank: {formatNumberNoSuffix(blackOp.reqdRank, 0)}
</Typography> </Typography>
<br /> <br />
<Typography> <Typography>
<SuccessChance action={blackOp} bladeburner={bladeburner} /> <SuccessChance action={action} bladeburner={bladeburner} />
<br /> <br />
Time Required: {convertTimeMsToTimeElapsedString(actionTime * 1000)} Time Required: {convertTimeMsToTimeElapsedString(actionTime * 1000)}
</Typography> </Typography>
+4 -4
View File
@@ -1,6 +1,6 @@
import type { Bladeburner } from "../Bladeburner"; import type { Bladeburner } from "../Bladeburner";
import * as React from "react"; import React from "react";
import { Button, Typography } from "@mui/material"; import { Button, Typography } from "@mui/material";
import { FactionName } from "@enums"; import { FactionName } from "@enums";
import { BlackOpElem } from "./BlackOpElem"; import { BlackOpElem } from "./BlackOpElem";
@@ -14,7 +14,7 @@ interface BlackOpPageProps {
} }
export function BlackOpPage({ bladeburner }: BlackOpPageProps): React.ReactElement { export function BlackOpPage({ bladeburner }: BlackOpPageProps): React.ReactElement {
const blackOps = blackOpsArray.slice(0, bladeburner.numBlackOpsComplete + 1).reverse(); const blackOperations = blackOpsArray.slice(0, bladeburner.numBlackOpsComplete + 1).reverse();
return ( return (
<> <>
@@ -38,8 +38,8 @@ export function BlackOpPage({ bladeburner }: BlackOpPageProps): React.ReactEleme
</Button> </Button>
) : ( ) : (
<> <>
{blackOps.map((blackOp) => ( {blackOperations.map((blackOperation) => (
<BlackOpElem key={blackOp.name} bladeburner={bladeburner} blackOp={blackOp} /> <BlackOpElem key={blackOperation.name} bladeburner={bladeburner} action={blackOperation} />
))} ))}
</> </>
)} )}
+3 -29
View File
@@ -2,18 +2,16 @@ import type { Bladeburner } from "../Bladeburner";
import type { Contract } from "../Actions/Contract"; import type { Contract } from "../Actions/Contract";
import React from "react"; import React from "react";
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
import { Player } from "@player"; import { Player } from "@player";
import { SuccessChance } from "./SuccessChance"; import { SuccessChance } from "./SuccessChance";
import { CopyableText } from "../../ui/React/CopyableText";
import { ActionLevel } from "./ActionLevel"; import { ActionLevel } from "./ActionLevel";
import { Autolevel } from "./Autolevel"; import { Autolevel } from "./Autolevel";
import { StartButton } from "./StartButton"; import { formatBigNumber } from "../../ui/formatNumber";
import { formatNumberNoSuffix, formatBigNumber } from "../../ui/formatNumber";
import { Paper, Typography } from "@mui/material"; import { Paper, Typography } from "@mui/material";
import { useRerender } from "../../ui/React/hooks"; import { useRerender } from "../../ui/React/hooks";
import { getEnumHelper } from "../../utils/EnumHelper"; import { getEnumHelper } from "../../utils/EnumHelper";
import { ActionHeader } from "./ActionHeader";
interface ContractElemProps { interface ContractElemProps {
bladeburner: Bladeburner; bladeburner: Bladeburner;
@@ -25,38 +23,14 @@ export function ContractElem({ bladeburner, action }: ContractElemProps): React.
// Temp special return // Temp special return
if (!getEnumHelper("BladeContractName").isMember(action.name)) return <></>; if (!getEnumHelper("BladeContractName").isMember(action.name)) return <></>;
const isActive = action.name === bladeburner.action?.name; const isActive = action.name === bladeburner.action?.name;
const computedActionTimeCurrent = Math.min(
bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow,
bladeburner.actionTimeToComplete,
);
const actionTime = action.getActionTime(bladeburner, Player); const actionTime = action.getActionTime(bladeburner, Player);
return ( return (
<Paper sx={{ my: 1, p: 1 }}> <Paper sx={{ my: 1, p: 1 }}>
{isActive ? ( <ActionHeader bladeburner={bladeburner} action={action} rerender={rerender}></ActionHeader>
<>
<CopyableText value={action.name} />
<Typography>
(IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)} /{" "}
{formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)})
</Typography>
<Typography>
{createProgressBarText({
progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete,
})}
</Typography>
</>
) : (
<>
<CopyableText value={action.name} />
<StartButton bladeburner={bladeburner} action={action} rerender={rerender} />
</>
)}
<br />
<br /> <br />
<ActionLevel action={action} bladeburner={bladeburner} isActive={isActive} rerender={rerender} /> <ActionLevel action={action} bladeburner={bladeburner} isActive={isActive} rerender={rerender} />
<br /> <br />
<br />
<Typography whiteSpace={"pre-wrap"}> <Typography whiteSpace={"pre-wrap"}>
{action.desc} {action.desc}
<br /> <br />
+3 -34
View File
@@ -2,15 +2,12 @@ import type { Bladeburner } from "../Bladeburner";
import type { GeneralAction } from "../Actions/GeneralAction"; import type { GeneralAction } from "../Actions/GeneralAction";
import React from "react"; import React from "react";
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
import { formatNumberNoSuffix } from "../../ui/formatNumber"; import { formatNumberNoSuffix } from "../../ui/formatNumber";
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
import { Player } from "@player"; import { Player } from "@player";
import { CopyableText } from "../../ui/React/CopyableText"; import { Paper, Typography } from "@mui/material";
import { StartButton } from "./StartButton";
import { StopButton } from "./StopButton";
import { Box, Paper, Typography } from "@mui/material";
import { useRerender } from "../../ui/React/hooks"; import { useRerender } from "../../ui/React/hooks";
import { ActionHeader } from "./ActionHeader";
interface GeneralActionElemProps { interface GeneralActionElemProps {
bladeburner: Bladeburner; bladeburner: Bladeburner;
@@ -19,44 +16,16 @@ interface GeneralActionElemProps {
export function GeneralActionElem({ bladeburner, action }: GeneralActionElemProps): React.ReactElement { export function GeneralActionElem({ bladeburner, action }: GeneralActionElemProps): React.ReactElement {
const rerender = useRerender(); const rerender = useRerender();
const isActive = action.name === bladeburner.action?.name;
const computedActionTimeCurrent = Math.min(
bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow,
bladeburner.actionTimeToComplete,
);
const actionTime = action.getActionTime(bladeburner, Player); const actionTime = action.getActionTime(bladeburner, Player);
const successChance = const successChance =
action.name === "Recruitment" ? Math.max(0, Math.min(bladeburner.getRecruitmentSuccessChance(Player), 1)) : -1; action.name === "Recruitment" ? Math.max(0, Math.min(bladeburner.getRecruitmentSuccessChance(Player), 1)) : -1;
return ( return (
<Paper sx={{ my: 1, p: 1 }}> <Paper sx={{ my: 1, p: 1 }}>
{isActive ? ( <ActionHeader bladeburner={bladeburner} action={action} rerender={rerender}></ActionHeader>
<>
<Box display="flex" flexDirection="row" alignItems="center">
<CopyableText value={action.name} />
<StopButton bladeburner={bladeburner} rerender={rerender} />
</Box>
<Typography>
(IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)} /{" "}
{formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)})
</Typography>
<Typography>
{createProgressBarText({
progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete,
})}
</Typography>
</>
) : (
<Box display="flex" flexDirection="row" alignItems="center">
<CopyableText value={action.name} />
<StartButton bladeburner={bladeburner} action={action} rerender={rerender} />
</Box>
)}
<br />
<br /> <br />
<Typography>{action.desc}</Typography> <Typography>{action.desc}</Typography>
<br /> <br />
<br />
<Typography> <Typography>
Time Required: {convertTimeMsToTimeElapsedString(actionTime * 1000)} Time Required: {convertTimeMsToTimeElapsedString(actionTime * 1000)}
{successChance !== -1 && ( {successChance !== -1 && (
+14 -43
View File
@@ -5,76 +5,47 @@ import React from "react";
import { Paper, Typography } from "@mui/material"; import { Paper, Typography } from "@mui/material";
import { Player } from "@player"; import { Player } from "@player";
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
import { SuccessChance } from "./SuccessChance"; import { SuccessChance } from "./SuccessChance";
import { ActionLevel } from "./ActionLevel"; import { ActionLevel } from "./ActionLevel";
import { Autolevel } from "./Autolevel"; import { Autolevel } from "./Autolevel";
import { StartButton } from "./StartButton"; import { formatBigNumber } from "../../ui/formatNumber";
import { TeamSizeButton } from "./TeamSizeButton";
import { CopyableText } from "../../ui/React/CopyableText";
import { formatNumberNoSuffix, formatBigNumber } from "../../ui/formatNumber";
import { useRerender } from "../../ui/React/hooks"; import { useRerender } from "../../ui/React/hooks";
import { BladeActionType } from "@enums"; import { BladeActionType } from "@enums";
import { ActionHeader } from "./ActionHeader";
interface OperationElemProps { interface OperationElemProps {
bladeburner: Bladeburner; bladeburner: Bladeburner;
operation: Operation; action: Operation;
} }
export function OperationElem({ bladeburner, operation }: OperationElemProps): React.ReactElement { export function OperationElem({ bladeburner, action }: OperationElemProps): React.ReactElement {
const rerender = useRerender(); const rerender = useRerender();
const isActive = const isActive = bladeburner.action?.type === BladeActionType.operation && action.name === bladeburner.action?.name;
bladeburner.action?.type === BladeActionType.operation && operation.name === bladeburner.action?.name; const actionTime = action.getActionTime(bladeburner, Player);
const computedActionTimeCurrent = Math.min(
bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow,
bladeburner.actionTimeToComplete,
);
const actionTime = operation.getActionTime(bladeburner, Player);
return ( return (
<Paper sx={{ my: 1, p: 1 }}> <Paper sx={{ my: 1, p: 1 }}>
{isActive ? ( <ActionHeader bladeburner={bladeburner} action={action} rerender={rerender}></ActionHeader>
<>
<Typography>
<CopyableText value={operation.name} /> (IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)}{" "}
/ {formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)})
</Typography>
<Typography>
{createProgressBarText({
progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete,
})}
</Typography>
</>
) : (
<>
<CopyableText value={operation.name} />
<StartButton bladeburner={bladeburner} action={operation} rerender={rerender} />
<TeamSizeButton action={operation} bladeburner={bladeburner} />
</>
)}
<br />
<br />
<ActionLevel action={operation} bladeburner={bladeburner} isActive={isActive} rerender={rerender} />
<br /> <br />
<ActionLevel action={action} bladeburner={bladeburner} isActive={isActive} rerender={rerender} />
<br /> <br />
<Typography whiteSpace={"pre-wrap"}> <Typography whiteSpace={"pre-wrap"}>
{operation.desc} {action.desc}
<br /> <br />
<br /> <br />
<SuccessChance action={operation} bladeburner={bladeburner} /> <SuccessChance action={action} bladeburner={bladeburner} />
<br /> <br />
Time Required: {convertTimeMsToTimeElapsedString(actionTime * 1000)} Time Required: {convertTimeMsToTimeElapsedString(actionTime * 1000)}
<br /> <br />
Operations remaining: {formatBigNumber(Math.floor(operation.count))} Operations remaining: {formatBigNumber(Math.floor(action.count))}
<br /> <br />
Successes: {formatBigNumber(operation.successes)} Successes: {formatBigNumber(action.successes)}
<br /> <br />
Failures: {formatBigNumber(operation.failures)} Failures: {formatBigNumber(action.failures)}
</Typography> </Typography>
<br /> <br />
<Autolevel rerender={rerender} action={operation} /> <Autolevel rerender={rerender} action={action} />
</Paper> </Paper>
); );
} }
+2 -2
View File
@@ -1,6 +1,6 @@
import type { Bladeburner } from "../Bladeburner"; import type { Bladeburner } from "../Bladeburner";
import * as React from "react"; import React from "react";
import { OperationElem } from "./OperationElem"; import { OperationElem } from "./OperationElem";
import { Typography } from "@mui/material"; import { Typography } from "@mui/material";
@@ -30,7 +30,7 @@ export function OperationPage({ bladeburner }: OperationPageProps): React.ReactE
difficult, but grant more rank and experience. difficult, but grant more rank and experience.
</Typography> </Typography>
{operations.map((operation) => ( {operations.map((operation) => (
<OperationElem key={operation.name} bladeburner={bladeburner} operation={operation} /> <OperationElem key={operation.name} bladeburner={bladeburner} action={operation} />
))} ))}
</> </>
); );
+5 -1
View File
@@ -20,7 +20,11 @@ export function StartButton({ bladeburner, action, rerender }: StartButtonProps)
} }
return ( return (
<ButtonWithTooltip disabledTooltip={disabledReason} onClick={onStart}> <ButtonWithTooltip
buttonProps={{ style: { marginLeft: "1rem" } }}
disabledTooltip={disabledReason}
onClick={onStart}
>
Start Start
</ButtonWithTooltip> </ButtonWithTooltip>
); );
+5 -1
View File
@@ -13,5 +13,9 @@ export function StopButton({ bladeburner, rerender }: StopButtonProps): React.Re
rerender(); rerender();
} }
return <Button onClick={onClick}>Stop</Button>; return (
<Button style={{ marginLeft: "1rem" }} onClick={onClick}>
Stop
</Button>
);
} }
+1 -1
View File
@@ -15,7 +15,7 @@ export function TeamSizeButton({ action, bladeburner }: TeamSizeButtonProps): Re
return ( return (
<> <>
<Button disabled={bladeburner.teamSize === 0} onClick={() => setOpen(true)}> <Button style={{ marginLeft: "1rem" }} disabled={bladeburner.teamSize === 0} onClick={() => setOpen(true)}>
Set Team Size (Curr Size: {formatNumberNoSuffix(action.teamCount, 0)}) Set Team Size (Curr Size: {formatNumberNoSuffix(action.teamCount, 0)})
</Button> </Button>
<TeamSizeModal open={open} onClose={() => setOpen(false)} action={action} bladeburner={bladeburner} /> <TeamSizeModal open={open} onClose={() => setOpen(false)} action={action} bladeburner={bladeburner} />