Tutorial: Remove NS1 tutorial, change getting started guide to .js (#258)

This commit is contained in:
Mughur 2022-12-22 00:49:12 +02:00 committed by GitHub
parent b004b7203d
commit addcee73fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 163 additions and 292 deletions

@ -28,7 +28,7 @@ entire "quest-line".
First Steps First Steps
----------- -----------
I'm going to assume you followed the introductory tutorial when you first began the game. I'm going to assume you followed the introductory tutorial when you first began the game.
In this introductory tutorial you created a script called :code:`n00dles.script` and ran it In this introductory tutorial you created a script called :code:`n00dles.js` and ran it
on the :code:`n00dles` server. Right now, we'll kill this script. There are two ways on the :code:`n00dles` server. Right now, we'll kill this script. There are two ways
to do this: to do this:
@ -37,7 +37,7 @@ to do this:
$ kill n00dles.script $ kill n00dles.script
2. You can go to the :code:`Active Scripts` page (|Keyboard shortcut| Alt + s) and 2. You can go to the :code:`Active Scripts` page (|Keyboard shortcut| Alt + s) and
press the "Kill Script" button for :code:`n00dles.script`. press the "Kill Script" button for :code:`n00dles.js`.
If you skipped the introductory tutorial, then ignore the part above. Instead, go to the If you skipped the introductory tutorial, then ignore the part above. Instead, go to the
:code:`Hacknet Nodes` page (|Keyboard shortcut| Alt + h) and purchase a :code:`Hacknet Nodes` page (|Keyboard shortcut| Alt + h) and purchase a
@ -67,11 +67,11 @@ the amount of money available on a server. The :js:func:`weaken` Netscript funct
used to decrease a server's security level. used to decrease a server's security level.
Now let's move on to actually creating the script. Now let's move on to actually creating the script.
Go to your home computer and then create a script called :code:`early-hack-template.script` by Go to your home computer and then create a script called :code:`early-hack-template.js` by
going to Terminal and entering the following two commands:: going to Terminal and entering the following two commands::
$ home $ home
$ nano early-hack-template.script $ nano early-hack-template.js
This will take you to the script editor, which you can use to code and create This will take you to the script editor, which you can use to code and create
:ref:`gameplay_scripts`. It will be helpful to consult the :ref:`netscript` documentation. :ref:`gameplay_scripts`. It will be helpful to consult the :ref:`netscript` documentation.
@ -80,49 +80,50 @@ Specifically, you'll want to take a look at :ref:`netscriptfunctions`.
Enter the following code in the script editor: Enter the following code in the script editor:
.. code:: javascript .. code:: javascript
/** @param {NS} ns */
export async function main(ns) {
// Defines the "target server", which is the server // Defines the "target server", which is the server
// that we're going to hack. In this case, it's "n00dles" // that we're going to hack. In this case, it's "n00dles"
var target = "n00dles"; const target = "n00dles";
// Defines how much money a server should have before we hack it // Defines how much money a server should have before we hack it
// In this case, it is set to 75% of the server's max money // In this case, it is set to 75% of the server's max money
var moneyThresh = getServerMaxMoney(target) * 0.75; const moneyThresh = ns.getServerMaxMoney(target) * 0.75;
// Defines the maximum security level the target server can // Defines the maximum security level the target server can
// have. If the target's security level is higher than this, // have. If the target's security level is higher than this,
// we'll weaken it before doing anything else // we'll weaken it before doing anything else
var securityThresh = getServerMinSecurityLevel(target) + 5; const securityThresh = ns.getServerMinSecurityLevel(target) + 5;
// If we have the BruteSSH.exe program, use it to open the SSH Port // If we have the BruteSSH.exe program, use it to open the SSH Port
// on the target server // on the target server
if (fileExists("BruteSSH.exe", "home")) { if (ns.fileExists("BruteSSH.exe", "home")) {
brutessh(target); ns.brutessh(target);
} }
// Get root access to target server // Get root access to target server
nuke(target); ns.nuke(target);
// Infinite loop that continously hacks/grows/weakens the target server // Infinite loop that continously hacks/grows/weakens the target server
while(true) { while(true) {
if (getServerSecurityLevel(target) > securityThresh) { if (ns.getServerSecurityLevel(target) > securityThresh) {
// If the server's security level is above our threshold, weaken it // If the server's security level is above our threshold, weaken it
weaken(target); await ns.weaken(target);
} else if (getServerMoneyAvailable(target) < moneyThresh) { } else if (ns.getServerMoneyAvailable(target) < moneyThresh) {
// If the server's money is less than our threshold, grow it // If the server's money is less than our threshold, grow it
grow(target); await ns.grow(target);
} else { } else {
// Otherwise, hack it // Otherwise, hack it
hack(target); await ns.hack(target);
}
} }
} }
The script above contains comments that document what it does, but let's go through it The script above contains comments that document what it does, but let's go through it
step-by-step anyways. step-by-step anyways.
.. code:: javascript .. code:: javascript
var target = "n00dles"; const target = "n00dles";
This first command defines a string which contains our target server. That's the server This first command defines a string which contains our target server. That's the server
that we're going to hack. For now, it's set to `n00dles` because that's the only that we're going to hack. For now, it's set to `n00dles` because that's the only
@ -132,7 +133,7 @@ variable to be the hostname of another server.
.. code:: javascript .. code:: javascript
var moneyThresh = getServerMaxMoney(target) * 0.75; const moneyThresh = ns.getServerMaxMoney(target) * 0.75;
This second command defines a numerical value representing the minimum This second command defines a numerical value representing the minimum
amount of money that must be available on the target server in order for our script amount of money that must be available on the target server in order for our script
@ -143,7 +144,7 @@ The :js:func:`getServerMaxMoney` Netscript function is used to find this value
.. code:: javascript .. code:: javascript
var securityThresh = getServerMinSecurityLevel(target) + 5; const securityThresh = ns.getServerMinSecurityLevel(target) + 5;
This third command defines a numerical value representing the maximum security level This third command defines a numerical value representing the maximum security level
the target server can have. If the target server's security level is higher than the target server can have. If the target server's security level is higher than
@ -151,11 +152,11 @@ this value, then our script will :js:func:`weaken` the script before doing anyth
.. code:: javascript .. code:: javascript
if (fileExists("BruteSSH.exe", "home")) { if (ns.fileExists("BruteSSH.exe", "home")) {
brutessh(target); ns.brutessh(target);
} }
nuke(target); ns.nuke(target);
This section of code is used to gain root access on the target server. This is This section of code is used to gain root access on the target server. This is
necessary for hacking. See :ref:`here for more details <gameplay_hacking>`. necessary for hacking. See :ref:`here for more details <gameplay_hacking>`.
@ -163,15 +164,15 @@ necessary for hacking. See :ref:`here for more details <gameplay_hacking>`.
.. code:: javascript .. code:: javascript
while (true) { while (true) {
if (getServerSecurityLevel(target) > securityThresh) { if (ns.getServerSecurityLevel(target) > securityThresh) {
// If the server's security level is above our threshold, weaken it // If the server's security level is above our threshold, weaken it
weaken(target); await ns.weaken(target);
} else if (getServerMoneyAvailable(target) < moneyThresh) { } else if (ns.getServerMoneyAvailable(target) < moneyThresh) {
// Otherwise, if the server's money is less than our threshold, grow it // Otherwise, if the server's money is less than our threshold, grow it
grow(target); await ns.grow(target);
} else { } else {
// Otherwise, hack it // Otherwise, hack it
hack(target); await ns.hack(target);
} }
} }
@ -179,6 +180,12 @@ This is the main section that drives our script. It dictates the script's logic
and carries out the hacking operations. The `while (true)` creates an infinite loop and carries out the hacking operations. The `while (true)` creates an infinite loop
that will continuously run the hacking logic until the the script is killed. that will continuously run the hacking logic until the the script is killed.
The await keyword is needed for `hack` / `grow` / `weaken` because these commands take
time to execute, unlike the others. If you forget to await these commands, you will get
an exception saying you tried to do multiple things at once, because your code will
immediately finish the function call without waiting for the operation to be done. Also
important is that await can only be used in functions marked async (which main() is).
Running our Scripts Running our Scripts
------------------- -------------------
Now we want to start running our hacking script so that it can start earning us Now we want to start running our hacking script so that it can start earning us
@ -268,7 +275,7 @@ First, let's determine how many threads of our hacking script we can run.
The script we wrote The script we wrote
uses 2.6GB of RAM. You can check this using the following |Terminal| command:: uses 2.6GB of RAM. You can check this using the following |Terminal| command::
$ mem early-hack-template.script $ mem early-hack-template.js
This means we can run 6 threads on a 16GB server. Now, to run our scripts on all of these This means we can run 6 threads on a 16GB server. Now, to run our scripts on all of these
servers, we have to do the following: servers, we have to do the following:
@ -283,36 +290,36 @@ servers, we have to do the following:
Here's the sequence of |Terminal| commands I used in order to achieve this:: Here's the sequence of |Terminal| commands I used in order to achieve this::
$ home $ home
$ scp early-hack-template.script n00dles $ scp early-hack-template.js n00dles
$ scp early-hack-template.script sigma-cosmetics $ scp early-hack-template.js sigma-cosmetics
$ scp early-hack-template.script joesguns $ scp early-hack-template.js joesguns
$ scp early-hack-template.script nectar-net $ scp early-hack-template.js nectar-net
$ scp early-hack-template.script hong-fang-tea $ scp early-hack-template.js hong-fang-tea
$ scp early-hack-template.script harakiri-sushi $ scp early-hack-template.js harakiri-sushi
$ connect n00dles $ connect n00dles
$ run NUKE.exe $ run NUKE.exe
$ run early-hack-template.script -t 1 $ run early-hack-template.js -t 1
$ home $ home
$ connect sigma-cosmetics $ connect sigma-cosmetics
$ run NUKE.exe $ run NUKE.exe
$ run early-hack-template.script -t 6 $ run early-hack-template.js -t 6
$ home $ home
$ connect joesguns $ connect joesguns
$ run NUKE.exe $ run NUKE.exe
$ run early-hack-template.script -t 6 $ run early-hack-template.js -t 6
$ home $ home
$ connect hong-fang-tea $ connect hong-fang-tea
$ run NUKE.exe $ run NUKE.exe
$ run early-hack-template.script -t 6 $ run early-hack-template.js -t 6
$ home $ home
$ connect harakiri-sushi $ connect harakiri-sushi
$ run NUKE.exe $ run NUKE.exe
$ run early-hack-template.script -t 6 $ run early-hack-template.js -t 6
$ home $ home
$ connect hong-fang-tea $ connect hong-fang-tea
$ connect nectar-net $ connect nectar-net
$ run NUKE.exe $ run NUKE.exe
$ run early-hack-template.script -t 6 $ run early-hack-template.js -t 6
.. note:: .. note::
@ -322,7 +329,7 @@ Here's the sequence of |Terminal| commands I used in order to achieve this::
This works for most commands in the game! This works for most commands in the game!
The :ref:`home_terminal_command` |Terminal| command is used to connect to the home The :ref:`home_terminal_command` |Terminal| command is used to connect to the home
computer. When running our scripts with the :code:`run early-hack-template.script -t 6` computer. When running our scripts with the :code:`run early-hack-template.js -t 6`
command, the :code:`-t 6` specifies that the script should be run with 6 threads. command, the :code:`-t 6` specifies that the script should be run with 6 threads.
Note that the |nectar-net| server isn't in the home computer's immediate network. Note that the |nectar-net| server isn't in the home computer's immediate network.
@ -371,13 +378,13 @@ script to target :code:`joesguns` instead of :code:`n00dles`.
Go to |Terminal| and edit the hacking script by entering:: Go to |Terminal| and edit the hacking script by entering::
$ home $ home
$ nano early-hack-template.script $ nano early-hack-template.js
At the top of the script, change the `target` variable to be `joesguns`: At the top of the script, change the `target` variable to be `joesguns`:
.. code:: javascript .. code:: javascript
var target = "joesguns"; const target = "joesguns";
Note that this will **NOT** affect any instances of the script that are already running. Note that this will **NOT** affect any instances of the script that are already running.
This will only affect instances of the script that are ran from this point forward. This will only affect instances of the script that are ran from this point forward.
@ -401,34 +408,39 @@ Netscript functions:
Create the script by going to |Terminal| and typing:: Create the script by going to |Terminal| and typing::
$ home $ home
$ nano purchase-server-8gb.script $ nano purchase-server-8gb.js
Paste the following code into the script editor: Paste the following code into the script editor:
.. code:: javascript .. code:: javascript
/** @param {NS} ns */
export async function main(ns) {
// How much RAM each purchased server will have. In this case, it'll // How much RAM each purchased server will have. In this case, it'll
// be 8GB. // be 8GB.
var ram = 8; const ram = 8;
// Iterator we'll use for our loop // Iterator we'll use for our loop
var i = 0; let i = 0;
// Continuously try to purchase servers until we've reached the maximum // Continuously try to purchase servers until we've reached the maximum
// amount of servers // amount of servers
while (i < getPurchasedServerLimit()) { while (i < ns.getPurchasedServerLimit()) {
// Check if we have enough money to purchase a server // Check if we have enough money to purchase a server
if (getServerMoneyAvailable("home") > getPurchasedServerCost(ram)) { if (ns.getServerMoneyAvailable("home") > ns.getPurchasedServerCost(ram)) {
// If we have enough money, then: // If we have enough money, then:
// 1. Purchase the server // 1. Purchase the server
// 2. Copy our hacking script onto the newly-purchased server // 2. Copy our hacking script onto the newly-purchased server
// 3. Run our hacking script on the newly-purchased server with 3 threads // 3. Run our hacking script on the newly-purchased server with 3 threads
// 4. Increment our iterator to indicate that we've bought a new server // 4. Increment our iterator to indicate that we've bought a new server
var hostname = purchaseServer("pserv-" + i, ram); let hostname = ns.purchaseServer("pserv-" + i, ram);
scp("early-hack-template.script", hostname); ns.scp("early-hack-template.script", hostname);
exec("early-hack-template.script", hostname, 3); ns.exec("early-hack-template.script", hostname, 3);
++i; ++i;
} }
//Make the script wait for a second before looping again.
//Removing this line will cause an infinite loop and crash the game.
await ns.sleep(1000);
}
} }
This code uses a while loop to purchase the maximum amount of servers using the This code uses a while loop to purchase the maximum amount of servers using the
@ -443,7 +455,7 @@ execute it on that server.
To run this script, go to |Terminal| and type:: To run this script, go to |Terminal| and type::
$ run purchase-server-8gb.script $ run purchase-server-8gb.js
This purchase will continuously run until it has purchased the maximum number of servers. This purchase will continuously run until it has purchased the maximum number of servers.
When this happens, it'll mean that you have a bunch of new servers that are all running When this happens, it'll mean that you have a bunch of new servers that are all running
@ -540,7 +552,7 @@ finish running. This will free up some RAM on your home computer. We don't want
to go to waste, so we'll make use of it. Go to |Terminal| and enter the following commands:: to go to waste, so we'll make use of it. Go to |Terminal| and enter the following commands::
$ home $ home
$ run early-hack-template.script -t 3 $ run early-hack-template.js -t 3
Reaching a Hacking Level of 50 Reaching a Hacking Level of 50
------------------------------ ------------------------------
@ -680,10 +692,10 @@ All of these servers have 32GB of RAM. You can use the |Terminal| command
go to |Terminal| and run:: go to |Terminal| and run::
$ home $ home
$ scp early-hack-template.script neo-net $ scp early-hack-template.js neo-net
$ scp early-hack-template.script zer0 $ scp early-hack-template.js zer0
$ scp early-hack-template.script max-hardware $ scp early-hack-template.js max-hardware
$ scp early-hack-template.script iron-gym $ scp early-hack-template.js iron-gym
Since each of these servers has 32GB of RAM, we can run our hacking script with 12 threads Since each of these servers has 32GB of RAM, we can run our hacking script with 12 threads
on each server. By now, you should know how to connect to servers. So find and connect to on each server. By now, you should know how to connect to servers. So find and connect to
@ -691,7 +703,7 @@ each of the servers above using the :code:`scan-analyze 3` |Terminal| command. T
following |Terminal| command to run our hacking following |Terminal| command to run our hacking
script with 12 threads:: script with 12 threads::
$ run early-hack-template.script -t 12 $ run early-hack-template.js -t 12
Remember that if you have the |AutoLink| program, you can simply click on the hostname of a server Remember that if you have the |AutoLink| program, you can simply click on the hostname of a server
after running :ref:`scan_analyze_terminal_command` to connect to it. after running :ref:`scan_analyze_terminal_command` to connect to it.
@ -766,7 +778,7 @@ much more money, and then you can come back later on and get all these Augmentat
Right now, I suggest purchasing at the very least the :code:`Neurotrainer I` Augmentation from Right now, I suggest purchasing at the very least the :code:`Neurotrainer I` Augmentation from
|CyberSec|. If you have the money to spare, I would also suggest getting :code:`BitWire` and |CyberSec|. If you have the money to spare, I would also suggest getting :code:`BitWire` and
several levels of the :code:`NeuroFlux Governor` Augmentations. Note that each time several levels of the :code:`NeuroFlux Governor` (:code:`NFG`) Augmentations. Note that each time
you purchase an Augmentation, you purchase an Augmentation,
:ref:`the price of purchasing another increases by 90% <gameplay_augmentations_purchasingmultiple>`, :ref:`the price of purchasing another increases by 90% <gameplay_augmentations_purchasingmultiple>`,
so make sure you buy the most expensive Augmentation first. Don't worry, once you choose to so make sure you buy the most expensive Augmentation first. Don't worry, once you choose to
@ -803,10 +815,11 @@ so you should write a script to automate the process. Here's a simple example fo
startup script. Feel free to adjust it to your liking. startup script. Feel free to adjust it to your liking.
.. code:: javascript .. code:: javascript
/** @param {NS} ns */
export async function main(ns) {
// Array of all servers that don't need any ports opened // Array of all servers that don't need any ports opened
// to gain root access. These have 16 GB of RAM // to gain root access. These have 16 GB of RAM
var servers0Port = ["sigma-cosmetics", const servers0Port = ["sigma-cosmetics",
"joesguns", "joesguns",
"nectar-net", "nectar-net",
"hong-fang-tea", "hong-fang-tea",
@ -814,7 +827,7 @@ startup script. Feel free to adjust it to your liking.
// Array of all servers that only need 1 port opened // Array of all servers that only need 1 port opened
// to gain root access. These have 32 GB of RAM // to gain root access. These have 32 GB of RAM
var servers1Port = ["neo-net", const servers1Port = ["neo-net",
"zer0", "zer0",
"max-hardware", "max-hardware",
"iron-gym"]; "iron-gym"];
@ -822,31 +835,31 @@ startup script. Feel free to adjust it to your liking.
// Copy our scripts onto each server that requires 0 ports // Copy our scripts onto each server that requires 0 ports
// to gain root access. Then use nuke() to gain admin access and // to gain root access. Then use nuke() to gain admin access and
// run the scripts. // run the scripts.
for (var i = 0; i < servers0Port.length; ++i) { for (let i = 0; i < servers0Port.length; ++i) {
var serv = servers0Port[i]; const serv = servers0Port[i];
scp("early-hack-template.script", serv); ns.scp("early-hack-template.script", serv);
nuke(serv); ns.nuke(serv);
exec("early-hack-template.script", serv, 6); ns.exec("early-hack-template.script", serv, 6);
} }
// Wait until we acquire the "BruteSSH.exe" program // Wait until we acquire the "BruteSSH.exe" program
while (!fileExists("BruteSSH.exe")) { while (!ns.fileExists("BruteSSH.exe")) {
sleep(60000); await ns.sleep(60000);
} }
// Copy our scripts onto each server that requires 1 port // Copy our scripts onto each server that requires 1 port
// to gain root access. Then use brutessh() and nuke() // to gain root access. Then use brutessh() and nuke()
// to gain admin access and run the scripts. // to gain admin access and run the scripts.
for (var i = 0; i < servers1Port.length; ++i) { for (let i = 0; i < servers1Port.length; ++i) {
var serv = servers1Port[i]; const serv = servers1Port[i];
scp("early-hack-template.script", serv); ns.scp("early-hack-template.script", serv);
brutessh(serv); ns.brutessh(serv);
nuke(serv); ns.nuke(serv);
exec("early-hack-template.script", serv, 12); ns.exec("early-hack-template.script", serv, 12);
}
} }
Random Tips Random Tips
----------- -----------
* Early on in the game, it's better to spend your money on upgrading RAM and purchasing * Early on in the game, it's better to spend your money on upgrading RAM and purchasing
@ -861,7 +874,7 @@ Random Tips
as useful as your hacking stat. Do not invest too much time or money into gaining combat as useful as your hacking stat. Do not invest too much time or money into gaining combat
stat exp. stat exp.
* As a rule of thumb, your hacking target should be the server with highest max money that's * As a rule of thumb, your hacking target should be the server with highest max money that's
required hacking level is under 1/3 of your hacking level. required hacking level is under 1/2 of your hacking level.

@ -7,7 +7,6 @@ import { ITutorialEvents } from "./ui/InteractiveTutorial/ITutorialEvents";
// Ordered array of keys to Interactive Tutorial Steps // Ordered array of keys to Interactive Tutorial Steps
enum iTutorialSteps { enum iTutorialSteps {
Start, Start,
NSSelection,
GoToCharacterPage, // Click on 'Stats' page GoToCharacterPage, // Click on 'Stats' page
CharacterPage, // Introduction to 'Stats' page CharacterPage, // Introduction to 'Stats' page
CharacterGoToTerminalPage, // Go back to Terminal CharacterGoToTerminalPage, // Go back to Terminal
@ -46,7 +45,6 @@ const ITutorial = {
// Keeps track of whether each step has been done // Keeps track of whether each step has been done
stepIsDone: { stepIsDone: {
[iTutorialSteps.Start]: false, [iTutorialSteps.Start]: false,
[iTutorialSteps.NSSelection]: false,
[iTutorialSteps.GoToCharacterPage]: false, [iTutorialSteps.GoToCharacterPage]: false,
[iTutorialSteps.CharacterPage]: false, [iTutorialSteps.CharacterPage]: false,
[iTutorialSteps.CharacterGoToTerminalPage]: false, [iTutorialSteps.CharacterGoToTerminalPage]: false,

@ -139,7 +139,7 @@ const Messages: Record<MessageFilenames, Message> = {
[MessageFilenames.Jumper1]: new Message( [MessageFilenames.Jumper1]: new Message(
MessageFilenames.Jumper1, MessageFilenames.Jumper1,
`Soon you will be contacted by a hacking group known as ${FactionNames.NiteSec}. ` + `Soon you will be contacted by a hacking group known as ${FactionNames.CyberSec}. ` +
"They can help you with your search. \n\n" + "They can help you with your search. \n\n" +
"You should join them, garner their favor, and " + "You should join them, garner their favor, and " +
"exploit them for their Augmentations. But do not trust them. " + "exploit them for their Augmentations. But do not trust them. " +

@ -9,7 +9,6 @@ import ArrowBackIos from "@mui/icons-material/ArrowBackIos";
import { ITutorialEvents } from "./ITutorialEvents"; import { ITutorialEvents } from "./ITutorialEvents";
import { CopyableText } from "../React/CopyableText"; import { CopyableText } from "../React/CopyableText";
import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem"; import ListItem from "@mui/material/ListItem";
import EqualizerIcon from "@mui/icons-material/Equalizer"; import EqualizerIcon from "@mui/icons-material/Equalizer";
import LastPageIcon from "@mui/icons-material/LastPage"; import LastPageIcon from "@mui/icons-material/LastPage";
@ -28,7 +27,6 @@ import {
iTutorialSteps, iTutorialSteps,
iTutorialEnd, iTutorialEnd,
} from "../../InteractiveTutorial"; } from "../../InteractiveTutorial";
import { NSSelection } from "./NSSelection";
interface IContent { interface IContent {
content: React.ReactElement; content: React.ReactElement;
@ -47,23 +45,10 @@ const useStyles = makeStyles((theme: Theme) =>
}), }),
); );
enum Language {
None,
NS1,
NS2,
}
export function InteractiveTutorialRoot(): React.ReactElement { export function InteractiveTutorialRoot(): React.ReactElement {
const [nsSelectionOpen, setNSSelectionOpen] = useState(false);
const [language, setLanguage] = useState(Language.None);
const classes = useStyles(); const classes = useStyles();
const tutorialScriptExtension = { const tutorialScriptName = `n00dles.js`;
[Language.None]: ".script",
[Language.NS1]: ".script",
[Language.NS2]: ".js",
}[language];
const tutorialScriptName = `n00dles${tutorialScriptExtension}`;
const contents: { [number: string]: IContent | undefined } = { const contents: { [number: string]: IContent | undefined } = {
[iTutorialSteps.Start as number]: { [iTutorialSteps.Start as number]: {
@ -83,47 +68,6 @@ export function InteractiveTutorialRoot(): React.ReactElement {
), ),
canNext: true, canNext: true,
}, },
[iTutorialSteps.NSSelection as number]: {
content: (
<>
<Typography>The tutorial will adjust to your programming ability.</Typography>
<Typography>Bitburner has 2 types of scripts:</Typography>
<List>
<ListItem>
<Typography>NS1: Javascript from 2009, very simple. Recommended for beginners to programming.</Typography>
</ListItem>
<ListItem>
<Typography>
NS2: Native, modern Javascript. Recommended if you know any programming language or are serious about
learning programming.
</Typography>
</ListItem>
</List>
<Typography>
Both are available at all time and interchangeably. This choice is only for the tutorial.
</Typography>
<Button
onClick={() => {
setLanguage(Language.NS1);
iTutorialNextStep();
}}
>
Use NS1
</Button>
<Button
onClick={() => {
setLanguage(Language.NS2);
iTutorialNextStep();
}}
>
Use NS2
</Button>
<Button onClick={() => setNSSelectionOpen(true)}>More info</Button>
<br />
</>
),
canNext: false,
},
[iTutorialSteps.GoToCharacterPage as number]: { [iTutorialSteps.GoToCharacterPage as number]: {
content: ( content: (
<> <>
@ -320,7 +264,7 @@ export function InteractiveTutorialRoot(): React.ReactElement {
<Typography></Typography> <Typography></Typography>
</> </>
), ),
canNext: true, canNext: false,
}, },
[iTutorialSteps.TerminalManualHack as number]: { [iTutorialSteps.TerminalManualHack as number]: {
content: ( content: (
@ -364,7 +308,7 @@ export function InteractiveTutorialRoot(): React.ReactElement {
<Typography>Let's head home before creating our first script!</Typography> <Typography>Let's head home before creating our first script!</Typography>
</> </>
), ),
canNext: true, canNext: false,
}, },
[iTutorialSteps.TerminalCreateScript as number]: { [iTutorialSteps.TerminalCreateScript as number]: {
content: ( content: (
@ -378,9 +322,7 @@ export function InteractiveTutorialRoot(): React.ReactElement {
</Typography> </Typography>
<Typography classes={{ root: classes.textfield }}>{"[home ~/]> nano"}</Typography> <Typography classes={{ root: classes.textfield }}>{"[home ~/]> nano"}</Typography>
<Typography> <Typography>Scripts must end with the .js extension. Let's make a script now by entering </Typography>
Scripts must end with the {tutorialScriptExtension} extension. Let's make a script now by entering{" "}
</Typography>
<Typography classes={{ root: classes.textfield }}>{`[home ~/]> nano ${tutorialScriptName}`}</Typography> <Typography classes={{ root: classes.textfield }}>{`[home ~/]> nano ${tutorialScriptName}`}</Typography>
<Typography> <Typography>
@ -394,20 +336,12 @@ export function InteractiveTutorialRoot(): React.ReactElement {
content: ( content: (
<> <>
<Typography> <Typography>
This is the script editor. You can use it to program your scripts.{" "} This is the script editor. You can use it to program your scripts. Copy and paste the following code into
{language !== Language.NS2 && <>Scripts are written in a simplified version of javascript.</>} Copy and the script editor: <br />
paste the following code into the script editor: <br />
</Typography> </Typography>
<Typography classes={{ root: classes.code }}> <Typography classes={{ root: classes.code }}>
{language !== Language.NS2 && ( {
<CopyableText
value={`while(true) {
hack('n00dles');
}`}
/>
)}
{language === Language.NS2 && (
<CopyableText <CopyableText
value={`export async function main(ns) { value={`export async function main(ns) {
while(true) { while(true) {
@ -415,7 +349,7 @@ export function InteractiveTutorialRoot(): React.ReactElement {
} }
}`} }`}
/> />
)} }
</Typography> </Typography>
<Typography> <Typography>
For anyone with basic programming experience, this code should be straightforward. This script will For anyone with basic programming experience, this code should be straightforward. This script will
@ -589,8 +523,17 @@ export function InteractiveTutorialRoot(): React.ReactElement {
content: ( content: (
<Typography> <Typography>
This page contains a lot of different documentation about the game's content and mechanics. I know it's a lot, 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 but I highly suggest you read (or at least skim) through this before you start playing.
tutorial. Hope you enjoy the game! <br />
<br />
The{" "}
<a href="https://bitburner.readthedocs.io/en/latest/guidesandtips/gettingstartedguideforbeginnerprogrammers.html">
Getting Started
</a>{" "}
contains the guide for new players, navigating you through most of early game.
<br />
<br />
That's the end of the tutorial. Hope you enjoy the game!
</Typography> </Typography>
), ),
canNext: true, canNext: true,
@ -614,7 +557,6 @@ export function InteractiveTutorialRoot(): React.ReactElement {
if (content === undefined) throw new Error("error in the tutorial"); if (content === undefined) throw new Error("error in the tutorial");
return ( return (
<> <>
<NSSelection open={nsSelectionOpen} onClose={() => setNSSelectionOpen(false)} />
<Paper square sx={{ maxWidth: "70vw", p: 2 }}> <Paper square sx={{ maxWidth: "70vw", p: 2 }}>
{content.content} {content.content}
{step !== iTutorialSteps.TutorialPageInfo && ( {step !== iTutorialSteps.TutorialPageInfo && (

@ -1,82 +0,0 @@
import Editor from "@monaco-editor/react";
import { Tab, Tabs, Typography } from "@mui/material";
import React from "react";
import { Modal } from "../React/Modal";
import * as monaco from "monaco-editor";
type IStandaloneCodeEditor = monaco.editor.IStandaloneCodeEditor;
interface IProps {
open: boolean;
onClose: () => void;
}
const ns1Example = `while(true) {
hack('n00dles');
}`;
const ns2Example = `/** @param {NS} ns */
export async function main(ns) {
while(true) {
await ns.hack('n00dles');
}
}`;
export function NSSelection(props: IProps): React.ReactElement {
const [value, setValue] = React.useState(0);
function handleChange(event: React.SyntheticEvent, tab: number): void {
setValue(tab);
}
function onMount(editor: IStandaloneCodeEditor): void {
editor.updateOptions({ readOnly: true });
}
return (
<Modal open={props.open} onClose={props.onClose} sx={{ zIndex: 999999 }}>
<Tabs variant="fullWidth" value={value} onChange={handleChange}>
<Tab label="NS1" />
<Tab label="NS2" />
</Tabs>
{value === 0 && (
<>
<Typography>
These scripts end with '.script'. Using a very old interpreted version of javascript. It is perfect for
beginner to programming.
</Typography>
<Typography>Example script using NS1:</Typography>
<Editor
loading={<></>}
defaultLanguage="javascript"
defaultValue={ns1Example}
height={`${300}px`}
theme={"vs-dark"}
onMount={onMount}
options={{ fontSize: 30 }}
/>
</>
)}
{value === 1 && (
<>
<Typography>
These scripts end with '.js'. Scripts using ns2 are running natively along the game. If you know any
programming language you should be using this. However if you're unfamiliar with javascript Promises you
might want to read up on them a little bit before diving in.
</Typography>
<Typography>Example script using NS2:</Typography>
<Editor
loading={<></>}
defaultLanguage="javascript"
defaultValue={ns2Example}
height={`${300}px`}
theme={"vs-dark"}
options={{ fontSize: 30 }}
/>
</>
)}
</Modal>
);
}