diff --git a/css/activescripts.scss b/css/activescripts.scss
index 35e959558..f5f7593ba 100644
--- a/css/activescripts.scss
+++ b/css/activescripts.scss
@@ -6,7 +6,6 @@
.active-scripts-container {
> p {
- width: 70%;
margin: 6px;
padding: 4px;
}
diff --git a/css/augmentations.scss b/css/augmentations.scss
index 2615aa4d6..53193ae1e 100644
--- a/css/augmentations.scss
+++ b/css/augmentations.scss
@@ -8,7 +8,6 @@
.augmentations-content {
> p {
font-size: $defaultFontSize * 0.875;
- width: 70%;
}
}
diff --git a/css/hacknetnodes.scss b/css/hacknetnodes.scss
index f06b0b79a..97bf22122 100644
--- a/css/hacknetnodes.scss
+++ b/css/hacknetnodes.scss
@@ -7,7 +7,6 @@
.hacknet-general-info {
margin: 10px;
- width: 70vw;
}
#hacknet-nodes-container li {
diff --git a/src/Augmentation/AugmentationHelpers.d.ts b/src/Augmentation/AugmentationHelpers.d.ts
index 9e2bb7935..c20c69364 100644
--- a/src/Augmentation/AugmentationHelpers.d.ts
+++ b/src/Augmentation/AugmentationHelpers.d.ts
@@ -1 +1,2 @@
export declare function isRepeatableAug(aug: Augmentation): boolean;
+export declare function installAugmentations(): void;
diff --git a/src/Faction/FactionHelpers.d.ts b/src/Faction/FactionHelpers.d.ts
index be7642c9a..a4a952b31 100644
--- a/src/Faction/FactionHelpers.d.ts
+++ b/src/Faction/FactionHelpers.d.ts
@@ -6,3 +6,4 @@ export declare function hasAugmentationPrereqs(aug: Augmentation): boolean;
export declare function purchaseAugmentation(aug: Augmentation, fac: Faction, sing?: boolean): void;
export declare function displayFactionContent(factionName: string, initiallyOnAugmentationsPage: boolean = false);
export declare function joinFaction(faction: Faction): void;
+export declare function startHackingMission(faction: Faction): void;
diff --git a/src/Faction/FactionHelpers.jsx b/src/Faction/FactionHelpers.jsx
index 772444402..1e5f0e166 100644
--- a/src/Faction/FactionHelpers.jsx
+++ b/src/Faction/FactionHelpers.jsx
@@ -1,7 +1,7 @@
import React from "react";
import ReactDOM from "react-dom";
-import { FactionRoot } from "./ui/Root";
+import { FactionRoot } from "./ui/FactionRoot";
import { Augmentations } from "../Augmentation/Augmentations";
import { PlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
diff --git a/src/Faction/ui/Root.tsx b/src/Faction/ui/FactionRoot.tsx
similarity index 92%
rename from src/Faction/ui/Root.tsx
rename to src/Faction/ui/FactionRoot.tsx
index 694fa9059..50655ea62 100644
--- a/src/Faction/ui/Root.tsx
+++ b/src/Faction/ui/FactionRoot.tsx
@@ -24,8 +24,7 @@ import { CreateGangPopup } from "./CreateGangPopup";
type IProps = {
engine: IEngine;
- initiallyOnAugmentationsPage?: boolean;
- faction: Faction;
+ faction: Faction | null;
p: IPlayer;
startHackingMissionFn: (faction: Faction) => void;
};
@@ -33,6 +32,7 @@ type IProps = {
type IState = {
rerenderFlag: boolean;
purchasingAugs: boolean;
+ faction: Faction;
};
// Info text for all options on the UI
@@ -74,11 +74,13 @@ const GangNames = [
export class FactionRoot extends React.Component {
constructor(props: IProps) {
+ if (props.faction === null) throw new Error("Trying to render the Faction page with null faction");
super(props);
this.state = {
rerenderFlag: false,
- purchasingAugs: props.initiallyOnAugmentationsPage ? props.initiallyOnAugmentationsPage : false,
+ purchasingAugs: false,
+ faction: props.faction,
};
this.manageGang = this.manageGang.bind(this);
@@ -101,7 +103,7 @@ export class FactionRoot extends React.Component {
const popupId = "create-gang-popup";
createPopup(popupId, CreateGangPopup, {
popupId: popupId,
- facName: this.props.faction.name,
+ facName: this.state.faction.name,
p: this.props.p,
engine: this.props.engine,
});
@@ -130,22 +132,22 @@ export class FactionRoot extends React.Component {
}
startFieldWork(): void {
- this.props.p.startFactionFieldWork(this.props.faction);
+ this.props.p.startFactionFieldWork(this.state.faction);
}
startHackingContracts(): void {
- this.props.p.startFactionHackWork(this.props.faction);
+ this.props.p.startFactionHackWork(this.state.faction);
}
startHackingMission(): void {
- const fac = this.props.faction;
+ const fac = this.state.faction;
this.props.p.singularityStopWork();
this.props.engine.loadMissionContent();
this.props.startHackingMissionFn(fac);
}
startSecurityWork(): void {
- this.props.p.startFactionSecurityWork(this.props.faction);
+ this.props.p.startFactionSecurityWork(this.state.faction);
}
render(): React.ReactNode {
@@ -154,7 +156,7 @@ export class FactionRoot extends React.Component {
renderMainPage(): React.ReactNode {
const p = this.props.p;
- const faction = this.props.faction;
+ const faction = this.state.faction;
const factionInfo = faction.getInfo();
// We have a special flag for whether the player this faction is the player's
@@ -200,7 +202,7 @@ export class FactionRoot extends React.Component {
)}
{!isPlayersGang && factionInfo.offersWork() && (
{
renderAugmentationsPage(): React.ReactNode {
return (
<>
-
+
>
);
}
diff --git a/src/Faction/ui/FactionList.tsx b/src/Faction/ui/FactionsRoot.tsx
similarity index 81%
rename from src/Faction/ui/FactionList.tsx
rename to src/Faction/ui/FactionsRoot.tsx
index 358771ed2..fbed0ae67 100644
--- a/src/Faction/ui/FactionList.tsx
+++ b/src/Faction/ui/FactionsRoot.tsx
@@ -1,20 +1,20 @@
import React, { useState } from "react";
import { IPlayer } from "../../PersonObjects/IPlayer";
-import { IEngine } from "../../IEngine";
+import { IRouter } from "../../ui/Router";
import { Factions } from "../Factions";
-import { displayFactionContent, joinFaction } from "../FactionHelpers";
+import { Faction } from "../Faction";
+import { joinFaction } from "../FactionHelpers";
interface IProps {
player: IPlayer;
- engine: IEngine;
+ router: IRouter;
}
-export function FactionList(props: IProps): React.ReactElement {
+export function FactionsRoot(props: IProps): React.ReactElement {
const setRerender = useState(false)[1];
- function openFaction(faction: string): void {
- props.engine.loadFactionContent();
- displayFactionContent(faction);
+ function openFaction(faction: Faction): void {
+ props.router.toFaction(faction);
}
function acceptInvitation(event: React.MouseEvent, faction: string): void {
@@ -33,7 +33,7 @@ export function FactionList(props: IProps): React.ReactElement {
openFaction(faction)}
+ onClick={() => openFaction(Factions[faction])}
style={{ padding: "4px", margin: "4px", display: "inline-block" }}
>
{faction}
diff --git a/src/Gang/IGang.ts b/src/Gang/IGang.ts
index b99f52f1d..00d7911cc 100644
--- a/src/Gang/IGang.ts
+++ b/src/Gang/IGang.ts
@@ -2,6 +2,7 @@ import { GangMemberUpgrade } from "./GangMemberUpgrade";
import { GangMember } from "./GangMember";
import { WorkerScript } from "../Netscript/WorkerScript";
import { IPlayer } from "../PersonObjects/IPlayer";
+import { IAscensionResult } from "./IAscensionResult";
export interface IGang {
facName: string;
@@ -37,8 +38,9 @@ export interface IGang {
getWantedPenalty(): number;
calculatePower(): number;
killMember(member: GangMember): void;
- ascendMember(member: GangMember, workerScript: WorkerScript): void;
+ ascendMember(member: GangMember, workerScript: WorkerScript): IAscensionResult;
getDiscount(): number;
getAllTaskNames(): string[];
getUpgradeCost(upg: GangMemberUpgrade): number;
+ toJSON(): any;
}
diff --git a/src/Locations/ui/GenericLocation.tsx b/src/Locations/ui/GenericLocation.tsx
index 3d6fa9168..f5f345483 100644
--- a/src/Locations/ui/GenericLocation.tsx
+++ b/src/Locations/ui/GenericLocation.tsx
@@ -12,7 +12,7 @@ import { HospitalLocation } from "./HospitalLocation";
import { SlumsLocation } from "./SlumsLocation";
import { SpecialLocation } from "./SpecialLocation";
import { TechVendorLocation } from "./TechVendorLocation";
-import { TravelAgencyLocation } from "./TravelAgencyLocation";
+import { TravelAgencyRoot } from "./TravelAgencyRoot";
import { UniversityLocation } from "./UniversityLocation";
import { CasinoLocation } from "./CasinoLocation";
@@ -21,6 +21,7 @@ import { LocationType } from "../LocationTypeEnum";
import { CityName } from "../data/CityNames";
import { IEngine } from "../../IEngine";
+import { IRouter } from "../../ui/Router";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Settings } from "../../Settings/Settings";
@@ -32,6 +33,7 @@ import { CorruptableText } from "../../ui/React/CorruptableText";
type IProps = {
engine: IEngine;
+ router: IRouter;
loc: Location;
p: IPlayer;
returnToCity: () => void;
@@ -91,7 +93,7 @@ export class GenericLocation extends React.Component {
}
if (this.props.loc.types.includes(LocationType.TravelAgency)) {
- content.push();
+ content.push();
}
if (this.props.loc.types.includes(LocationType.University)) {
diff --git a/src/Locations/ui/Root.tsx b/src/Locations/ui/Root.tsx
index f554e7e06..ec7e5c58b 100644
--- a/src/Locations/ui/Root.tsx
+++ b/src/Locations/ui/Root.tsx
@@ -15,6 +15,7 @@ import { LocationName } from "../data/LocationNames";
import { CONSTANTS } from "../../Constants";
import { IEngine } from "../../IEngine";
+import { IRouter } from "../../ui/Router";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { dialogBoxCreate } from "../../../utils/DialogBox";
@@ -22,6 +23,7 @@ import { dialogBoxCreate } from "../../../utils/DialogBox";
type IProps = {
initiallyInCity?: boolean;
engine: IEngine;
+ router: IRouter;
p: IPlayer;
};
@@ -47,6 +49,10 @@ export class LocationRoot extends React.Component {
}
enterLocation(to: LocationName): void {
+ if (to == LocationName.TravelAgency) {
+ this.props.router.toTravel();
+ return;
+ }
this.props.p.gotoLocation(to);
this.setState({
inCity: false,
@@ -98,6 +104,7 @@ export class LocationRoot extends React.Component {
return (
void;
+ router: IRouter;
};
-function createTravelPopup(p: IPlayer, city: string, travel: () => void): void {
+function travel(p: IPlayer, router: IRouter, to: CityName): void {
+ const cost = CONSTANTS.TravelCost;
+ if (!p.canAfford(cost)) {
+ dialogBoxCreate(`You cannot afford to travel to ${to}`);
+ return;
+ }
+
+ p.loseMoney(cost);
+ p.travel(to);
+ dialogBoxCreate(You are now in {to}!);
+ router.toCity();
+}
+
+function createTravelPopup(p: IPlayer, router: IRouter, city: CityName): void {
if (Settings.SuppressTravelConfirmation) {
- travel();
+ travel(p, router, city);
return;
}
const popupId = `travel-confirmation`;
createPopup(popupId, TravelConfirmationPopup, {
player: p,
city: city,
- travel: travel,
+ travel: () => travel(p, router, city),
popupId: popupId,
});
}
@@ -45,7 +60,7 @@ function ASCIIWorldMap(props: IProps): React.ReactElement {
createTravelPopup(props.p, city, () => props.travel(city))}
+ onTravel={(city: CityName) => createTravelPopup(props.p, props.router, city)}
/>
);
@@ -66,7 +81,7 @@ function ListWorldMap(props: IProps): React.ReactElement {
return (
createTravelPopup(props.p, city, () => props.travel(match[1]))}
+ onClick={() => createTravelPopup(props.p, props.router, city as CityName)}
style={{ display: "block" }}
text={`Travel to ${city}`}
/>
@@ -76,10 +91,15 @@ function ListWorldMap(props: IProps): React.ReactElement {
);
}
-export function TravelAgencyLocation(props: IProps): React.ReactElement {
- if (Settings.DisableASCIIArt) {
- return ;
- } else {
- return ;
- }
+export function TravelAgencyRoot(props: IProps): React.ReactElement {
+ return (
+ <>
+ Travel Agency
+ {Settings.DisableASCIIArt ? (
+
+ ) : (
+
+ )}
+ >
+ );
}
diff --git a/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx b/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx
index 9df9c22e6..b7e33961d 100644
--- a/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx
+++ b/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx
@@ -20,7 +20,7 @@ export function SleeveRoot(props: IProps): React.ReactElement {
}, []);
return (
-
+ <>
Sleeves
Duplicate Sleeves are MK-V Synthoids (synthetic androids) into which your consciousness has been copied. In
@@ -50,6 +50,6 @@ export function SleeveRoot(props: IProps): React.ReactElement {
))}
-
+ >
);
}
diff --git a/src/Prestige.d.ts b/src/Prestige.d.ts
new file mode 100644
index 000000000..61d353ba4
--- /dev/null
+++ b/src/Prestige.d.ts
@@ -0,0 +1,2 @@
+export declare function prestigeAugmentation(): void;
+export declare function prestigeSourceFile(flume: boolean): void;
diff --git a/src/ScriptEditor/ui/Root.tsx b/src/ScriptEditor/ui/Root.tsx
index 543ebf9d6..b1eb01bef 100644
--- a/src/ScriptEditor/ui/Root.tsx
+++ b/src/ScriptEditor/ui/Root.tsx
@@ -308,7 +308,7 @@ export function Root(props: IProps): React.ReactElement {
}
return (
-
+ <>
{" "}
@@ -328,7 +328,7 @@ export function Root(props: IProps): React.ReactElement {
beforeMount={beforeMount}
onMount={onMount}
loading={
Loading script editor!
}
- height="80%"
+ height="90%"
defaultLanguage="javascript"
defaultValue={code}
onChange={updateCode}
@@ -352,6 +352,6 @@ export function Root(props: IProps): React.ReactElement {
Netscript Documentation
-
+ >
);
}
diff --git a/src/Sidebar/ui/SidebarRoot.tsx b/src/Sidebar/ui/SidebarRoot.tsx
index b3a27cd94..50086ceab 100644
--- a/src/Sidebar/ui/SidebarRoot.tsx
+++ b/src/Sidebar/ui/SidebarRoot.tsx
@@ -44,7 +44,7 @@ import LiveHelpIcon from "@mui/icons-material/LiveHelp";
import ExpandLessIcon from "@mui/icons-material/ExpandLess";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
-import { IEngine } from "../../IEngine";
+import { IRouter, Page } from "../../ui/Router";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { CONSTANTS } from "../../Constants";
import { iTutorialSteps, iTutorialNextStep, ITutorial } from "../../InteractiveTutorial";
@@ -56,7 +56,6 @@ import { inMission } from "../../Missions";
import { cinematicTextFlag } from "../../CinematicText";
import { KEY } from "../../../utils/helpers/keyCodes";
import { FconfSettings } from "../../Fconf/FconfSettings";
-import { Page, routing } from "../../ui/navigationTracking";
const drawerWidth = 240;
@@ -83,7 +82,6 @@ const closedMixin = (theme: Theme): CSSObject => ({
const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== "open" })(({ theme, open }) => ({
width: theme.spacing(31),
- flexShrink: 0,
whiteSpace: "nowrap",
boxSizing: "border-box",
...(open && {
@@ -110,7 +108,8 @@ const useStyles = makeStyles((theme: Theme) =>
interface IProps {
player: IPlayer;
- engine: IEngine;
+ router: IRouter;
+ page: Page;
}
export function SidebarRoot(props: IProps): React.ReactElement {
@@ -124,7 +123,6 @@ export function SidebarRoot(props: IProps): React.ReactElement {
return () => clearInterval(id);
}, []);
- const [activeTab, setActiveTab] = useState("Terminal");
const [hackingOpen, setHackingOpen] = useState(true);
const [characterOpen, setCharacterOpen] = useState(true);
const [worldOpen, setWorldOpen] = useState(true);
@@ -176,108 +174,88 @@ export function SidebarRoot(props: IProps): React.ReactElement {
const canBladeburner = !!(props.player.bladeburner as any);
function clickTerminal(): void {
- setActiveTab("Terminal");
- props.engine.loadTerminalContent();
+ props.router.toTerminal();
if (flashTerminal) iTutorialNextStep();
}
function clickCreateScripts(): void {
- setActiveTab("CreateScripts");
- props.engine.loadScriptEditorContent();
+ props.router.toScriptEditor();
}
function clickStats(): void {
- setActiveTab("Stats");
- props.engine.loadCharacterContent();
+ props.router.toCharacterInfo();
if (flashStats) iTutorialNextStep();
}
function clickActiveScripts(): void {
- setActiveTab("ActiveScripts");
- props.engine.loadActiveScriptsContent();
+ props.router.toActiveScripts();
if (flashActiveScripts) iTutorialNextStep();
}
function clickCreateProgram(): void {
- setActiveTab("CreateProgram");
- props.engine.loadCreateProgramContent();
+ props.router.toCreateProgram();
}
function clickFactions(): void {
- setActiveTab("Factions");
- props.engine.loadFactionsContent();
+ props.router.toFactions();
}
function clickAugmentations(): void {
- setActiveTab("Augmentations");
- props.engine.loadAugmentationsContent();
+ props.router.toAugmentations();
}
function clickSleeves(): void {
- setActiveTab("Sleeves");
- props.engine.loadSleevesContent();
+ props.router.toSleeves();
}
function clickHacknet(): void {
- setActiveTab("Hacknet");
- props.engine.loadHacknetNodesContent();
+ props.router.toHacknetNodes();
if (flashHacknet) iTutorialNextStep();
}
function clickCity(): void {
- setActiveTab("City");
- props.engine.loadLocationContent();
+ props.router.toCity();
if (flashCity) iTutorialNextStep();
}
function clickTravel(): void {
- setActiveTab("Travel");
- props.engine.loadTravelContent();
+ props.router.toTravel();
}
function clickJob(): void {
- setActiveTab("Job");
- props.engine.loadJobContent();
+ props.router.toJob();
}
function clickStockMarket(): void {
- setActiveTab("StockMarket");
- props.engine.loadStockMarketContent();
+ props.router.toStockMarket();
}
function clickBladeburner(): void {
- setActiveTab("Bladeburner");
- props.engine.loadBladeburnerContent();
+ props.router.toBladeburner();
}
function clickCorp(): void {
- setActiveTab("Corp");
- props.engine.loadCorporationContent();
+ props.router.toCorporation();
}
function clickGang(): void {
- setActiveTab("Gang");
- props.engine.loadGangContent();
+ props.router.toGang();
}
function clickTutorial(): void {
- setActiveTab("Tutorial");
- props.engine.loadTutorialContent();
+ props.router.toTutorial();
if (flashTutorial) iTutorialNextStep();
}
function clickMilestones(): void {
- setActiveTab("Milestones");
- props.engine.loadMilestonesContent();
+ props.router.toMilestones();
}
function clickOptions(): void {
- setActiveTab("Options");
- props.engine.loadGameOptionsContent();
+ props.router.toGameOptions();
}
function clickDev(): void {
- setActiveTab("Dev");
- props.engine.loadDevMenuContent();
+ props.router.toDevMenu();
}
useEffect(() => {
@@ -327,7 +305,7 @@ export function SidebarRoot(props: IProps): React.ReactElement {
clickCreateProgram();
} else if (event.keyCode === KEY.F && event.altKey) {
// Overriden by Fconf
- if (routing.isOn(Page.Terminal) && FconfSettings.ENABLE_BASH_HOTKEYS) {
+ if (props.page == Page.Terminal && FconfSettings.ENABLE_BASH_HOTKEYS) {
return;
}
event.preventDefault();
@@ -359,421 +337,427 @@ export function SidebarRoot(props: IProps): React.ReactElement {
const [open, setOpen] = useState(true);
const toggleDrawer = (): void => setOpen((old) => !old);
return (
-
-
-
+
+
+
+ {!open ? : }
+
+ Bitburner v{CONSTANTS.Version}} />
+
+
+
+ setHackingOpen((old) => !old)}>
- {!open ? : }
+
- Bitburner v{CONSTANTS.Version}} />
+ Hacking} />
+ {hackingOpen ? : }
-
-
- setHackingOpen((old) => !old)}>
-
-
-
- Hacking} />
- {hackingOpen ? : }
-
-
-
-
-
-
-
-
-
- Terminal
-
-
-
-
-
-
-
-
- Create Script
-
-
-
-
-
-
-
-
- Active Scripts
-
-
-
- {canCreateProgram && (
-
+
+
+
+
+
+
+
+ Terminal
+
+
+
+
+
+
+
+
+
+ Create Script
+
+
+
+
+
+
+
+
+
-
- 0 ? programCount : undefined} color="error">
-
-
-
-
-
- Create Program
-
-
-
- )}
-
-
-
-
- setCharacterOpen((old) => !old)}>
-
-
-
- Character} />
- {characterOpen ? : }
-
-
-
-
-
-
-
-
- Stats
+ Active Scripts
- {canOpenFactions && (
+ {canCreateProgram && (
-
-
+ 0 ? programCount : undefined} color="error">
+
- Factions
+
+ Create Program
+
)}
- {canOpenAugmentations && (
-
-
-
-
-
-
-
- Augmentations
-
-
- )}
-
-
-
-
-
-
- Hacknet
-
-
-
- {canOpenSleeves && (
-
-
-
-
-
- Sleeves
-
-
- )}
-
+
+
-
- setWorldOpen((old) => !old)}>
+
+ setCharacterOpen((old) => !old)}>
+
+
+
+ Character} />
+ {characterOpen ? : }
+
+
+
-
+
- World} />
- {worldOpen ? : }
+
+
+ Stats
+
+
-
+ {canOpenFactions && (
-
+
+
+
-
- City
+
+ Factions
+ )}
+ {canOpenAugmentations && (
-
+
+
+
- Travel
+
+ Augmentations
+
- {canJob && (
-
-
-
-
-
- Job
-
-
- )}
- {canStockMarket && (
-
-
-
-
-
- Stock Market
-
-
- )}
- {canBladeburner && (
-
-
-
-
-
- Bladeburner
-
-
- )}
- {canCorporation && (
-
-
-
-
-
- Corp
-
-
- )}
- {canGang && (
-
-
-
-
-
- Gang
-
-
- )}
-
+ )}
+
+
+
+
+
+
+ Hacknet
+
+
+
+ {canOpenSleeves && (
+
+
+
+
+
+ Sleeves
+
+
+ )}
+
-
- setHelpOpen((old) => !old)}>
+
+ setWorldOpen((old) => !old)}>
+
+
+
+ World} />
+ {worldOpen ? : }
+
+
+
-
+
- Help} />
- {helpOpen ? : }
+
+
+ City
+
+
-
+
+
+
+
+
+ Travel
+
+
+ {canJob && (
-
+
- Milestones
+ Job
+ )}
+ {canStockMarket && (
-
+
-
- Tutorial
-
+ Stock Market
+ )}
+ {canBladeburner && (
-
+
- Options
+ Bladeburner
- {process.env.NODE_ENV === "development" && (
-
-
-
-
-
- Dev
-
-
- )}
-
-
-
-
+ )}
+ {canCorporation && (
+
+
+
+
+
+ Corp
+
+
+ )}
+ {canGang && (
+
+
+
+
+
+ Gang
+
+
+ )}
+
+
+
+ setHelpOpen((old) => !old)}>
+
+
+
+ Help} />
+ {helpOpen ? : }
+
+
+
+
+
+
+
+ Milestones
+
+
+
+
+
+
+
+
+ Tutorial
+
+
+
+
+
+
+
+
+ Options
+
+
+ {process.env.NODE_ENV === "development" && (
+
+
+
+
+
+ Dev
+
+
+ )}
+
+
+
);
}
diff --git a/src/StockMarket/StockMarket.tsx b/src/StockMarket/StockMarket.tsx
index 3846e1889..dbb62e2e7 100644
--- a/src/StockMarket/StockMarket.tsx
+++ b/src/StockMarket/StockMarket.tsx
@@ -9,7 +9,7 @@ import { InitStockMetadata } from "./data/InitStockMetadata";
import { OrderTypes } from "./data/OrderTypes";
import { PositionTypes } from "./data/PositionTypes";
import { StockSymbols } from "./data/StockSymbols";
-import { StockMarketRoot } from "./ui/Root";
+import { StockMarketRoot } from "./ui/StockMarketRoot";
import { CONSTANTS } from "../Constants";
import { WorkerScript } from "../Netscript/WorkerScript";
diff --git a/src/StockMarket/ui/Root.tsx b/src/StockMarket/ui/StockMarketRoot.tsx
similarity index 100%
rename from src/StockMarket/ui/Root.tsx
rename to src/StockMarket/ui/StockMarketRoot.tsx
diff --git a/src/Terminal/ui/TerminalRoot.tsx b/src/Terminal/ui/TerminalRoot.tsx
index 3cc00a346..cc4de1e29 100644
--- a/src/Terminal/ui/TerminalRoot.tsx
+++ b/src/Terminal/ui/TerminalRoot.tsx
@@ -76,7 +76,7 @@ export function TerminalRoot({ terminal, engine, player }: IProps): React.ReactE
const classes = useStyles();
return (
<>
-
+
{terminal.outputHistory.map((item, i) => {
if (item instanceof Output)
@@ -105,7 +105,7 @@ export function TerminalRoot({ terminal, engine, player }: IProps): React.ReactE
{terminal.action !== null && }
-
+
>
diff --git a/src/engine.jsx b/src/engine.jsx
index 25ab34d64..ec3856841 100644
--- a/src/engine.jsx
+++ b/src/engine.jsx
@@ -19,13 +19,14 @@ import { CONSTANTS } from "./Constants";
import { DevMenuRoot } from "./DevMenu";
import { Factions, initFactions } from "./Faction/Factions";
import { processPassiveFactionRepGain, inviteToFaction } from "./Faction/FactionHelpers";
-import { FactionList } from "./Faction/ui/FactionList";
+import { FactionsRoot } from "./Faction/ui/FactionsRoot";
import { Root as BladeburnerRoot } from "./Bladeburner/ui/Root";
import { Root as GangRoot } from "./Gang/ui/Root";
import { SidebarRoot } from "./Sidebar/ui/SidebarRoot";
import { CorporationRoot } from "./Corporation/ui/CorporationRoot";
import { ResleeveRoot } from "./PersonObjects/Resleeving/ui/ResleeveRoot";
import { GameOptionsRoot } from "./ui/React/GameOptionsRoot";
+import { GameRoot } from "./ui/GameRoot";
import { TTheme as Theme } from "./ui/React/Theme";
import { SleeveRoot } from "./PersonObjects/Sleeve/ui/SleeveRoot";
import { displayInfiltrationContent } from "./Infiltration/Helper";
@@ -106,16 +107,16 @@ const Engine = {
_idleSpeed: 200, // Speed (in ms) at which the main loop is updated
loadTerminalContent: function () {
- Engine.hideAllContent();
- Engine.Display.content.style.display = "block";
- routing.navigateTo(Page.CharacterInfo);
- ReactDOM.render(
-
-
- ,
- Engine.Display.content,
- );
- MainMenuLinks.Stats.classList.add("active");
+ // Engine.hideAllContent();
+ // Engine.Display.content.style.display = "block";
+ // routing.navigateTo(Page.CharacterInfo);
+ // ReactDOM.render(
+ //
+ //
+ // ,
+ // Engine.Display.content,
+ // );
+ // MainMenuLinks.Stats.classList.add("active");
},
loadCharacterContent: function () {
@@ -171,7 +172,7 @@ const Engine = {
Engine.Display.content.style.display = "block";
routing.navigateTo(Page.Factions);
MainMenuLinks.Factions.classList.add("active");
- ReactDOM.render(, Engine.Display.content);
+ ReactDOM.render(, Engine.Display.content);
},
// TODO reactify
@@ -394,9 +395,9 @@ const Engine = {
// Helper function that hides all content
hideAllContent: function () {
- Engine.Display.content.style.display = "none";
- Engine.Display.content.scrollTop = 0;
- ReactDOM.unmountComponentAtNode(Engine.Display.content);
+ // Engine.Display.content.style.display = "none";
+ // Engine.Display.content.scrollTop = 0;
+ // ReactDOM.unmountComponentAtNode(Engine.Display.content);
Engine.Display.infiltrationContent.style.display = "none";
ReactDOM.unmountComponentAtNode(Engine.Display.infiltrationContent);
@@ -408,7 +409,6 @@ const Engine = {
},
displayCharacterOverviewInfo: function () {
- console.log("rendering");
ReactDOM.render(
saveObject.saveGame(Engine.indexedDb)} />
@@ -806,15 +806,15 @@ const Engine = {
ReactDOM.render(
-
+
,
- document.getElementById("sidebar"),
+ document.getElementById("mainmenu-container"),
);
},
setDisplayElements: function () {
- Engine.Display.content = document.getElementById("generic-react-container");
- Engine.Display.content.style.display = "none";
+ // Engine.Display.content = document.getElementById("generic-react-container");
+ // Engine.Display.content.style.display = "none";
Engine.Display.missionContent = document.getElementById("mission-container");
Engine.Display.missionContent.style.display = "none";
diff --git a/src/ui/GameRoot.tsx b/src/ui/GameRoot.tsx
new file mode 100644
index 000000000..b8c27ca85
--- /dev/null
+++ b/src/ui/GameRoot.tsx
@@ -0,0 +1,194 @@
+import React, { useState, useEffect, useRef } from "react";
+
+import { IPlayer } from "../PersonObjects/IPlayer";
+import { IEngine } from "../IEngine";
+import { ITerminal } from "../Terminal/ITerminal";
+import { installAugmentations } from "../Augmentation/AugmentationHelpers";
+import { saveObject } from "../SaveObject";
+import { onExport } from "../ExportBonus";
+import { LocationName } from "../Locations/data/LocationNames";
+import { CityName } from "../Locations/data/CityNames";
+import { Faction } from "../Faction/Faction";
+import { prestigeAugmentation } from "../Prestige";
+import { dialogBoxCreate } from "../../utils/DialogBox";
+import { AllServers } from "../Server/AllServers";
+
+import { Theme } from "@mui/material/styles";
+import makeStyles from "@mui/styles/makeStyles";
+import createStyles from "@mui/styles/createStyles";
+import Box from "@mui/material/Box";
+import Typography from "@mui/material/Typography";
+
+import { Page, IRouter } from "./Router";
+import { SidebarRoot } from "../Sidebar/ui/SidebarRoot";
+import { AugmentationsRoot } from "../Augmentation/ui/Root";
+import { DevMenuRoot } from "../DevMenu";
+import { Root as BladeburnerRoot } from "../Bladeburner/ui/Root";
+import { Root as GangRoot } from "../Gang/ui/Root";
+import { CorporationRoot } from "../Corporation/ui/CorporationRoot";
+import { ResleeveRoot } from "../PersonObjects/Resleeving/ui/ResleeveRoot";
+import { GameOptionsRoot } from "../ui/React/GameOptionsRoot";
+import { SleeveRoot } from "../PersonObjects/Sleeve/ui/SleeveRoot";
+import { HacknetRoot } from "../Hacknet/ui/HacknetRoot";
+import { LocationRoot } from "../Locations/ui/Root";
+import { ProgramsRoot } from "../Programs/ui/ProgramsRoot";
+import { Root as ScriptEditorRoot } from "../ScriptEditor/ui/Root";
+import { MilestonesRoot } from "../Milestones/ui/MilestonesRoot";
+import { TerminalRoot } from "../Terminal/ui/TerminalRoot";
+import { TutorialRoot } from "../Tutorial/ui/TutorialRoot";
+import { ActiveScriptsRoot } from "../ui/ActiveScripts/Root";
+import { FactionsRoot } from "../Faction/ui/FactionsRoot";
+import { FactionRoot } from "../Faction/ui/FactionRoot";
+import { CharacterInfo } from "./CharacterInfo";
+import { TravelAgencyRoot } from "../Locations/ui/TravelAgencyRoot";
+import { StockMarketRoot } from "../Locations/ui/StockMarketRoot";
+import { workerScripts } from "../Netscript/WorkerScripts";
+
+import { startHackingMission } from "../Faction/FactionHelpers";
+
+interface IProps {
+ terminal: ITerminal;
+ player: IPlayer;
+ engine: IEngine;
+}
+
+const useStyles = makeStyles((theme: Theme) =>
+ createStyles({
+ root: {
+ "-ms-overflow-style": "none" /* for Internet Explorer, Edge */,
+ "scrollbar-width": "none" /* for Firefox */,
+ },
+ }),
+);
+
+export function GameRoot({ player, engine, terminal }: IProps): React.ReactElement {
+ const contentRef = useRef(null);
+ const [faction, setFaction] = useState(null);
+ const [page, setPage] = useState(Page.Terminal);
+ const classes = useStyles();
+
+ const router = {
+ toActiveScripts: () => setPage(Page.ActiveScripts),
+ toAugmentations: () => setPage(Page.Augmentations),
+ toBladeburner: () => setPage(Page.Bladeburner),
+ toCharacterInfo: () => setPage(Page.Stats),
+ toCorporation: () => setPage(Page.Corporation),
+ toCreateProgram: () => setPage(Page.CreateProgram),
+ toDevMenu: () => setPage(Page.DevMenu),
+ toFaction: (faction: Faction) => {
+ setPage(Page.Faction);
+ setFaction(faction);
+ },
+ toFactions: () => setPage(Page.Factions),
+ toGameOptions: () => setPage(Page.Options),
+ toGang: () => setPage(Page.Gang),
+ toHacknetNodes: () => setPage(Page.Hacknet),
+ toMilestones: () => setPage(Page.Milestones),
+ toResleeves: () => setPage(Page.Resleeves),
+ toScriptEditor: () => setPage(Page.CreateScript),
+ toSleeves: () => setPage(Page.Sleeves),
+ toStockMarket: () => setPage(Page.StockMarket),
+ toTerminal: () => setPage(Page.Terminal),
+ toTutorial: () => setPage(Page.Tutorial),
+ toJob: () => setPage(Page.Job),
+ toCity: () => {
+ // TODO This is bad.
+ player.gotoLocation(player.city as unknown as LocationName);
+ setPage(Page.City);
+ },
+ toTravel: () => {
+ player.gotoLocation(LocationName.TravelAgency);
+ setPage(Page.Travel);
+ },
+ };
+
+ return (
+ <>
+
+
+
+ {page === Page.Terminal ? (
+
+ ) : page === Page.Sleeves ? (
+
+ ) : page === Page.Stats ? (
+
+ ) : page === Page.CreateScript ? (
+
+ ) : page === Page.ActiveScripts ? (
+
+ ) : page === Page.Hacknet ? (
+
+ ) : page === Page.CreateProgram ? (
+
+ ) : page === Page.Factions ? (
+
+ ) : page === Page.Faction ? (
+
+ ) : page === Page.Milestones ? (
+
+ ) : page === Page.Tutorial ? (
+
+ ) : page === Page.DevMenu ? (
+
+ ) : page === Page.Gang ? (
+
+ ) : page === Page.Corporation ? (
+
+ ) : page === Page.Bladeburner ? (
+
+ ) : page === Page.Resleeves ? (
+
+ ) : page === Page.Travel ? (
+
+ ) : page === Page.City ? (
+
+ ) : page === Page.StockMarket ? (
+
+ ) : page === Page.Options ? (
+ saveObject.saveGame(engine.indexedDb)}
+ delete={() => saveObject.deleteGame(engine.indexedDb)}
+ export={() => saveObject.exportGame()}
+ import={() => saveObject.importGame()}
+ forceKill={() => {
+ for (const hostname of Object.keys(AllServers)) {
+ AllServers[hostname].runningScripts = [];
+ }
+ dialogBoxCreate("Forcefully deleted all running scripts. Please save and refresh page.");
+ }}
+ softReset={() => {
+ dialogBoxCreate("Soft Reset!");
+ prestigeAugmentation();
+ }}
+ />
+ ) : page === Page.Augmentations ? (
+ {
+ saveObject.exportGame();
+ onExport(player);
+ }}
+ installAugmentationsFn={installAugmentations}
+ />
+ ) : (
+ <>
+ Cannot load
+ >
+ )}
+
+
+ >
+ );
+}
diff --git a/src/ui/Router.ts b/src/ui/Router.ts
new file mode 100644
index 000000000..58ad8732b
--- /dev/null
+++ b/src/ui/Router.ts
@@ -0,0 +1,62 @@
+import { Faction } from "../Faction/Faction";
+/**
+ * The full-screen page the player is currently be on.
+ * These pages are mutually exclusive.
+ */
+export enum Page {
+ ActiveScripts,
+ Augmentations,
+ Bladeburner,
+ Stats,
+ City,
+ Corporation,
+ CreateProgram,
+ DevMenu,
+ Faction,
+ Factions,
+ Options,
+ Gang,
+ Hacknet,
+ Job,
+ Milestones,
+ Resleeves,
+ CreateScript,
+ Sleeves,
+ StockMarket,
+ Terminal,
+ Travel,
+ Tutorial,
+}
+
+/**
+ * This class keeps track of player navigation/routing within the game.
+ */
+export interface IRouter {
+ // toCinematicText(): void;
+ // toInfiltration(): void;
+ // toMission(): void;
+ // toRedPill(): void;
+ // toworkInProgress(): void;
+ toActiveScripts(): void;
+ toAugmentations(): void;
+ toBladeburner(): void;
+ toCharacterInfo(): void;
+ toCorporation(): void;
+ toCreateProgram(): void;
+ toDevMenu(): void;
+ toFaction(faction: Faction): void; // faction name
+ toFactions(): void;
+ toGameOptions(): void;
+ toGang(): void;
+ toHacknetNodes(): void;
+ toCity(): void; // travel ? city ?
+ toJob(): void;
+ toMilestones(): void;
+ toResleeves(): void;
+ toScriptEditor(filename?: string, code?: string): void;
+ toSleeves(): void;
+ toStockMarket(): void;
+ toTerminal(): void;
+ toTravel(): void;
+ toTutorial(): void;
+}