diff --git a/src/Programs/ui/ProgramsRoot.tsx b/src/Programs/ui/ProgramsRoot.tsx index 7c23b3183..e67c74014 100644 --- a/src/Programs/ui/ProgramsRoot.tsx +++ b/src/Programs/ui/ProgramsRoot.tsx @@ -1,9 +1,19 @@ import React, { useState, useEffect } from "react"; -import { use } from "../../ui/Context"; -import { getAvailableCreatePrograms } from "../ProgramHelpers"; +import _ from "lodash"; -import { Box, Tooltip, Typography } from "@mui/material"; -import Button from "@mui/material/Button"; +import { + Box, + Typography, + Button, + Container, + Paper +} from "@mui/material"; +import { Check, Lock, Create } from "@mui/icons-material"; + +import { use } from "../../ui/Context"; +import { Settings } from "../../Settings/Settings"; + +import { Programs } from "../Programs"; export const ProgramsSeen: string[] = []; @@ -15,7 +25,20 @@ export function ProgramsRoot(): React.ReactElement { setRerender((old) => !old); } - const programs = getAvailableCreatePrograms(player); + const programs = [...Object.values(Programs)] + .filter(prog => { + const create = prog.create; + if (create === null) return false; + if (prog.name === "b1t_flum3.exe") { + return create.req(player); + } + return true; + }) + .sort((a, b) => { + if (player.hasProgram(a.name)) return 1; + if (player.hasProgram(b.name)) return -1; + return (a.create?.level ?? 0) - (b.create?.level ?? 0); + }) useEffect(() => { programs.forEach((p) => { @@ -29,8 +52,27 @@ export function ProgramsRoot(): React.ReactElement { return () => clearInterval(id); }, []); + const getHackingLevelRemaining = (lvl: number): number => { + return Math.ceil(Math.max(lvl - (player.hacking + player.intelligence / 2), 0)); + } + + const getProgCompletion = (name: string): number => { + const programFile = _.find(player.getHomeComputer().programs, p => { + return (p.startsWith(name) && p.endsWith("%-INC")); + }); + if (!programFile) return -1; + + const res = programFile.split("-"); + if (res.length != 3) return -1; + const percComplete = Number(res[1].slice(0, -1)); + if (isNaN(percComplete) || percComplete < 0 || percComplete >= 100) { + return -1; + } + return percComplete; + } + return ( - <> + Create program This page displays any programs that you are able to create. Writing the code for a program takes time, which @@ -38,30 +80,45 @@ export function ProgramsRoot(): React.ReactElement { time. Your progress will be saved and you can continue later. - + {programs.map((program) => { const create = program.create; if (create === null) return <>; + const curCompletion = getProgCompletion(program.name); return ( - - - - - + + + {player.hasProgram(program.name) && || + (create.req(player) && || )} + {program.name} + + {(!player.hasProgram(program.name) && create.req(player)) && } + {(player.hasProgram(program.name) || getHackingLevelRemaining(create.level) === 0) || + + Unlocks in: {getHackingLevelRemaining(create.level)} hacking levels + } + {(curCompletion !== -1) && + + Current completion: {curCompletion}% + } + + {create.tooltip} + + ); })} - + ); } diff --git a/src/Sidebar/ui/SidebarRoot.tsx b/src/Sidebar/ui/SidebarRoot.tsx index 8a3ebe8f6..bd1a1fbf8 100644 --- a/src/Sidebar/ui/SidebarRoot.tsx +++ b/src/Sidebar/ui/SidebarRoot.tsx @@ -143,11 +143,6 @@ export function SidebarRoot(props: IProps): React.ReactElement { const augmentationCount = props.player.queuedAugmentations.length; const invitationsCount = props.player.factionInvitations.filter((f) => !InvitationsSeen.includes(f)).length; const programCount = getAvailableCreatePrograms(props.player).length - ProgramsSeen.length; - const canCreateProgram = - getAvailableCreatePrograms(props.player).length > 0 || - props.player.augmentations.length > 0 || - props.player.queuedAugmentations.length > 0 || - props.player.sourceFiles.length > 0; const canOpenFactions = props.player.factionInvitations.length > 0 || @@ -439,29 +434,27 @@ export function SidebarRoot(props: IProps): React.ReactElement { - {canCreateProgram && ( - - - 0 ? programCount : undefined} color="error"> - - - - - - - - Create Program - - - - )} + + + 0 ? programCount : undefined} color="error"> + + + + + + + + Create Program + + + {canStaneksGift && (