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 && (