diff --git a/cypress.json b/cypress.json
index 52a751f84..97707ced4 100644
--- a/cypress.json
+++ b/cypress.json
@@ -4,5 +4,7 @@
"trashAssetsBeforeRuns": true,
"screenshotsFolder": ".cypress/screenshots",
"videosFolder": ".cypress/videos",
- "videoUploadOnPasses": false
+ "videoUploadOnPasses": false,
+ "viewportWidth": 1980,
+ "viewportHeight": 1080
}
diff --git a/cypress/integration/netscript.spec.ts b/cypress/integration/netscript.spec.ts
index a07421d54..58a31e9ef 100644
--- a/cypress/integration/netscript.spec.ts
+++ b/cypress/integration/netscript.spec.ts
@@ -2,7 +2,7 @@ export {};
describe("netscript", () => {
it("creates and runs a NetScript 2.0 script", () => {
- cy.findByRole("button", { name: "Exit Tutorial" }).click();
+ cy.findByRole("button", { name: "SKIP TUTORIAL" }).click();
cy.findByText("Got it!").click();
cy.findByRole("textbox").type("connect n00dles{enter}");
@@ -32,7 +32,7 @@ describe("netscript", () => {
});
it("errors and shows a dialog box when static RAM !== dynamic RAM", () => {
- cy.findByRole("button", { name: "Exit Tutorial" }).click();
+ cy.findByRole("button", { name: "SKIP TUTORIAL" }).click();
cy.findByText("Got it!").click();
cy.findByRole("textbox").type("nano script.js{enter}");
diff --git a/cypress/integration/tutorial.spec.ts b/cypress/integration/tutorial.spec.ts
index f13eb7592..1198bf7f9 100644
--- a/cypress/integration/tutorial.spec.ts
+++ b/cypress/integration/tutorial.spec.ts
@@ -3,19 +3,19 @@ export {};
describe("tutorial", () => {
it("completes the tutorial", () => {
cy.findByText(/dark, dystopian future/);
- cy.findByRole("button", { name: "Next" }).click();
+ cy.findByRole("button", { name: "next" }).click();
cy.findByText(/heading to the Stats page/);
cy.findByRole("button", { name: "Stats" }).click();
cy.findByText(/lot of important information/);
- cy.findByRole("button", { name: "Next" }).click();
+ cy.findByRole("button", { name: "next" }).click();
cy.findByText(/head to your computer's terminal/);
cy.findByRole("button", { name: "Terminal" }).click();
cy.findByText(/is used to interface/);
- cy.findByRole("button", { name: "Next" }).click();
+ cy.findByRole("button", { name: "next" }).click();
cy.findByText(/Let's try it out/i);
cy.findByRole("textbox").type("help{enter}");
@@ -29,7 +29,7 @@ describe("tutorial", () => {
cy.findByText(/that's great and all/i);
cy.findByRole("textbox").type("scan-analyze{enter}");
- cy.findByText(/this command shows more detailed information/i);
+ cy.findByText(/shows more detailed information/i);
cy.findByRole("textbox").type("scan-analyze 2{enter}");
cy.findByText(/now you can see information/i);
@@ -46,10 +46,11 @@ describe("tutorial", () => {
cy.findByRole("textbox").type("hack{enter}");
cy.findByText(/now attempting to hack the server/i);
- cy.findByRole("button", { name: "Next" }).click();
+ cy.findByRole("button", { name: "next" }).click();
- cy.findByText(/hacking exp/i);
- cy.findByRole("textbox", { timeout: 15_000 }).should("not.be.disabled").type("nano n00dles.script{enter}");
+ cy.findByRole("textbox", { timeout: 15_000 }).should("not.be.disabled").type("home{enter}");
+
+ cy.findByRole("textbox").type("nano n00dles.script{enter}");
// monaco can take a bit
cy.findByRole("code", { timeout: 15_000 }).type("{selectall}{del}").type("while(true) {{}{enter}hack('n00dles');");
@@ -72,7 +73,7 @@ describe("tutorial", () => {
cy.findByRole("textbox").type("tail n00dles.script{enter}");
cy.findByText(/The log for this script won't show much/i);
- cy.findByRole("button", { name: "Next" }).click();
+ cy.findByRole("button", { name: "next" }).click();
cy.findByText(/Hacking is not the only way to earn money/i);
cy.findByRole("button", { name: "Hacknet" }).click();
@@ -87,7 +88,7 @@ describe("tutorial", () => {
cy.findByRole("button", { name: "Tutorial" }).click();
cy.findByText(/a lot of different documentation about the game/i);
- cy.findByRole("button", { name: "Finish Tutorial" }).click();
+ cy.findByRole("button", { name: "next" }).click();
cy.findByText("Got it!").click();
cy.findByText(/Tutorial \(AKA Links to Documentation\)/i);
diff --git a/src/InteractiveTutorial.js b/src/InteractiveTutorial.js
index bbead93e9..18379f521 100644
--- a/src/InteractiveTutorial.js
+++ b/src/InteractiveTutorial.js
@@ -28,6 +28,7 @@ const orderedITutorialSteps = [
"TerminalNuke", // NUKE n00dles
"TerminalManualHack", // Hack n00dles
"TerminalHackingMechanics", // Explanation of hacking mechanics
+ "TerminalGoHome", // Go home before creating a script.
"TerminalCreateScript", // Create a script using 'nano'
"TerminalTypeScript", // Script Editor page - Type script and then save & close
"TerminalFree", // Using 'Free' Terminal command
diff --git a/src/Terminal/Terminal.ts b/src/Terminal/Terminal.ts
index cd6929ad1..8039090ec 100644
--- a/src/Terminal/Terminal.ts
+++ b/src/Terminal/Terminal.ts
@@ -590,6 +590,14 @@ export class Terminal implements ITerminal {
return;
}
break;
+ case iTutorialSteps.TerminalGoHome:
+ if (commandArray.length == 1 && commandArray[0] == "home") {
+ iTutorialNextStep();
+ } else {
+ this.print("Bad command. Please follow the tutorial");
+ return;
+ }
+ break;
case iTutorialSteps.TerminalCreateScript:
if (commandArray.length == 2 && commandArray[0] == "nano" && commandArray[1] == "n00dles.script") {
iTutorialNextStep();
diff --git a/src/ui/InteractiveTutorial/InteractiveTutorialRoot.tsx b/src/ui/InteractiveTutorial/InteractiveTutorialRoot.tsx
index dc5d86fe2..486d342d8 100644
--- a/src/ui/InteractiveTutorial/InteractiveTutorialRoot.tsx
+++ b/src/ui/InteractiveTutorial/InteractiveTutorialRoot.tsx
@@ -8,14 +8,19 @@ import ArrowForwardIos from "@mui/icons-material/ArrowForwardIos";
import ArrowBackIos from "@mui/icons-material/ArrowBackIos";
import { ITutorialEvents } from "./ITutorialEvents";
import { use } from "../Context";
+import { CopyableText } from "../React/CopyableText";
import ListItem from "@mui/material/ListItem";
+import TextField from "@mui/material/TextField";
import EqualizerIcon from "@mui/icons-material/Equalizer";
import LastPageIcon from "@mui/icons-material/LastPage";
import HelpIcon from "@mui/icons-material/Help";
import AccountTreeIcon from "@mui/icons-material/AccountTree";
import StorageIcon from "@mui/icons-material/Storage";
import LocationCityIcon from "@mui/icons-material/LocationCity";
+import { Theme } from "@mui/material/styles";
+import makeStyles from "@mui/styles/makeStyles";
+import createStyles from "@mui/styles/createStyles";
import {
iTutorialPrevStep,
@@ -30,439 +35,496 @@ interface IContent {
canNext: boolean;
}
-const contents: { [number: string]: IContent | undefined } = {
- [iTutorialSteps.Start as number]: {
- content: (
-
- Welcome to Bitburner, a cyberpunk-themed incremental RPG! The game takes place in a dark, dystopian future...
- The year is 2077...
-
-
- This tutorial will show you the basics of the game. You may skip the tutorial at any time.
-
- ),
- canNext: true,
- },
- [iTutorialSteps.GoToCharacterPage as number]: {
- content: (
- <>
- Let's start by heading to the Stats page. Click
-
-
- Stats
-
-
- on the main navigation menu (left-hand side of the screen)
- >
- ),
- canNext: false,
- },
- [iTutorialSteps.CharacterPage as number]: {
- content: (
- <>
-
-
- Stats
-
-
- shows a lot of important information about your progress, such as your skills, money, and bonuses.
-
- >
- ),
- canNext: true,
- },
- [iTutorialSteps.CharacterGoToTerminalPage as number]: {
- content: (
- <>
- Let's head to your computer's terminal by clicking
-
-
- Terminal
-
- on the main navigation menu.
- >
- ),
- canNext: false,
- },
- [iTutorialSteps.TerminalIntro as number]: {
- content: (
- <>
-
-
- Terminal
-
-
- is used to interface with your home computer as well as all of the other machines around the world.
-
- >
- ),
- canNext: true,
- },
- [iTutorialSteps.TerminalHelp as number]: {
- content: (
- <>
-
- Let's try it out. Start by entering the help command
- into the
-
-
-
- Terminal
-
- (Don't forget to press Enter after typing the command)
- >
- ),
- canNext: false,
- },
- [iTutorialSteps.TerminalLs as number]: {
- content: (
- <>
-
- The help command displays a list of all available
-
-
-
- Terminal
-
-
- commands, how to use them, and a description of what they do.
-
- Let's try another command. Enter the ls command.
-
- >
- ),
- canNext: false,
- },
- [iTutorialSteps.TerminalScan as number]: {
- content: (
-
- ls is a basic command that shows files on the computer.
- Right now, it shows that you have a program called{" "}
- NUKE.exe on your computer. We'll get to what this does
- later.
-
- Using your home computer's terminal, you can connect to other machines throughout the world. Let's do that now
- by first entering the scan command.
-
- ),
- canNext: false,
- },
- [iTutorialSteps.TerminalScanAnalyze1 as number]: {
- content: (
-
- The scan command shows all available network connections.
- In other words, it displays a list of all servers that can be connected to from your current machine. A server
- is identified by its hostname.
-
- That's great and all, but there's so many servers. Which one should you go to? The{" "}
- scan-analyze command gives some more detailed information
- about servers on the network. Try it now!
-
- ),
- canNext: false,
- },
- [iTutorialSteps.TerminalScanAnalyze2 as number]: {
- content: (
-
- You just ran scan-analyze with a depth of one. This
- command shows more detailed information about each server that you can connect to (servers that are a distance
- of one node away).
- It is also possible to run scan-analyze with a
- higher depth. Let's try a depth of two with the following command:{" "}
- scan-analyze 2.
-
- ),
- canNext: false,
- },
- [iTutorialSteps.TerminalConnect as number]: {
- content: (
-
- Now you can see information about all servers that are up to two nodes away, as well as figure out how to
- navigate to those servers through the network. You can only connect to a server that is one node away. To
- connect to a machine, use the connect [hostname] command.
-
-
- From the results of the scan-analyze command, we can see
- that the n00dles server is only one node away. Let's
- connect so it now using: connect n00dles
-
- ),
- canNext: false,
- },
- [iTutorialSteps.TerminalAnalyze as number]: {
- content: (
-
- You are now connected to another machine! What can you do now? You can hack it!
-
- In the year 2077, currency has become digital and decentralized. People and corporations store their
- money on servers and computers. Using your hacking abilities, you can hack servers to steal money and gain
- experience.
-
- Before you try to hack a server, you should run diagnostics using the{" "}
- analyze command.
-
- ),
- canNext: false,
- },
- [iTutorialSteps.TerminalNuke as number]: {
- content: (
-
- When the analyze command finishes running it will show
- useful information about hacking the server.
- For this server, the required hacking skill is only 1, which
- means you can hack it right now. However, in order to hack a server you must first gain root access. The{" "}
- NUKE.exe program that we saw earlier on your home computer
- is a virus that will grant you root access to a machine if there are enough open ports.
-
- The analyze results shows that there do not need to
- be any open ports on this machine for the NUKE virus to work, so go ahead and run the virus using the{" "}
- run NUKE.exe command.
-
- ),
- canNext: true,
- },
- [iTutorialSteps.TerminalManualHack as number]: {
- content: (
-
- You now have root access! You can hack the server using the{" "}
- hack command. Try doing that now.
-
- ),
- canNext: true,
- },
- [iTutorialSteps.TerminalHackingMechanics as number]: {
- content: (
-
- You are now attempting to hack the server. Performing a hack takes time and only has a certain percentage chance
- of success. This time and success chance is determined by a variety of factors, including your hacking skill and
- the server's security level.
-
-
- If your attempt to hack the server is successful, you will steal a certain percentage of the server's total
- money. This percentage is affected by your hacking skill and the server's security level.
-
-
- The amount of money on a server is not limitless. So, if you constantly hack a server and deplete its money,
- then you will encounter diminishing returns in your hacking.
-
- ),
- canNext: true,
- },
- [iTutorialSteps.TerminalCreateScript as number]: {
- content: (
-
- Hacking is the core mechanic of the game and is necessary for progressing. However, you don't want to be hacking
- manually the entire time. You can automate your hacking by writing scripts!
-
-
- To create a new script or edit an existing one, you can use the{" "}
- nano
- command. Scripts must end with the .script extension.
- Let's make a script now by entering nano n00dles.script{" "}
- after the hack command finishes running (Sidenote: Pressing ctrl + c will end a command like hack early)
-
- ),
- canNext: false,
- },
- [iTutorialSteps.TerminalTypeScript as number]: {
- content: (
- <>
-
- This is the script editor. You can use it to program your scripts. Scripts are written in a simplified version
- of javascript. Copy and paste the following code into the script editor:
-
-
- while(true) {"{"}
- hack('n00dles');
- {"}"}
-
-
- For anyone with basic programming experience, this code should be straightforward. This script will
- continuously hack the n00dles server.
-
-
- To save and close the script editor, press the button in the bottom left, or press ctrl + b.
-
- >
- ),
- canNext: false,
- },
- [iTutorialSteps.TerminalFree as number]: {
- content: (
-
- Now we'll run the script. Scripts require a certain amount of RAM to run, and can be run on any machine which
- you have root access to. Different servers have different amounts of RAM. You can also purchase more RAM for
- your home server.
-
-
- To check how much RAM is available on this machine, enter the{" "}
- free command.
-
- ),
- canNext: false,
- },
- [iTutorialSteps.TerminalRunScript as number]: {
- content: (
-
- We have 4GB of free RAM on this machine, which is enough to run our script. Let's run our script using{" "}
- run n00dles.script.
-
- ),
- canNext: false,
- },
- [iTutorialSteps.TerminalGoToActiveScriptsPage as number]: {
- content: (
- <>
-
- Your script is now running! It will continuously run in the background and will automatically stop if the code
- ever completes (the n00dles.script will never complete
- because it runs an infinite loop).
-
- These scripts can passively earn you income and hacking experience. Your scripts will also earn money and
- experience while you are offline, although at a slightly slower rate.
-
- Let's check out some statistics for our running scripts by clicking{" "}
-
-
-
- Active Scripts
-
- >
- ),
- canNext: false,
- },
- [iTutorialSteps.ActiveScriptsPage as number]: {
- content: (
- <>
-
- This page displays information about all of your scripts that are running across every server. You can use
- this to gauge how well your scripts are doing. Let's go back to
-
-
-
- Terminal
-
- >
- ),
- canNext: false,
- },
- [iTutorialSteps.ActiveScriptsToTerminal as number]: {
- content: (
-
- One last thing about scripts, each active script contains logs that detail what it's doing. We can check these
- logs using the tail command. Do that now for the script we
- just ran by typing tail n00dles.script
-
- ),
- canNext: false,
- },
- [iTutorialSteps.TerminalTailScript as number]: {
- content: (
- <>
-
- The log for this script won't show much right now (it might show nothing at all) because it just started
- running...but check back again in a few minutes!
-
- This covers the basics of hacking. To learn more about writing scripts, select
-
-
-
- Tutorial
-
-
- in the main navigation menu to look at the documentation.
-
- If you are an experienced JavaScript developer, I would highly suggest you check out the section on
- NetscriptJS/Netscript 2.0, it's faster and more powerful.
-
-
-
- For now, let's move on to something else!
-
- >
- ),
- canNext: true,
- },
- [iTutorialSteps.GoToHacknetNodesPage as number]: {
- content: (
- <>
-
- Hacking is not the only way to earn money. One other way to passively earn money is by purchasing and
- upgrading Hacknet Nodes. Let's go to
-
-
-
- Hacknet
-
- through the main navigation menu now.
- >
- ),
- canNext: true,
- },
- [iTutorialSteps.HacknetNodesIntroduction as number]: {
- content: (
-
- here you can purchase new Hacknet Nodes and upgrade your existing ones. Let's purchase a new one now.
-
- ),
- canNext: true,
- },
- [iTutorialSteps.HacknetNodesGoToWorldPage as number]: {
- content: (
- <>
-
- You just purchased a Hacknet Node! This Hacknet Node will passively earn you money over time, both online and
- offline. When you get enough money, you can upgrade your newly-purchased Hacknet Node below.
-
-
- Let's go to
-
-
-
- City
-
- >
- ),
- canNext: true,
- },
- [iTutorialSteps.WorldDescription as number]: {
- content: (
- <>
-
- This page lists all of the different locations you can currently travel to. Each location has something that
- you can do. There's a lot of content out in the world, make sure you explore and discover!
-
-
- Lastly, click on
-
-
-
- Tutorial
-
- >
- ),
- canNext: true,
- },
- [iTutorialSteps.TutorialPageInfo as number]: {
- content: (
-
- This page contains a lot of different documentation about the game's content and mechanics.{" "}
-
- {" "}
- I know it's a lot, but I highly suggest you read (or at least skim) through this before you start playing
-
- . That's the end of the tutorial. Hope you enjoy the game!
-
- ),
- canNext: true,
- },
- [iTutorialSteps.End as number]: {
- content: ,
- canNext: true,
- },
-};
+const useStyles = makeStyles((theme: Theme) =>
+ createStyles({
+ textfield: {
+ borderBottom: "1px solid " + theme.palette.primary.main,
+ },
+ code: {
+ whiteSpace: "pre",
+ backgroundColor: theme.palette.background.paper,
+ },
+ }),
+);
export function InteractiveTutorialRoot(): React.ReactElement {
+ const classes = useStyles();
+
+ const contents: { [number: string]: IContent | undefined } = {
+ [iTutorialSteps.Start as number]: {
+ content: (
+ <>
+
+ Welcome to Bitburner, a cyberpunk-themed incremental RPG! The game takes place in a dark, dystopian
+ future... The year is 2077...
+
+
+ This tutorial will show you the basics of the game. You may skip the tutorial at any time.
+
+ >
+ ),
+ canNext: true,
+ },
+ [iTutorialSteps.GoToCharacterPage as number]: {
+ content: (
+ <>
+ Let's start by heading to the Stats page. Click
+
+
+ Stats
+
+
+ on the main navigation menu (left-hand side of the screen)
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.CharacterPage as number]: {
+ content: (
+ <>
+
+
+ Stats
+
+
+ shows a lot of important information about your progress, such as your skills, money, and bonuses.
+
+ >
+ ),
+ canNext: true,
+ },
+ [iTutorialSteps.CharacterGoToTerminalPage as number]: {
+ content: (
+ <>
+ Let's head to your computer's terminal by clicking
+
+
+ Terminal
+
+ on the main navigation menu.
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.TerminalIntro as number]: {
+ content: (
+ <>
+
+
+ Terminal
+
+
+ is used to interface with your home computer as well as all of the other machines around the world.
+
+ >
+ ),
+ canNext: true,
+ },
+ [iTutorialSteps.TerminalHelp as number]: {
+ content: (
+ <>
+ Let's try it out. Start by entering
+ {"[home ~/]> help"}
+ (Don't forget to press Enter after typing the command)
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.TerminalLs as number]: {
+ content: (
+ <>
+ {"[home ~/]> help"}
+
+ displays a list of all available Terminal commands, how to use them, and a description of what they do.{" "}
+
+
+ Let's try another command. Enter
+
+
+ {"[home ~/]> ls"}
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.TerminalScan as number]: {
+ content: (
+ <>
+ {"[home ~/]> ls"}
+
+ {" "}
+ is a basic command that shows files on the computer. Right now, it shows that you have a program called{" "}
+ NUKE.exe on your computer. We'll get to what this does later.
+
+ Using your home computer's terminal, you can connect to other machines throughout the world. Let's do that
+ now by first entering
+
+ {"[home ~/]> scan"}
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.TerminalScanAnalyze1 as number]: {
+ content: (
+ <>
+ {"[home ~/]> scan"}
+
+ shows all available network connections. In other words, it displays a list of all servers that can be
+ connected to from your current machine. A server is identified by its hostname.
+
+ That's great and all, but there's so many servers. Which one should you go to?{" "}
+
+
+ {"[home ~/]> scan-analyze"}
+ gives some more detailed information about servers on the network. Try it now!
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.TerminalScanAnalyze2 as number]: {
+ content: (
+ <>
+ {"[home ~/]> scan-analyze"}
+
+ shows more detailed information about each server that you can connect to (servers that are a distance of
+ one node away).
+ It is also possible to run scan-analyze with a higher depth. Let's try a depth of two with the
+ following command:{" "}
+
+
+ {"[home ~/]> scan-analyze 2"}
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.TerminalConnect as number]: {
+ content: (
+ <>
+
+ Now you can see information about all servers that are up to two nodes away, as well as figure out how to
+ navigate to those servers through the network. You can only connect to a server that is one node away. To
+ connect to a machine, use
+
+ {"[home ~/]> connect hostname"}
+
+ From the results of
+ {"[home ~/]> scan-analyze 2"}
+
+
+ {" "}
+ we can see that the n00dles server is only one node away. Let's connect so it now using:
+
+
+ {"[home ~/]> connect n00dles"}
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.TerminalAnalyze as number]: {
+ content: (
+ <>
+
+ You are now connected to another machine! What can you do now? You can hack it!
+
+ In the year 2077, currency has become digital and decentralized. People and corporations store their
+ money on servers and computers. Using your hacking abilities, you can hack servers to steal money and gain
+ experience.
+
+ Before you try to hack a server, you should run diagnostics using{" "}
+
+ {"[n00dles ~/]> analyze"}
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.TerminalNuke as number]: {
+ content: (
+ <>
+ When
+ {"[n00dles ~/]> analyze"}
+
+
+ finishes running it will show useful information about hacking the server.
+ For this server, the required hacking skill is only 1, which means you can hack it right now.
+ However, in order to hack a server you must first gain root access. The NUKE.exe program that we saw earlier
+ on your home computer is a virus that will grant you root access to a machine if there are enough open
+ ports.
+
+ {"[n00dles ~/]> analyze"}
+
+
+ {" "}
+ shows that there do not need to be any open ports on this machine for the NUKE virus to work, so go ahead
+ and run the virus using{" "}
+
+ {"[n00dles ~/]> run NUKE.exe"}
+
+
+ >
+ ),
+ canNext: true,
+ },
+ [iTutorialSteps.TerminalManualHack as number]: {
+ content: (
+ <>
+ You now have root access! You can hack the server using
+ {"[home ~/]> hack"}
+
+ Try doing that now.
+ >
+ ),
+ canNext: true,
+ },
+ [iTutorialSteps.TerminalHackingMechanics as number]: {
+ content: (
+
+ You are now attempting to hack the server. Performing a hack takes time and only has a certain percentage
+ chance of success. This time and success chance is determined by a variety of factors, including your hacking
+ skill and the server's security level.
+
+
+ If your attempt to hack the server is successful, you will steal a certain percentage of the server's total
+ money. This percentage is affected by your hacking skill and the server's security level.
+
+
+ The amount of money on a server is not limitless. So, if you constantly hack a server and deplete its money,
+ then you will encounter diminishing returns in your hacking.
+
+ ),
+ canNext: true,
+ },
+ [iTutorialSteps.TerminalGoHome as number]: {
+ content: (
+ <>
+ From any server you can get back home using
+ {"[home ~/]> home"}
+
+ Let's head home before creating our first script!
+ >
+ ),
+ canNext: true,
+ },
+ [iTutorialSteps.TerminalCreateScript as number]: {
+ content: (
+ <>
+
+ Hacking is the core mechanic of the game and is necessary for progressing. However, you don't want to be
+ hacking manually the entire time. You can automate your hacking by writing scripts!
+
+
+ To create a new script or edit an existing one, you can use{" "}
+
+ {"[home ~/]> nano"}
+
+ Scripts must end with the .script extension. Let's make a script now by entering
+ {"[home ~/]> nano n00dles.script"}
+
+
+ after the hack command finishes running (Sidenote: Pressing ctrl + c will end a command like hack early)
+
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.TerminalTypeScript as number]: {
+ content: (
+ <>
+
+ This is the script editor. You can use it to program your scripts. Scripts are written in a simplified
+ version of javascript. Copy and paste the following code into the script editor:
+
+
+
+
+
+
+ For anyone with basic programming experience, this code should be straightforward. This script will
+ continuously hack the n00dles server.
+
+
+ To save and close the script editor, press the button in the bottom left, or press ctrl + b.
+
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.TerminalFree as number]: {
+ content: (
+ <>
+
+ Now we'll run the script. Scripts require a certain amount of RAM to run, and can be run on any machine
+ which you have root access to. Different servers have different amounts of RAM. You can also purchase more
+ RAM for your home server.
+
+
+ To check how much RAM is available on this machine, enter
+
+ {"[home ~/]> free"}
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.TerminalRunScript as number]: {
+ content: (
+ <>
+
+ We have 8GB of free RAM on this machine, which is enough to run our script. Let's run our script using
+
+ {"[home ~/]> run n00dles.script"}
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.TerminalGoToActiveScriptsPage as number]: {
+ content: (
+ <>
+
+ Your script is now running! It will continuously run in the background and will automatically stop if the
+ code ever completes (the n00dles.script will never complete because it runs an infinite loop).
+
+ These scripts can passively earn you income and hacking experience. Your scripts will also earn money and
+ experience while you are offline, although at a slightly slower rate.
+
+ Let's check out some statistics for our running scripts by clicking{" "}
+
+
+
+ Active Scripts
+
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.ActiveScriptsPage as number]: {
+ content: (
+ <>
+
+ This page displays information about all of your scripts that are running across every server. You can use
+ this to gauge how well your scripts are doing. Let's go back to
+
+
+
+ Terminal
+
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.ActiveScriptsToTerminal as number]: {
+ content: (
+ <>
+
+ One last thing about scripts, each active script contains logs that detail what it's doing. We can check
+ these logs using the tail command. Do that now for the script we just ran by typing{" "}
+
+ {"[home ~/]> tail n00dles.script"}
+ >
+ ),
+ canNext: false,
+ },
+ [iTutorialSteps.TerminalTailScript as number]: {
+ content: (
+ <>
+
+ The log for this script won't show much right now (it might show nothing at all) because it just started
+ running...but check back again in a few minutes!
+
+ This covers the basics of hacking. To learn more about writing scripts, select
+
+
+
+ Tutorial
+
+
+ in the main navigation menu to look at the documentation. If you are an experienced JavaScript developer, I
+ would highly suggest you check out the section on NetscriptJS/Netscript 2.0, it's faster and more powerful.
+
+
+ For now, let's move on to something else!
+
+ >
+ ),
+ canNext: true,
+ },
+ [iTutorialSteps.GoToHacknetNodesPage as number]: {
+ content: (
+ <>
+
+ Hacking is not the only way to earn money. One other way to passively earn money is by purchasing and
+ upgrading Hacknet Nodes. Let's go to
+
+
+
+ Hacknet
+
+ through the main navigation menu now.
+ >
+ ),
+ canNext: true,
+ },
+ [iTutorialSteps.HacknetNodesIntroduction as number]: {
+ content: (
+
+ here you can purchase new Hacknet Nodes and upgrade your existing ones. Let's purchase a new one now.
+
+ ),
+ canNext: true,
+ },
+ [iTutorialSteps.HacknetNodesGoToWorldPage as number]: {
+ content: (
+ <>
+
+ You just purchased a Hacknet Node! This Hacknet Node will passively earn you money over time, both online
+ and offline. When you get enough money, you can upgrade your newly-purchased Hacknet Node below.
+
+
+ Let's go to
+
+
+
+ City
+
+ >
+ ),
+ canNext: true,
+ },
+ [iTutorialSteps.WorldDescription as number]: {
+ content: (
+ <>
+
+ This page lists all of the different locations you can currently travel to. Each location has something that
+ you can do. There's a lot of content out in the world, make sure you explore and discover!
+
+
+ Lastly, click on
+
+
+
+ Tutorial
+
+ >
+ ),
+ canNext: true,
+ },
+ [iTutorialSteps.TutorialPageInfo as number]: {
+ content: (
+
+ This page contains a lot of different documentation about the game's content and mechanics. I know it's a lot,
+ but I highly suggest you read (or at least skim) through this before you start playing . That's the end of the
+ tutorial. Hope you enjoy the game!
+
+ ),
+ canNext: true,
+ },
+ [iTutorialSteps.End as number]: {
+ content: ,
+ canNext: true,
+ },
+ };
+
const setRerender = useState(false)[1];
function rerender(): void {
setRerender((old) => !old);
@@ -477,17 +539,23 @@ export function InteractiveTutorialRoot(): React.ReactElement {
return (
{content.content}
-
-
-
- {content.canNext && (
-
-
-
+ {step !== iTutorialSteps.TutorialPageInfo && (
+ <>
+
+
+
+ {content.canNext && (
+
+
+
+ )}
+ >
)}