Merge pull request #134 from danielyxie/dev

All v0.29.0 changes
This commit is contained in:
danielyxie 2017-09-19 13:57:41 -05:00 committed by GitHub
commit 9d8e7fca51
19 changed files with 3626 additions and 3194 deletions

@ -321,7 +321,7 @@ a:link, a:visited {
position: absolute; /* Stay in place */ position: absolute; /* Stay in place */
right: 0; right: 0;
top: 0; top: 0;
height: 195px; /* Full height */ height: 205px; /* Full height */
/*margin: 50% auto;*/ /*margin: 50% auto;*/
padding: 5px; padding: 5px;
border: 2px solid var(--my-highlight-color); border: 2px solid var(--my-highlight-color);

6302
dist/bundle.js vendored

File diff suppressed because one or more lines are too long

@ -780,6 +780,7 @@
<div id="log-box-container"> <div id="log-box-container">
<div id="log-box-content"> <div id="log-box-content">
<span id="log-box-close"> &times; </span> <span id="log-box-close"> &times; </span>
<p id="log-box-text-header"> </p>
<p id="log-box-text"> </p> <p id="log-box-text"> </p>
</div> </div>
</div> </div>
@ -829,6 +830,10 @@
</div> </div>
</div> </div>
<!-- Mission container -->
<div id="mission-container" class="generic-fullscreen-container">
</div>
<!-- Work in progress screen --> <!-- Work in progress screen -->
<div id="work-in-progress-container" class="generic-fullscreen-container"> <div id="work-in-progress-container" class="generic-fullscreen-container">
<p id="work-in-progress-text"> </p> <p id="work-in-progress-text"> </p>

@ -57,13 +57,20 @@ function initBitNodes() {
"along with its consciousness and intelligence, couldn't be replicated. They said the complexity " + "along with its consciousness and intelligence, couldn't be replicated. They said the complexity " +
"of the brain results from unpredictable, nonlinear interactions that couldn't be modeled " + "of the brain results from unpredictable, nonlinear interactions that couldn't be modeled " +
"by 1's and 0's. They were wrong.<br><br>" + "by 1's and 0's. They were wrong.<br><br>" +
"In this BitNode <br><br>" + "In this BitNode:<br><br>" +
"The base security level of servers is doubled<br>" +
"The starting money on servers is halved, but the maximum money is doubled<br>" +
"Most methods of earning money now give significantly less<br>" +
"Augmentations are more expensive<br>" +
"Hacking experience gain rates are reduced<br><br>" +
"Destroying this BitNode will give you Source-File 5, or if you already have this Source-File it will " + "Destroying this BitNode will give you Source-File 5, or if you already have this Source-File it will " +
"upgrade its level up to a maximum of 3. This Source-File grants you a special new stat called Intelligence. " + "upgrade its level up to a maximum of 3. This Source-File grants you a special new stat called Intelligence. " +
"Intelligence is unique because it is permanent and persistent (it never gets reset back to 1). However " + "Intelligence is unique because it is permanent and persistent (it never gets reset back to 1). However " +
"gaining Intelligence experience is much slower than other stats, and it is also hidden (you won't know " + "gaining Intelligence experience is much slower than other stats, and it is also hidden (you won't know " +
"when you gain experience and how much). Higher Intelligence levels will boost your production for many actions " + "when you gain experience and how much). Higher Intelligence levels will boost your production for many actions " +
"in the game. This source file will also raise all of your hacking-related multipliers by:<br><br>" + "in the game. <br><br>" +
"In addition, this Source-File will unlock the getBitNodeMultipliers() Netscript function, " +
"and will also raise all of your hacking-related multipliers by:<br><br>" +
"Level 1: 4%<br>" + "Level 1: 4%<br>" +
"Level 2: 6%<br>" + "Level 2: 6%<br>" +
"Level 3: 7%"); "Level 3: 7%");
@ -100,6 +107,7 @@ let BitNodeMultipliers = {
ServerStartingMoney: 1, ServerStartingMoney: 1,
ServerGrowthRate: 1, ServerGrowthRate: 1,
ServerWeakenRate: 1, ServerWeakenRate: 1,
ServerStartingSecurity: 1,
ManualHackMoney: 1, ManualHackMoney: 1,
ScriptHackMoney: 1, ScriptHackMoney: 1,
@ -131,7 +139,7 @@ function initBitNodeMultipliers() {
} }
switch (Player.bitNodeN) { switch (Player.bitNodeN) {
case 1: case 1: //Source Genesis (every multiplier is 1)
break; break;
case 2: //Rise of the Underworld case 2: //Rise of the Underworld
BitNodeMultipliers.ServerMaxMoney = 0.2; BitNodeMultipliers.ServerMaxMoney = 0.2;
@ -152,6 +160,16 @@ function initBitNodeMultipliers() {
BitNodeMultipliers.CrimeExpGain = 0.5; BitNodeMultipliers.CrimeExpGain = 0.5;
BitNodeMultipliers.FactionWorkRepGain = 0.75; BitNodeMultipliers.FactionWorkRepGain = 0.75;
break; break;
case 5: //Artificial intelligence
BitNodeMultipliers.ServerMaxMoney = 2;
BitNodeMultipliers.ServerStartingSecurity = 2;
BitNodeMultipliers.ServerStartingMoney = 0.5;
BitNodeMultipliers.ScriptHackMoney = 0.25;
BitNodeMultipliers.HacknetNodeMoney = 0.2;
BitNodeMultipliers.CrimeMoney = 0.5;
BitNodeMultipliers.AugmentationMoneyCost = 2;
BitNodeMultipliers.HackExpGain = 0.5;
break;
case 11: //The Big Crash case 11: //The Big Crash
BitNodeMultipliers.ServerMaxMoney = 0.1; BitNodeMultipliers.ServerMaxMoney = 0.1;
BitNodeMultipliers.ServerStartingMoney = 0.25; BitNodeMultipliers.ServerStartingMoney = 0.25;

@ -1,5 +1,5 @@
let CONSTANTS = { let CONSTANTS = {
Version: "0.28.6", Version: "0.29.0",
//Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience //Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
//and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then //and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@ -58,8 +58,9 @@ let CONSTANTS = {
ScriptScpRamCost: 0.5, ScriptScpRamCost: 0.5,
ScriptKillRamCost: 0.5, //Kill and killall ScriptKillRamCost: 0.5, //Kill and killall
ScriptHasRootAccessRamCost: 0.05, ScriptHasRootAccessRamCost: 0.05,
ScriptGetHostnameRamCost: 0.05, ScriptGetHostnameRamCost: 0.05, //getHostname() and getIp()
ScriptGetHackingLevelRamCost: 0.05, ScriptGetHackingLevelRamCost: 0.05, //getHackingLevel() and getIntelligence()
ScriptGetMultipliersRamCost: 4.0, //getHackingMultipliers() and getBitNodeMultipliers()
ScriptGetServerCost: 0.1, ScriptGetServerCost: 0.1,
ScriptFileExistsRamCost: 0.1, ScriptFileExistsRamCost: 0.1,
ScriptIsRunningRamCost: 0.1, ScriptIsRunningRamCost: 0.1,
@ -115,9 +116,14 @@ let CONSTANTS = {
//Intelligence-related constants //Intelligence-related constants
IntelligenceCrimeWeight: 0.05, //Weight for how much int affects crime success rates IntelligenceCrimeWeight: 0.05, //Weight for how much int affects crime success rates
IntelligenceInfiltrationWeight: 0.1, //Weight for how much int affects infiltration success rates IntelligenceInfiltrationWeight: 0.1, //Weight for how much int affects infiltration success rates
IntelligenceCrimeBaseExpGain: 0.0001, IntelligenceCrimeBaseExpGain: 0.0002,
IntelligenceProgramBaseExpGain: 1000, //Program required hack level divided by this to determine int exp gain IntelligenceProgramBaseExpGain: 1000, //Program required hack level divided by this to determine int exp gain
IntelligenceTerminalHackBaseExpGain: 200, //Hacking exp divided by this to determine int exp gain IntelligenceTerminalHackBaseExpGain: 200, //Hacking exp divided by this to determine int exp gain
IntelligenceSingFnBaseExpGain: 0.0005,
//Hacking Missions
HackingMissionRepToDiffConversion: 5000, //Faction rep is divided by this to get mission difficulty
HackingMissionRepToRewardConversion: 20, //Faction rep divided byt his to get mission rep reward
//Gang constants //Gang constants
GangRespectToReputationRatio: 2, //Respect is divided by this to get rep gain GangRespectToReputationRatio: 2, //Respect is divided by this to get rep gain
@ -238,9 +244,10 @@ let CONSTANTS = {
"encounter diminishing returns in your hacking (since you are only hacking a certain percentage). You can " + "encounter diminishing returns in your hacking (since you are only hacking a certain percentage). You can " +
"increase the amount of money on a server using a script and the grow() function in Netscript.<br><br>" + "increase the amount of money on a server using a script and the grow() function in Netscript.<br><br>" +
"<h1>Server Security</h1><br>" + "<h1>Server Security</h1><br>" +
"Each server has a security level, typically between 1 and 100. It is possible for a server to have a security " + "Each server has a security level, typically between 1 and 100. A higher number means the server has stronger security. " +
"level 100 or higher, in which case hacking a server will become impossible. A higher number means " + "It is possible for a server to have a security level of 100 or higher, in which case hacking that server " +
"the server has stronger security. As mentioned above, a server's security level is an important factor " + "will become impossible (0% chance to hack).<br><br>" +
"As mentioned above, a server's security level is an important factor " +
"to consider when hacking. You can check a server's security level using the 'analyze' command, although this " + "to consider when hacking. You can check a server's security level using the 'analyze' command, although this " +
"only gives an estimate (with 5% uncertainty). You can also check a server's security in a script, using the " + "only gives an estimate (with 5% uncertainty). You can also check a server's security in a script, using the " +
"<i>getServerSecurityLevel(server)</i> function in Netscript. See the Netscript documentation for more details. " + "<i>getServerSecurityLevel(server)</i> function in Netscript. See the Netscript documentation for more details. " +
@ -406,8 +413,11 @@ let CONSTANTS = {
"<i>print(x)</i><br>Prints a value or a variable to the scripts logs (which can be viewed with the 'tail [script]' terminal command ). <br><br>" + "<i>print(x)</i><br>Prints a value or a variable to the scripts logs (which can be viewed with the 'tail [script]' terminal command ). <br><br>" +
"<i>tprint(x)</i><br>Prints a value or a variable to the Terminal<br><br>" + "<i>tprint(x)</i><br>Prints a value or a variable to the Terminal<br><br>" +
"<i>clearLog()</i><br>Clears the script's logs. <br><br>" + "<i>clearLog()</i><br>Clears the script's logs. <br><br>" +
"<i>scan(hostname/ip)</i><br>Returns an array containing the hostnames of all servers that are one node away from the specified server. " + "<i>scan(hostname/ip, [hostnames=true])</i><br>Returns an array containing the hostnames or IPs of all servers that are one node away from the specified server. " +
"The argument must be a string containing the IP or hostname of the target server. The hostnames in the returned array are strings.<br><br>" + "The argument must be a string containing the IP or hostname of the target server. The second argument is a boolean that specifies whether " +
"the hostnames or IPs of the scanned servers should be output. If it is true then hostnames will be returned, and if false then IP addresses will. " +
"This second argument is optional and, if ommitted, the function will output " +
"the hostnames of the scanned servers. The hostnames/IPs in the returned array are strings.<br><br>" +
"<i>nuke(hostname/ip)</i><br>Run NUKE.exe on the target server. NUKE.exe must exist on your home computer. Does NOT work while offline <br> Example: nuke('foodnstuff'); <br><br>" + "<i>nuke(hostname/ip)</i><br>Run NUKE.exe on the target server. NUKE.exe must exist on your home computer. Does NOT work while offline <br> Example: nuke('foodnstuff'); <br><br>" +
"<i>brutessh(hostname/ip)</i><br>Run BruteSSH.exe on the target server. BruteSSH.exe must exist on your home computer. Does NOT work while offline <br> Example: brutessh('foodnstuff');<br><br>" + "<i>brutessh(hostname/ip)</i><br>Run BruteSSH.exe on the target server. BruteSSH.exe must exist on your home computer. Does NOT work while offline <br> Example: brutessh('foodnstuff');<br><br>" +
"<i>ftpcrack(hostname/ip)</i><br>Run FTPCrack.exe on the target server. FTPCrack.exe must exist on your home computer. Does NOT work while offline <br> Example: ftpcrack('foodnstuff');<br><br>" + "<i>ftpcrack(hostname/ip)</i><br>Run FTPCrack.exe on the target server. FTPCrack.exe must exist on your home computer. Does NOT work while offline <br> Example: ftpcrack('foodnstuff');<br><br>" +
@ -457,17 +467,66 @@ let CONSTANTS = {
"kill('foo.script', getHostname(), 1, 'foodnstuff');<br><br>" + "kill('foo.script', getHostname(), 1, 'foodnstuff');<br><br>" +
"<i>killall(hostname/ip)</i><br> Kills all running scripts on the specified server. This function takes a single argument which " + "<i>killall(hostname/ip)</i><br> Kills all running scripts on the specified server. This function takes a single argument which " +
"must be a string containing the hostname or IP of the target server. This function will always return true. <br><br>" + "must be a string containing the hostname or IP of the target server. This function will always return true. <br><br>" +
"<i>scp(script, hostname/ip)</i><br>Copies a script or literature (.lit) file to another server. The first argument is a string with " + "<i>scp(script, [source], destination)</i><br>Copies a script or literature (.lit) file to another server. The first argument is a string with " +
"the filename of the script or literature file " + "the filename of the script or literature file " +
"to be copied. The second argument is a string with the hostname or IP of the destination server. Returns true if the script is successfully " + "to be copied. The next two arguments are strings containing the hostname/IPs of the source and target server. " +
"copied over and false otherwise. <br> Example: scp('hack-template.script', 'foodnstuff');<br><br>" + "The source refers to the server from which the script/literature file will be copied, while the destination " +
"refers to the server to which it will be copied. The source server argument is optional, and if ommitted the source " +
"will be the current server (the server on which the script is running). Returns true if the script/literature file is " +
"successfully copied over and false otherwise. <br><br>" +
"Example: scp('hack-template.script', 'foodnstuff'); //Copies hack-template.script from the current server to foodnstuff<br>" +
"Example: scp('foo.lit', 'helios', 'home'); //Copies foo.lit from the helios server to the home computer<br><br>" +
"<i>ls(hostname/ip)</i><br>Returns an array containing the names of all files on the specified server. The argument must be a " + "<i>ls(hostname/ip)</i><br>Returns an array containing the names of all files on the specified server. The argument must be a " +
"string with the hostname or IP of the target server.<br><br>" + "string with the hostname or IP of the target server.<br><br>" +
"<i>hasRootAccess(hostname/ip)</i><br> Returns a boolean (true or false) indicating whether or not the Player has root access to a server. " + "<i>hasRootAccess(hostname/ip)</i><br> Returns a boolean (true or false) indicating whether or not the Player has root access to a server. " +
"The argument passed in must be a string with either the hostname or IP of the target server. Does NOT work while offline.<br> " + "The argument passed in must be a string with either the hostname or IP of the target server. Does NOT work while offline.<br> " +
"Example:<br>if (hasRootAccess('foodnstuff') == false) {<br>&nbsp;&nbsp;&nbsp;&nbsp;nuke('foodnstuff');<br>}<br><br>" + "Example:<br>if (hasRootAccess('foodnstuff') == false) {<br>&nbsp;&nbsp;&nbsp;&nbsp;nuke('foodnstuff');<br>}<br><br>" +
"<i>getIp()</i><br>Returns a string with the IP Address of the server that the script is running on <br><br>" +
"<i>getHostname()</i><br>Returns a string with the hostname of the server that the script is running on<br><br>" + "<i>getHostname()</i><br>Returns a string with the hostname of the server that the script is running on<br><br>" +
"<i>getHackingLevel()</i><br>Returns the Player's current hacking level. Does NOT work while offline<br><br> " + "<i>getHackingLevel()</i><br>Returns the Player's current hacking level. Does NOT work while offline<br><br> " +
"<i>getIntelligence()</i><br>Returns the Player's current intelligence level. Requires Source-File 5 to run<br><br>" +
"<i>getHackingMultipliers()</i><br>Returns an object containing the Player's hacking related multipliers. " +
"These multipliers are returned in integer forms, not percentages (e.g. 1.5 instead of 150%). " +
"The object has the following structure:<br><br>" +
"{<br>" +
"chance: Player's hacking chance multiplier<br>" +
"speed: Player's hacking speed multiplier<br>" +
"money: Player's hacking money stolen multiplier<br>" +
"growth: Player's hacking growth multiplier<br>" +
"}<br><br>Example:<br><br>" +
"mults = getHackingMultipliers();<br>" +
"print(mults.chance);<br>" +
"print(mults.growth);<br><br>" +
"<i>getBitNodeMultipliers()</i><br>Returns an object containing the current BitNode multipliers. " +
"This function requires Source-File 5 in order to run. The multipliers are returned in integer forms, not percentages " +
"(e.g. 1.5 instead of 150%). The multipliers represent the difference between the current BitNode and the " +
"original BitNode (BitNode-1). For example, if the 'CrimeMoney' multiplier has a value of 0.1 then that means " +
"that committing crimes in the current BitNode will only give 10% of the money you would have received in " +
"BitNode-1. The object has the following structure (subject to change in the future):<br><br>" +
"{<br>" +
"ServerMaxMoney: 1,<br>" +
"ServerStartingMoney: 1,<br>" +
"ServerGrowthRate: 1,<br>" +
"ServerWeakenRate: 1,<br>" +
"ServerStartingSecurity: 1,<br>" +
"ManualHackMoney: 1,<br>" +
"ScriptHackMoney: 1,<br>" +
"CompanyWorkMoney: 1,<br>" +
"CrimeMoney: 1,<br>" +
"HacknetNodeMoney: 1,<br>" +
"CompanyWorkExpGain: 1,<br>" +
"ClassGymExpGain: 1,<br>" +
"FactionWorkExpGain: 1,<br>" +
"HackExpGain: 1,<br>" +
"CrimeExpGain: 1,<br>" +
"FactionWorkRepGain: 1,<br>" +
"FactionPassiveRepGain: 1,<br>" +
"AugmentationRepCost: 1,<br>" +
"AugmentationMoneyCost: 1,<br>" +
"}<br><br>Example:<br><br>" +
"mults = getBitNodeMultipliers();<br>" +
"print(mults.ServerMaxMoney);<br>" +
"print(mults.HackExpGain);<br><br>" +
"<i>getServerMoneyAvailable(hostname/ip)</i><br> Returns the amount of money available on a server. The argument passed in must be a string with either the " + "<i>getServerMoneyAvailable(hostname/ip)</i><br> Returns the amount of money available on a server. The argument passed in must be a string with either the " +
"hostname or IP of the target server. Does NOT work while offline <br> Example: getServerMoneyAvailable('foodnstuff');<br><br>" + "hostname or IP of the target server. Does NOT work while offline <br> Example: getServerMoneyAvailable('foodnstuff');<br><br>" +
"<i>getServerMaxMoney(hostname/ip)</i><br>Returns the maximum amount of money that can be available on a server. The argument passed in must be a string with " + "<i>getServerMaxMoney(hostname/ip)</i><br>Returns the maximum amount of money that can be available on a server. The argument passed in must be a string with " +
@ -523,6 +582,8 @@ let CONSTANTS = {
"(2, 4, 8, etc...). <br><br>" + "(2, 4, 8, etc...). <br><br>" +
"This function returns the hostname of the newly purchased server as a string. If the function fails to purchase a server, then it will return " + "This function returns the hostname of the newly purchased server as a string. If the function fails to purchase a server, then it will return " +
"an empty string. The function will fail if the arguments passed in are invalid or if the player does not have enough money to purchase the specified server.<br><br>" + "an empty string. The function will fail if the arguments passed in are invalid or if the player does not have enough money to purchase the specified server.<br><br>" +
"<i>deleteServer(hostname)</i><br>Deletes one of the servers you've purchased with the specified hostname. The function will fail if " +
"there are any scripts running on the specified server. Returns true if successful and false otherwise<br><br>" +
"<i>round(n)</i><br>Rounds the number n to the nearest integer. If the argument passed in is not a number, then the function will return 0.<br><br>" + "<i>round(n)</i><br>Rounds the number n to the nearest integer. If the argument passed in is not a number, then the function will return 0.<br><br>" +
"<i>write(port, data)</i><br>Writes data to a port. The first argument must be a number between 1 and 10 that specifies the port. The second " + "<i>write(port, data)</i><br>Writes data to a port. The first argument must be a number between 1 and 10 that specifies the port. The second " +
"argument defines the data to write to the port. If the second argument is not specified then it will write an empty string to the port.<br><br>" + "argument defines the data to write to the port. If the second argument is not specified then it will write an empty string to the port.<br><br>" +
@ -896,16 +957,19 @@ let CONSTANTS = {
"World Stock Exchange account and TIX API Access<br>", "World Stock Exchange account and TIX API Access<br>",
LatestUpdate: LatestUpdate:
"v0.28.6<br>" + "v0.29.0<br>" +
"-Time required to create programs now scales better with hacking level, and should generally be much faster<br>" + "-Added BitNode-5: Artificial Intelligence<br>" +
"-Added serverExists(hostname/ip) and getScriptExpGain(scriptname, ip, args...) Netscript functions<br>" + "-Added getIp(), getIntelligence(), getHackingMultipliers(), and getBitNodeMultipliers() Netscript functions (requires Source-File 5)<br>" +
"-Short circuiting && and || logical operators should now work<br>" + "-Updated scan() Netscript function so that you can choose to have it print IPs rather than hostnames<br>" +
"-Assigning to multidimensional arrays should now work<br>" + "-Refactored scp() Netscript function so that it takes an optional 'source server' argument<br>" +
"-Scripts will no longer wait for hack/grow/weaken functions to finish if they are killed. They will die immediately<br>" + "-For Infiltration, decreased the percentage by which the security level increases by " +
"-The script loop that checks whether any scripts need to be started/stopped now runs every 6 seconds rather than 10 " + "about 10% for every location<br>" +
"(resulting in less delays when stopping/starting scripts)<br>" + "-Using :w in the script editor's Vim keybinding mode should now save and quit to Terminal<br>" +
"-Fixed several bugs/exploits<br>" + "-Some minor optimizations that should reduce the size of the save file<br>" +
"-Added some description for BitNode-5 (not implemented yet, should be soon though)<br>", "-scan-analyze Terminal command will no longer show your purchased servers, unless you pass a '-a' flag into the command<br>" +
"-After installing the Red Pill augmentation from Daedalus, the message telling you to find 'The-Cave' " +
"will now repeatedly pop up regardless of whether or not you have messages suppressed<br>" +
"-Various bugfixes",
} }

@ -24,7 +24,7 @@ let TerminalHelpText =
"rm [file] Delete a file from the server<br>" + "rm [file] Delete a file from the server<br>" +
"run [name] [-t] [n] [args...] Execute a program or script<br>" + "run [name] [-t] [n] [args...] Execute a program or script<br>" +
"scan Prints all immediately-available network connections<br>" + "scan Prints all immediately-available network connections<br>" +
"scan-analyze [d] Prints info for all servers up to <i>d</i> nodes away<br>" + "scan-analyze [d] [-a] Prints info for all servers up to <i>d</i> nodes away<br>" +
"scp [file] [server] Copies a script or .lit file to a destination server<br>" + "scp [file] [server] Copies a script or .lit file to a destination server<br>" +
"sudov Shows whether you have root access on this computer<br>" + "sudov Shows whether you have root access on this computer<br>" +
"tail [script] [args...] Displays dynamic logs for the specified script<br>" + "tail [script] [args...] Displays dynamic logs for the specified script<br>" +
@ -153,7 +153,7 @@ let HelpTexts = {
scan: "scan<br>" + scan: "scan<br>" +
"Prints all immediately-available network connection. This will print a list of all servers that you can currently connect " + "Prints all immediately-available network connection. This will print a list of all servers that you can currently connect " +
"to using the 'connect' Terminal command.", "to using the 'connect' Terminal command.",
"scan-analyze": "scan-analyze [depth]<br>" + "scan-analyze": "scan-analyze [depth] [-a]<br>" +
"Prints detailed information about all servers up to [depth] nodes away on the network. Calling " + "Prints detailed information about all servers up to [depth] nodes away on the network. Calling " +
"'scan-analyze 1' will display information for the same servers that are shown by the 'scan' Terminal " + "'scan-analyze 1' will display information for the same servers that are shown by the 'scan' Terminal " +
"command. This command also shows the relative paths to reach each server.<br><br>" + "command. This command also shows the relative paths to reach each server.<br><br>" +
@ -162,7 +162,9 @@ let HelpTexts = {
"5 and 10, respectively.<br><br>" + "5 and 10, respectively.<br><br>" +
"The information 'scan-analyze' displays about each server includes whether or not you have root access to it, " + "The information 'scan-analyze' displays about each server includes whether or not you have root access to it, " +
"its required hacking level, the number of open ports required to run NUKE.exe on it, and how much RAM " + "its required hacking level, the number of open ports required to run NUKE.exe on it, and how much RAM " +
"it has", "it has.<br><br>" +
"By default, this command will not display servers that you have purchased. However, you can pass in the " +
"-a flag at the end of the command if you would like to enable that.",
scp: "scp [filename] [target server]<br>" + scp: "scp [filename] [target server]<br>" +
"Copies the specified file from the current server to the target server. " + "Copies the specified file from the current server to the target server. " +
"This command only works for script files (.script extension) and literature files (.lit extension). " + "This command only works for script files (.script extension) and literature files (.lit extension). " +

@ -420,7 +420,7 @@ function displayLocationContent() {
purchaseTor.style.display = "block"; purchaseTor.style.display = "block";
purchaseHomeRam.style.display = "block"; purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumECorp, setInfiltrateButton(infiltrate, Locations.AevumECorp,
6000, 116, 150, 9.5); 6000, 116, 150, 8.5);
break; break;
case Locations.AevumBachmanAndAssociates: case Locations.AevumBachmanAndAssociates:
@ -433,7 +433,7 @@ function displayLocationContent() {
businessJob.style.display = "block"; businessJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumBachmanAndAssociates, setInfiltrateButton(infiltrate, Locations.AevumBachmanAndAssociates,
1500, 42, 60, 6.5); 1500, 42, 60, 5.75);
break; break;
case Locations.AevumClarkeIncorporated: case Locations.AevumClarkeIncorporated:
@ -446,7 +446,7 @@ function displayLocationContent() {
businessJob.style.display = "block"; businessJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumClarkeIncorporated, setInfiltrateButton(infiltrate, Locations.AevumClarkeIncorporated,
2400, 34, 75, 6); 2400, 34, 75, 5.4);
break; break;
case Locations.AevumFulcrumTechnologies: case Locations.AevumFulcrumTechnologies:
@ -465,7 +465,7 @@ function displayLocationContent() {
purchaseTor.style.display = "block"; purchaseTor.style.display = "block";
purchaseHomeRam.style.display = "block"; purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumFulcrumTechnologies, setInfiltrateButton(infiltrate, Locations.AevumFulcrumTechnologies,
6000, 96, 100, 10); 6000, 96, 100, 9);
break; break;
case Locations.AevumAeroCorp: case Locations.AevumAeroCorp:
@ -477,7 +477,7 @@ function displayLocationContent() {
networkEngineerJob.style.display = "block"; networkEngineerJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumAeroCorp, setInfiltrateButton(infiltrate, Locations.AevumAeroCorp,
2000, 32, 50, 7); 2000, 32, 50, 6.3);
break; break;
case Locations.AevumGalacticCybersystems: case Locations.AevumGalacticCybersystems:
@ -490,7 +490,7 @@ function displayLocationContent() {
networkEngineerJob.style.display = "block"; networkEngineerJob.style.display = "block";
businessJob.style.display = "block"; businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumGalacticCybersystems, setInfiltrateButton(infiltrate, Locations.AevumGalacticCybersystems,
1400, 30, 50, 6); 1400, 30, 50, 5.3);
break; break;
case Locations.AevumWatchdogSecurity: case Locations.AevumWatchdogSecurity:
@ -504,7 +504,7 @@ function displayLocationContent() {
securityJob.style.display = "block"; securityJob.style.display = "block";
agentJob.style.display = "block"; agentJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumWatchdogSecurity, setInfiltrateButton(infiltrate, Locations.AevumWatchdogSecurity,
850, 16, 30, 5); 850, 16, 30, 4.5);
break; break;
case Locations.AevumRhoConstruction: case Locations.AevumRhoConstruction:
@ -513,7 +513,7 @@ function displayLocationContent() {
softwareJob.style.display = "block"; softwareJob.style.display = "block";
businessJob.style.display = "block"; businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumRhoConstruction, setInfiltrateButton(infiltrate, Locations.AevumRhoConstruction,
600, 12, 20, 3); 600, 12, 20, 2.7);
break; break;
case Locations.AevumPolice: case Locations.AevumPolice:
@ -522,7 +522,7 @@ function displayLocationContent() {
softwareJob.style.display = "block"; softwareJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumPolice, setInfiltrateButton(infiltrate, Locations.AevumPolice,
700, 14, 25, 3.5); 700, 14, 25, 3.2);
break; break;
case Locations.AevumNetLinkTechnologies: case Locations.AevumNetLinkTechnologies:
@ -540,7 +540,7 @@ function displayLocationContent() {
purchaseTor.style.display = "block"; purchaseTor.style.display = "block";
purchaseHomeRam.style.display = "block"; purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumNetLinkTechnologies, setInfiltrateButton(infiltrate, Locations.AevumNetLinkTechnologies,
160, 10, 15, 2); 160, 10, 15, 1.8);
break; break;
case Locations.AevumCrushFitnessGym: case Locations.AevumCrushFitnessGym:
@ -574,7 +574,7 @@ function displayLocationContent() {
businessJob.style.display = "block"; businessJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.ChongqingKuaiGongInternational, setInfiltrateButton(infiltrate, Locations.ChongqingKuaiGongInternational,
5500, 48, 100, 10); 5500, 48, 100, 9);
break; break;
case Locations.ChongqingSolarisSpaceSystems: case Locations.ChongqingSolarisSpaceSystems:
@ -586,7 +586,7 @@ function displayLocationContent() {
networkEngineerJob.style.display = "block"; networkEngineerJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.ChongqingSolarisSpaceSystems, setInfiltrateButton(infiltrate, Locations.ChongqingSolarisSpaceSystems,
3600, 26, 75, 9.5); 3600, 26, 75, 8.6);
break; break;
@ -615,7 +615,7 @@ function displayLocationContent() {
businessJob.style.display = "block"; businessJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12MegaCorp, setInfiltrateButton(infiltrate, Locations.Sector12MegaCorp,
6000, 114, 125, 11); 6000, 114, 125, 9.8);
break; break;
case Locations.Sector12BladeIndustries: case Locations.Sector12BladeIndustries:
@ -628,7 +628,7 @@ function displayLocationContent() {
businessJob.style.display = "block"; businessJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12BladeIndustries, setInfiltrateButton(infiltrate, Locations.Sector12BladeIndustries,
3000, 46, 100, 7.5); 3000, 46, 100, 6.7);
break; break;
case Locations.Sector12FourSigma: case Locations.Sector12FourSigma:
@ -641,7 +641,7 @@ function displayLocationContent() {
businessJob.style.display = "block"; businessJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12FourSigma, setInfiltrateButton(infiltrate, Locations.Sector12FourSigma,
1500, 58, 100, 11.5); 1500, 58, 100, 10.2);
break; break;
case Locations.Sector12IcarusMicrosystems: case Locations.Sector12IcarusMicrosystems:
@ -654,7 +654,7 @@ function displayLocationContent() {
networkEngineerJob.style.display = "block"; networkEngineerJob.style.display = "block";
businessJob.style.display = "block"; businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12IcarusMicrosystems, setInfiltrateButton(infiltrate, Locations.Sector12IcarusMicrosystems,
900, 32, 70, 8.5); 900, 32, 70, 7.8);
break; break;
case Locations.Sector12UniversalEnergy: case Locations.Sector12UniversalEnergy:
@ -667,7 +667,7 @@ function displayLocationContent() {
networkEngineerJob.style.display = "block"; networkEngineerJob.style.display = "block";
businessJob.style.display = "block"; businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12UniversalEnergy, setInfiltrateButton(infiltrate, Locations.Sector12UniversalEnergy,
775, 24, 50, 7); 775, 24, 50, 6.3);
break; break;
case Locations.Sector12DeltaOne: case Locations.Sector12DeltaOne:
@ -679,7 +679,7 @@ function displayLocationContent() {
networkEngineerJob.style.display = "block"; networkEngineerJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12DeltaOne, setInfiltrateButton(infiltrate, Locations.Sector12DeltaOne,
1200, 38, 75, 7); 1200, 38, 75, 6.3);
break; break;
case Locations.Sector12CIA: case Locations.Sector12CIA:
@ -692,7 +692,7 @@ function displayLocationContent() {
securityJob.style.display = "block"; securityJob.style.display = "block";
agentJob.style.display = "block"; agentJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12CIA, setInfiltrateButton(infiltrate, Locations.Sector12CIA,
1450, 44, 80, 8.5); 1450, 44, 80, 7.6);
break; break;
case Locations.Sector12NSA: case Locations.Sector12NSA:
@ -705,7 +705,7 @@ function displayLocationContent() {
securityJob.style.display = "block"; securityJob.style.display = "block";
agentJob.style.display = "block"; agentJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12NSA, setInfiltrateButton(infiltrate, Locations.Sector12NSA,
1400, 40, 80, 8); 1400, 40, 80, 7.2);
break; break;
case Locations.Sector12AlphaEnterprises: case Locations.Sector12AlphaEnterprises:
@ -719,7 +719,7 @@ function displayLocationContent() {
purchaseTor.style.display = "block"; purchaseTor.style.display = "block";
purchaseHomeRam.style.display = "block"; purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12AlphaEnterprises, setInfiltrateButton(infiltrate, Locations.Sector12AlphaEnterprises,
250, 14, 40, 3); 250, 14, 40, 2.7);
break; break;
case Locations.Sector12CarmichaelSecurity: case Locations.Sector12CarmichaelSecurity:
@ -733,7 +733,7 @@ function displayLocationContent() {
securityJob.style.display = "block"; securityJob.style.display = "block";
agentJob.style.display = "block"; agentJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12CarmichaelSecurity, setInfiltrateButton(infiltrate, Locations.Sector12CarmichaelSecurity,
500, 18, 60, 3); 500, 18, 60, 2.7);
break; break;
case Locations.Sector12FoodNStuff: case Locations.Sector12FoodNStuff:
@ -749,7 +749,7 @@ function displayLocationContent() {
employeeJob.style.display = "block"; employeeJob.style.display = "block";
employeePartTimeJob.style.display = "block"; employeePartTimeJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12JoesGuns, setInfiltrateButton(infiltrate, Locations.Sector12JoesGuns,
120, 8, 20, 2.5); 120, 8, 20, 2.2);
break; break;
case Locations.Sector12IronGym: case Locations.Sector12IronGym:
@ -782,7 +782,7 @@ function displayLocationContent() {
securityEngineerJob.style.display = "block"; securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block"; networkEngineerJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.NewTokyoDefComm, setInfiltrateButton(infiltrate, Locations.NewTokyoDefComm,
1300, 28, 70, 6); 1300, 28, 70, 5.4);
break; break;
case Locations.NewTokyoVitaLife: case Locations.NewTokyoVitaLife:
@ -795,7 +795,7 @@ function displayLocationContent() {
networkEngineerJob.style.display = "block"; networkEngineerJob.style.display = "block";
businessJob.style.display = "block"; businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.NewTokyoVitaLife, setInfiltrateButton(infiltrate, Locations.NewTokyoVitaLife,
750, 22, 100, 5.5); 750, 22, 100, 5);
break; break;
case Locations.NewTokyoGlobalPharmaceuticals: case Locations.NewTokyoGlobalPharmaceuticals:
@ -809,7 +809,7 @@ function displayLocationContent() {
businessJob.style.display = "block"; businessJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.NewTokyoGlobalPharmaceuticals, setInfiltrateButton(infiltrate, Locations.NewTokyoGlobalPharmaceuticals,
900, 24, 80, 6); 900, 24, 80, 5.4);
break; break;
case Locations.NewTokyoNoodleBar: case Locations.NewTokyoNoodleBar:
@ -848,7 +848,7 @@ function displayLocationContent() {
purchase256gb.style.display = "block"; purchase256gb.style.display = "block";
purchaseHomeRam.style.display = "block"; purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.IshimaStormTechnologies, setInfiltrateButton(infiltrate, Locations.IshimaStormTechnologies,
700, 24, 100, 6.5); 700, 24, 100, 5.9);
break; break;
case Locations.IshimaNovaMedical: case Locations.IshimaNovaMedical:
@ -861,7 +861,7 @@ function displayLocationContent() {
networkEngineerJob.style.display = "block"; networkEngineerJob.style.display = "block";
businessJob.style.display = "block"; businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.IshimaNovaMedical, setInfiltrateButton(infiltrate, Locations.IshimaNovaMedical,
600, 20, 50, 5); 600, 20, 50, 4.5);
break; break;
case Locations.IshimaOmegaSoftware: case Locations.IshimaOmegaSoftware:
@ -879,7 +879,7 @@ function displayLocationContent() {
purchaseTor.style.display = "block"; purchaseTor.style.display = "block";
purchaseHomeRam.style.display = "block"; purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.IshimaOmegaSoftware, setInfiltrateButton(infiltrate, Locations.IshimaOmegaSoftware,
200, 10, 40, 2.5); 200, 10, 40, 2.3);
break; break;
case Locations.VolhavenTravelAgency: case Locations.VolhavenTravelAgency:
@ -912,7 +912,7 @@ function displayLocationContent() {
purchase512gb.style.display = "block"; purchase512gb.style.display = "block";
purchase1tb.style.display = "block"; purchase1tb.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenOmniTekIncorporated, setInfiltrateButton(infiltrate, Locations.VolhavenOmniTekIncorporated,
1500, 44, 100, 7); 1500, 44, 100, 6.3);
break; break;
case Locations.VolhavenNWO: case Locations.VolhavenNWO:
@ -925,7 +925,7 @@ function displayLocationContent() {
businessJob.style.display = "block"; businessJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenNWO, setInfiltrateButton(infiltrate, Locations.VolhavenNWO,
1800, 56, 200, 8); 1800, 56, 200, 7.2);
break; break;
case Locations.VolhavenHeliosLabs: case Locations.VolhavenHeliosLabs:
@ -937,7 +937,7 @@ function displayLocationContent() {
securityEngineerJob.style.display = "block"; securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block"; networkEngineerJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenHeliosLabs, setInfiltrateButton(infiltrate, Locations.VolhavenHeliosLabs,
1200, 28, 75, 6); 1200, 28, 75, 5.4);
break; break;
case Locations.VolhavenOmniaCybersystems: case Locations.VolhavenOmniaCybersystems:
@ -949,7 +949,7 @@ function displayLocationContent() {
networkEngineerJob.style.display = "block"; networkEngineerJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenOmniaCybersystems, setInfiltrateButton(infiltrate, Locations.VolhavenOmniaCybersystems,
900, 28, 90, 6.5); 900, 28, 90, 5.8);
break; break;
case Locations.VolhavenLexoCorp: case Locations.VolhavenLexoCorp:
@ -963,7 +963,7 @@ function displayLocationContent() {
businessJob.style.display = "block"; businessJob.style.display = "block";
securityJob.style.display = "block"; securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenLexoCorp, setInfiltrateButton(infiltrate, Locations.VolhavenLexoCorp,
500, 14, 40, 3.5); 500, 14, 40, 3.1);
break; break;
case Locations.VolhavenSysCoreSecurities: case Locations.VolhavenSysCoreSecurities:
@ -974,7 +974,7 @@ function displayLocationContent() {
securityEngineerJob.style.display = "block"; securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block"; networkEngineerJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenSysCoreSecurities, setInfiltrateButton(infiltrate, Locations.VolhavenSysCoreSecurities,
600, 16, 50, 4); 600, 16, 50, 3.6);
break; break;
case Locations.VolhavenCompuTek: case Locations.VolhavenCompuTek:
@ -995,7 +995,7 @@ function displayLocationContent() {
purchaseTor.style.display = "block"; purchaseTor.style.display = "block";
purchaseHomeRam.style.display = "block"; purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenCompuTek, setInfiltrateButton(infiltrate, Locations.VolhavenCompuTek,
300, 12, 35, 3.5); 300, 12, 35, 3.1);
break; break;
case Locations.VolhavenMilleniumFitnessGym: case Locations.VolhavenMilleniumFitnessGym:

@ -4,7 +4,7 @@ import {Programs} from "./CreateProgram.js";
import {Player} from "./Player.js"; import {Player} from "./Player.js";
import {GetServerByHostname} from "./Server.js"; import {GetServerByHostname} from "./Server.js";
import {Settings} from "./Settings.js"; import {Settings} from "./Settings.js";
import {dialogBoxCreate} from "../utils/DialogBox.js"; import {dialogBoxCreate, dialogBoxOpened} from "../utils/DialogBox.js";
import {Reviver, Generic_toJSON, import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js"; Generic_fromJSON} from "../utils/JSONReviver.js";
@ -27,10 +27,10 @@ Message.fromJSON = function(value) {
Reviver.constructors.Message = Message; Reviver.constructors.Message = Message;
//Sends message to player, including a pop up //Sends message to player, including a pop up
function sendMessage(msg) { function sendMessage(msg, forced=false) {
console.log("sending message: " + msg.filename); console.log("sending message: " + msg.filename);
msg.recvd = true; msg.recvd = true;
if (!Settings.SuppressMessages) { if (forced || !Settings.SuppressMessages) {
showMessage(msg); showMessage(msg);
} }
addMessageToServer(msg, "home"); addMessageToServer(msg, "home");
@ -50,6 +50,11 @@ function addMessageToServer(msg, serverHostname) {
console.log("WARNING: Did not locate " + serverHostname); console.log("WARNING: Did not locate " + serverHostname);
return; return;
} }
for (var i = 0; i < server.messages.length; ++i) {
if (server.messages[i].filename === msg.filename) {
return; //Already exists
}
}
server.messages.push(msg); server.messages.push(msg);
} }
@ -70,7 +75,11 @@ function checkForMessagesToSend() {
redpillOwned = true; redpillOwned = true;
} }
if (jumper0 && !jumper0.recvd && Player.hacking_skill >= 25) { if (redpill && redpillOwned) {
if (!dialogBoxOpened) {
sendMessage(redpill, true);
}
} else if (jumper0 && !jumper0.recvd && Player.hacking_skill >= 25) {
sendMessage(jumper0); sendMessage(jumper0);
Player.getHomeComputer().programs.push(Programs.Flight); Player.getHomeComputer().programs.push(Programs.Flight);
} else if (jumper1 && !jumper1.recvd && Player.hacking_skill >= 40) { } else if (jumper1 && !jumper1.recvd && Player.hacking_skill >= 40) {
@ -87,8 +96,6 @@ function checkForMessagesToSend() {
sendMessage(jumper4); sendMessage(jumper4);
} else if (bitrunnersTest && !bitrunnersTest.recvd && Player.hacking_skill >= 500) { } else if (bitrunnersTest && !bitrunnersTest.recvd && Player.hacking_skill >= 500) {
sendMessage(bitrunnersTest); sendMessage(bitrunnersTest);
} else if (redpill && !redpill.recvd && Player.hacking_skill >= 2000 && redpillOwned) {
sendMessage(redpill);
} }
} }

@ -474,8 +474,6 @@ function evalAssignment(exp, workerScript) {
}); });
} }
//Returns true if any of the if statements evaluated, false otherwise. Therefore, the else statement
//should evaluate if this returns false
function evaluateIf(exp, workerScript, i) { function evaluateIf(exp, workerScript, i) {
var env = workerScript.env; var env = workerScript.env;
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {

@ -2,6 +2,7 @@ import {updateActiveScriptsItems} from "./ActiveScriptsUI.js";
import {Augmentations, Augmentation, import {Augmentations, Augmentation,
augmentationExists, installAugmentations, augmentationExists, installAugmentations,
AugmentationNames} from "./Augmentations.js"; AugmentationNames} from "./Augmentations.js";
import {BitNodeMultipliers} from "./BitNode.js";
import {Companies, Company, CompanyPosition, import {Companies, Company, CompanyPosition,
CompanyPositions, companyExists} from "./Company.js"; CompanyPositions, companyExists} from "./Company.js";
import {CONSTANTS} from "./Constants.js"; import {CONSTANTS} from "./Constants.js";
@ -43,14 +44,20 @@ import {createRandomIp} from "../utils/IPAddress.js"
import {formatNumber, isString, isHTML} from "../utils/StringHelperFunctions.js"; import {formatNumber, isString, isHTML} from "../utils/StringHelperFunctions.js";
var hasSingularitySF = false; var hasSingularitySF = false;
var hasAISF = false;
var singularitySFLvl = 1; var singularitySFLvl = 1;
//Also used to check for Artificial Intelligence Source File, don't want to change
//name though
function initSingularitySFFlags() { function initSingularitySFFlags() {
for (var i = 0; i < Player.sourceFiles.length; ++i) { for (var i = 0; i < Player.sourceFiles.length; ++i) {
if (Player.sourceFiles[i].n === 4) { if (Player.sourceFiles[i].n === 4) {
hasSingularitySF = true; hasSingularitySF = true;
singularitySFLvl = Player.sourceFiles[i].lvl; singularitySFLvl = Player.sourceFiles[i].lvl;
} }
if (Player.sourceFiles[i].n === 5) {
hasAISF = true;
}
} }
} }
@ -58,14 +65,19 @@ function NetscriptFunctions(workerScript) {
return { return {
Math : Math, Math : Math,
hacknetnodes : Player.hacknetNodes, hacknetnodes : Player.hacknetNodes,
scan : function(ip=workerScript.serverIp){ scan : function(ip=workerScript.serverIp, hostnames=true){
var server = getServer(ip); var server = getServer(ip);
if (server == null) { if (server == null) {
throw makeRuntimeRejectMsg(workerScript, 'Invalid IP or hostname passed into scan() command'); throw makeRuntimeRejectMsg(workerScript, 'Invalid IP or hostname passed into scan() command');
} }
var out = []; var out = [];
for (var i = 0; i < server.serversOnNetwork.length; i++) { for (var i = 0; i < server.serversOnNetwork.length; i++) {
var entry = server.getServerOnNetwork(i).hostname; var entry;
if (hostnames) {
entry = server.getServerOnNetwork(i).hostname;
} else {
entry = server.getServerOnNetwork(i).ip;
}
if (entry == null) { if (entry == null) {
continue; continue;
} }
@ -451,22 +463,43 @@ function NetscriptFunctions(workerScript) {
workerScript.scriptRef.log("killall(): Killing all scripts on " + server.hostname + ". May take a few minutes for the scripts to die"); workerScript.scriptRef.log("killall(): Killing all scripts on " + server.hostname + ". May take a few minutes for the scripts to die");
return true; return true;
}, },
scp : function(scriptname, ip){ scp : function(scriptname, ip1, ip2){
if (scriptname === undefined || ip === undefined || arguments.length != 2) { if (arguments.length !== 2 && arguments.length !== 3) {
throw makeRuntimeRejectMsg(workerScript, "Error: scp() call has incorrect number of arguments. Takes 2 arguments"); throw makeRuntimeRejectMsg(workerScript, "Error: scp() call has incorrect number of arguments. Takes 2 or 3 arguments");
}
var destServer = getServer(ip);
if (destServer == null) {
throw makeRuntimeRejectMsg(workerScript, "Error: Invalid hostname/ip passed into scp() command: " + ip);
} }
if (!scriptname.endsWith(".lit") && !scriptname.endsWith(".script")) { if (!scriptname.endsWith(".lit") && !scriptname.endsWith(".script")) {
throw makeRuntimeRejectMsg(workerScript, "Error: scp() only works for .script and .lit files"); throw makeRuntimeRejectMsg(workerScript, "Error: scp() only works for .script and .lit files");
} }
var currServ = getServer(workerScript.serverIp); var destServer, currServ;
if (arguments.length === 3) { //scriptname, source, destination
if (scriptname === undefined || ip1 === undefined || ip2 === undefined) {
throw makeRuntimeRejectMsg(workerScript, "Error: scp() call has incorrect number of arguments. Takes 2 or 3 arguments");
}
destServer = getServer(ip2);
if (destServer == null) {
throw makeRuntimeRejectMsg(workerScript, "Error: Invalid hostname/ip passed into scp() command: " + ip);
}
currServ = getServer(ip1);
if (currServ == null) { if (currServ == null) {
throw makeRuntimeRejectMsg(workerScript, "Could not find server ip for this script. This is a bug please contact game developer"); throw makeRuntimeRejectMsg(workerScript, "Could not find server ip for this script. This is a bug please contact game developer");
} }
} else if (arguments.length === 2) { //scriptname, destination
if (scriptname === undefined || ip1 === undefined) {
throw makeRuntimeRejectMsg(workerScript, "Error: scp() call has incorrect number of arguments. Takes 2 or 3 arguments");
}
destServer = getServer(ip1);
if (destServer == null) {
throw makeRuntimeRejectMsg(workerScript, "Error: Invalid hostname/ip passed into scp() command: " + ip);
}
currServ = getServer(workerScript.serverIp);
if (currServ == null) {
throw makeRuntimeRejectMsg(workerScript, "Could not find server ip for this script. This is a bug please contact game developer");
}
}
//Scp for lit files //Scp for lit files
if (scriptname.endsWith(".lit")) { if (scriptname.endsWith(".lit")) {
@ -597,6 +630,13 @@ function NetscriptFunctions(workerScript) {
} }
return server.hasAdminRights; return server.hasAdminRights;
}, },
getIp : function() {
var scriptServer = getServer(workerScript.serverIp);
if (scriptServer == null) {
throw makeRuntimeRejectMsg(workerScript, "Could not find server. This is a bug in the game. Report to game dev");
}
return scriptServer.ip;
},
getHostname : function(){ getHostname : function(){
var scriptServer = getServer(workerScript.serverIp); var scriptServer = getServer(workerScript.serverIp);
if (scriptServer == null) { if (scriptServer == null) {
@ -609,6 +649,28 @@ function NetscriptFunctions(workerScript) {
workerScript.scriptRef.log("getHackingLevel() returned " + Player.hacking_skill); workerScript.scriptRef.log("getHackingLevel() returned " + Player.hacking_skill);
return Player.hacking_skill; return Player.hacking_skill;
}, },
getIntelligence : function () {
if (!hasAISF) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run getIntelligence(). It requires Source-File 5 to run.");
}
Player.updateSkillLevels();
workerScript.scriptRef.log("getHackingLevel() returned " + Player.intelligence);
return Player.intelligence;
},
getHackingMultipliers : function() {
return {
chance: Player.hacking_chance_mult,
speed: Player.hacking_speed_mult,
money: Player.hacking_money_mult,
growth: Player.hacking_grow_mult,
};
},
getBitNodeMultipliers: function() {
if (!hasAISF) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run getBitNodeMultipliers(). It requires Source-File 5 to run.");
}
return BitNodeMultipliers;
},
getServerMoneyAvailable : function(ip){ getServerMoneyAvailable : function(ip){
var server = getServer(ip); var server = getServer(ip);
if (server == null) { if (server == null) {
@ -1257,6 +1319,7 @@ function NetscriptFunctions(workerScript) {
case Locations.Volhaven: case Locations.Volhaven:
Player.loseMoney(200000); Player.loseMoney(200000);
Player.city = cityname; Player.city = cityname;
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
workerScript.scriptRef.log("Traveled to " + cityname); workerScript.scriptRef.log("Traveled to " + cityname);
return true; return true;
default: default:
@ -1292,6 +1355,7 @@ function NetscriptFunctions(workerScript) {
Player.getHomeComputer().serversOnNetwork.push(darkweb.ip); Player.getHomeComputer().serversOnNetwork.push(darkweb.ip);
darkweb.serversOnNetwork.push(Player.getHomeComputer().ip); darkweb.serversOnNetwork.push(Player.getHomeComputer().ip);
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
workerScript.scriptRef.log("You have purchased a Tor router!"); workerScript.scriptRef.log("You have purchased a Tor router!");
return true; return true;
}, },
@ -1427,6 +1491,7 @@ function NetscriptFunctions(workerScript) {
Player.loseMoney(cost); Player.loseMoney(cost);
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
workerScript.scriptRef.log("Purchased additional RAM for home computer! It now has " + homeComputer.maxRam + "GB of RAM."); workerScript.scriptRef.log("Purchased additional RAM for home computer! It now has " + homeComputer.maxRam + "GB of RAM.");
return true; return true;
}, },
@ -1597,6 +1662,7 @@ function NetscriptFunctions(workerScript) {
Player.factionInvitations.splice(index, 1); Player.factionInvitations.splice(index, 1);
var fac = Factions[name]; var fac = Factions[name];
joinFaction(fac); joinFaction(fac);
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
workerScript.scriptRef.log("Joined the " + name + " faction."); workerScript.scriptRef.log("Joined the " + name + " faction.");
return true; return true;
}, },
@ -1852,6 +1918,7 @@ function NetscriptFunctions(workerScript) {
var res = purchaseAugmentation(aug, fac, true); var res = purchaseAugmentation(aug, fac, true);
workerScript.scriptRef.log(res); workerScript.scriptRef.log(res);
if (isString(res) && res.startsWith("You purchased")) { if (isString(res) && res.startsWith("You purchased")) {
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
return true; return true;
} else { } else {
return false; return false;
@ -1869,6 +1936,7 @@ function NetscriptFunctions(workerScript) {
workerScript.scriptRef.log("ERROR: installAugmentations() failed because you do not have any Augmentations to be installed"); workerScript.scriptRef.log("ERROR: installAugmentations() failed because you do not have any Augmentations to be installed");
return false; return false;
} }
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
workerScript.scriptRef.log("Installing Augmentations. This will cause this script to be killed"); workerScript.scriptRef.log("Installing Augmentations. This will cause this script to be killed");
installAugmentations(); installAugmentations();
return true; return true;

@ -9,6 +9,7 @@ import {Factions, Faction, initFactions,
joinFaction} from "./Faction.js"; joinFaction} from "./Faction.js";
import {Locations} from "./Location.js"; import {Locations} from "./Location.js";
import {initMessages, Messages, Message} from "./Message.js"; import {initMessages, Messages, Message} from "./Message.js";
import {initSingularitySFFlags} from "./NetscriptFunctions.js";
import {WorkerScript, workerScripts, import {WorkerScript, workerScripts,
prestigeWorkerScripts} from "./NetscriptWorker.js"; prestigeWorkerScripts} from "./NetscriptWorker.js";
import {Player} from "./Player.js"; import {Player} from "./Player.js";
@ -219,6 +220,9 @@ function prestigeSourceFile() {
Terminal.resetTerminalInput(); Terminal.resetTerminalInput();
Engine.loadTerminalContent(); Engine.loadTerminalContent();
//Reinitialize flags in case you just finished BN-4
initSingularitySFFlags();
//Gain int exp //Gain int exp
Player.gainIntelligenceExp(5); Player.gainIntelligenceExp(5);
} }

@ -123,6 +123,9 @@ function giveSourceFile(bitNodeNumber) {
} else { } else {
var playerSrcFile = new PlayerOwnedSourceFile(bitNodeNumber, 1); var playerSrcFile = new PlayerOwnedSourceFile(bitNodeNumber, 1);
Player.sourceFiles.push(playerSrcFile); Player.sourceFiles.push(playerSrcFile);
if (bitNodeNumber === 5) { //Artificial Intelligence
Player.intelligence = 1;
}
dialogBoxCreate("You received a Source-File for destroying a Bit Node!<br><br>" + dialogBoxCreate("You received a Source-File for destroying a Bit Node!<br><br>" +
sourceFile.name + "<br><br>" + sourceFile.info); sourceFile.name + "<br><br>" + sourceFile.info);
} }
@ -206,7 +209,7 @@ function loadBitVerse(destroyedBitNodeNum) {
var elemId = "bitnode-" + i.toString(); var elemId = "bitnode-" + i.toString();
var elem = clearEventListeners(elemId); var elem = clearEventListeners(elemId);
if (elem == null) {return;} if (elem == null) {return;}
if (i === 1 || i === 2 || i === 4 || i === 11) { if (i === 1 || i === 2 || i === 4 || i === 5 || i === 11) {
elem.addEventListener("click", function() { elem.addEventListener("click", function() {
var bitNodeKey = "BitNode" + i; var bitNodeKey = "BitNode" + i;
var bitNode = BitNodes[bitNodeKey]; var bitNode = BitNodes[bitNodeKey];

@ -73,7 +73,16 @@ BitburnerSaveObject.prototype.saveGame = function() {
this.AllGangsSave = JSON.stringify(AllGangs); this.AllGangsSave = JSON.stringify(AllGangs);
} }
var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this)))); var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this))));
try {
window.localStorage.setItem("bitburnerSave", saveString); window.localStorage.setItem("bitburnerSave", saveString);
} catch(e) {
if (e.code == 22) {
dialogBoxCreate("Failed to save game because the size of the save file " +
"is too large. Consider killing several of your scripts to " +
"fix this, or increasing the size of your browsers localStorage");
}
}
console.log("Game saved!"); console.log("Game saved!");
Engine.createStatusText("Game saved!"); Engine.createStatusText("Game saved!");

@ -12,6 +12,8 @@ require('brace/theme/xcode');
require("brace/keybinding/vim"); require("brace/keybinding/vim");
require("brace/keybinding/emacs"); require("brace/keybinding/emacs");
import {CONSTANTS} from "./Constants.js"; import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js"; import {Engine} from "./engine.js";
import {iTutorialSteps, iTutorialNextStep, import {iTutorialSteps, iTutorialNextStep,
@ -85,7 +87,17 @@ function scriptEditorInit() {
editor.getSession().setUseSoftTabs(softTabChkBox.checked); editor.getSession().setUseSoftTabs(softTabChkBox.checked);
}; };
}; //Configure some of the VIM keybindings
ace.config.loadModule('ace/keyboard/vim', function(module) {
var VimApi = module.CodeMirror.Vim;
VimApi.defineEx('write', 'w', function(cm, input) {
saveAndCloseScriptEditor();
});
VimApi.defineEx('quit', 'q', function(cm, input) {
Engine.loadTerminalContent();
});
});
}
document.addEventListener("DOMContentLoaded", scriptEditorInit, false); document.addEventListener("DOMContentLoaded", scriptEditorInit, false);
//Updates line number and RAM usage in script //Updates line number and RAM usage in script
@ -223,8 +235,12 @@ function calculateRamUsage(codeCopy) {
var killCount = numOccurrences(codeCopy, "kill(") + numOccurrences(codeCopy, "killall("); var killCount = numOccurrences(codeCopy, "kill(") + numOccurrences(codeCopy, "killall(");
var scpCount = numOccurrences(codeCopy, "scp("); var scpCount = numOccurrences(codeCopy, "scp(");
var hasRootAccessCount = numOccurrences(codeCopy, "hasRootAccess("); var hasRootAccessCount = numOccurrences(codeCopy, "hasRootAccess(");
var getHostnameCount = numOccurrences(codeCopy, "getHostname("); var getHostnameCount = numOccurrences(codeCopy, "getHostname(") +
var getHackingLevelCount = numOccurrences(codeCopy, "getHackingLevel("); numOccurrences(codeCopy, "getIp(");
var getHackingLevelCount = numOccurrences(codeCopy, "getHackingLevel(") +
numOccurrences(codeCopy, "getIntelligence(");
var getMultipliersCount = numOccurrences(codeCopy, "getHackingMultipliers(") +
numOccurrences(codeCopy, "getBitNodeMultipliers(");
var getServerCount = numOccurrences(codeCopy, "getServerMoneyAvailable(") + var getServerCount = numOccurrences(codeCopy, "getServerMoneyAvailable(") +
numOccurrences(codeCopy, "getServerMaxMoney(") + numOccurrences(codeCopy, "getServerMaxMoney(") +
numOccurrences(codeCopy, "getServerSecurityLevel(") + numOccurrences(codeCopy, "getServerSecurityLevel(") +
@ -304,6 +320,7 @@ function calculateRamUsage(codeCopy) {
(hasRootAccessCount * CONSTANTS.ScriptHasRootAccessRamCost) + (hasRootAccessCount * CONSTANTS.ScriptHasRootAccessRamCost) +
(getHostnameCount * CONSTANTS.ScriptGetHostnameRamCost) + (getHostnameCount * CONSTANTS.ScriptGetHostnameRamCost) +
(getHackingLevelCount * CONSTANTS.ScriptGetHackingLevelRamCost) + (getHackingLevelCount * CONSTANTS.ScriptGetHackingLevelRamCost) +
(getMultipliersCount * CONSTANTS.ScriptGetMultipliersRamCost) +
(getServerCount * CONSTANTS.ScriptGetServerCost) + (getServerCount * CONSTANTS.ScriptGetServerCost) +
(fileExistsCount * CONSTANTS.ScriptFileExistsRamCost) + (fileExistsCount * CONSTANTS.ScriptFileExistsRamCost) +
(isRunningCount * CONSTANTS.ScriptIsRunningRamCost) + (isRunningCount * CONSTANTS.ScriptIsRunningRamCost) +
@ -485,19 +502,7 @@ function RunningScript(script, args) {
this.threads = 1; this.threads = 1;
//[MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken] //[MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken]
this.dataMap = new AllServersMap([0, 0, 0, 0]); this.dataMap = new AllServersMap([0, 0, 0, 0], true);
}
RunningScript.prototype.reset = function() {
this.scriptRef.updateRamUsage();
this.offlineRunningTime = 0.01; //Seconds
this.offlineMoneyMade = 0;
this.offlineExpGained = 0;
this.onlineRunningTime = 0.01; //Seconds
this.onlineMoneyMade = 0;
this.onlineExpGained = 0;
this.logs = [];
} }
RunningScript.prototype.log = function(txt) { RunningScript.prototype.log = function(txt) {
@ -524,7 +529,7 @@ RunningScript.prototype.clearLog = function() {
RunningScript.prototype.recordHack = function(serverIp, moneyGained, n=1) { RunningScript.prototype.recordHack = function(serverIp, moneyGained, n=1) {
if (this.dataMap == null) { if (this.dataMap == null) {
//[MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken] //[MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken]
this.dataMap = new AllServersMap([0, 0, 0, 0]); this.dataMap = new AllServersMap([0, 0, 0, 0], true);
} }
this.dataMap[serverIp][0] += moneyGained; this.dataMap[serverIp][0] += moneyGained;
this.dataMap[serverIp][1] += n; this.dataMap[serverIp][1] += n;
@ -534,7 +539,7 @@ RunningScript.prototype.recordHack = function(serverIp, moneyGained, n=1) {
RunningScript.prototype.recordGrow = function(serverIp, n=1) { RunningScript.prototype.recordGrow = function(serverIp, n=1) {
if (this.dataMap == null) { if (this.dataMap == null) {
//[MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken] //[MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken]
this.dataMap = new AllServersMap([0, 0, 0, 0]); this.dataMap = new AllServersMap([0, 0, 0, 0], true);
} }
this.dataMap[serverIp][2] += n; this.dataMap[serverIp][2] += n;
} }
@ -543,7 +548,7 @@ RunningScript.prototype.recordGrow = function(serverIp, n=1) {
RunningScript.prototype.recordWeaken = function(serverIp, n=1) { RunningScript.prototype.recordWeaken = function(serverIp, n=1) {
if (this.dataMap == null) { if (this.dataMap == null) {
//[MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken] //[MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken]
this.dataMap = new AllServersMap([0, 0, 0, 0]); this.dataMap = new AllServersMap([0, 0, 0, 0], true);
} }
this.dataMap[serverIp][3] += n; this.dataMap[serverIp][3] += n;
} }
@ -561,9 +566,12 @@ Reviver.constructors.RunningScript = RunningScript;
//Creates an object that creates a map/dictionary with the IP of each existing server as //Creates an object that creates a map/dictionary with the IP of each existing server as
//a key. Initializes every key with a specified value that can either by a number or an array //a key. Initializes every key with a specified value that can either by a number or an array
function AllServersMap(arr=false) { function AllServersMap(arr=false, filterOwned=false) {
for (var ip in AllServers) { for (var ip in AllServers) {
if (AllServers.hasOwnProperty(ip)) { if (AllServers.hasOwnProperty(ip)) {
if (filterOwned && (AllServers[ip].purchasedByPlayer || AllServers[ip].hostname === "home")) {
continue;
}
if (arr) { if (arr) {
this[ip] = [0, 0, 0, 0]; this[ip] = [0, 0, 0, 0];
} else { } else {
@ -573,14 +581,6 @@ function AllServersMap(arr=false) {
} }
} }
AllServersMap.prototype.reset = function() {
for (var ip in this) {
if (this.hasOwnProperty(ip)) {
this[ip] = 0;
}
}
}
AllServersMap.prototype.printConsole = function() { AllServersMap.prototype.printConsole = function() {
for (var ip in this) { for (var ip in this) {
if (this.hasOwnProperty(ip)) { if (this.hasOwnProperty(ip)) {

@ -32,7 +32,7 @@ function Server(ip=createRandomIp(), hostname="", organizationName="",
//RAM, CPU speed and Scripts //RAM, CPU speed and Scripts
this.maxRam = maxRam; //GB this.maxRam = maxRam; //GB
this.ramUsed = 0; this.ramUsed = 0;
this.cpuSpeed = 1; //MHz this.cpuCores = 1; //Max of 8, affects hacking times and Hacking MIssion starting Cores
this.scripts = []; this.scripts = [];
this.runningScripts = []; //Stores RunningScript objects this.runningScripts = []; //Stores RunningScript objects
@ -78,8 +78,8 @@ Server.prototype.setHackingParameters = function(requiredHackingSkill, moneyAvai
this.moneyAvailable = moneyAvailable * BitNodeMultipliers.ServerStartingMoney; this.moneyAvailable = moneyAvailable * BitNodeMultipliers.ServerStartingMoney;
} }
this.moneyMax = 25 * this.moneyAvailable * BitNodeMultipliers.ServerMaxMoney; this.moneyMax = 25 * this.moneyAvailable * BitNodeMultipliers.ServerMaxMoney;
this.hackDifficulty = hackDifficulty; this.hackDifficulty = hackDifficulty * BitNodeMultipliers.ServerStartingSecurity;
this.baseDifficulty = hackDifficulty; this.baseDifficulty = hackDifficulty * BitNodeMultipliers.ServerStartingSecurity;
this.minDifficulty = Math.max(1, Math.round(hackDifficulty / 3)); this.minDifficulty = Math.max(1, Math.round(hackDifficulty / 3));
this.serverGrowth = serverGrowth; this.serverGrowth = serverGrowth;
} }
@ -118,7 +118,9 @@ Server.prototype.getScript = function(scriptName) {
//Strengthens a server's security level (difficulty) by the specified amount //Strengthens a server's security level (difficulty) by the specified amount
Server.prototype.fortify = function(amt) { Server.prototype.fortify = function(amt) {
this.hackDifficulty += amt; this.hackDifficulty += amt;
if (this.hackDifficulty > 99) {this.hackDifficulty = 99;} //Place some arbitrarily limit that realistically should never happen unless someone is
//screwing around with the game
if (this.hackDifficulty > 1000000) {this.hackDifficulty = 1000000;}
} }
Server.prototype.weaken = function(amt) { Server.prototype.weaken = function(amt) {

@ -13,6 +13,9 @@ import {iTutorialNextStep, iTutorialSteps,
currITutorialStep} from "./InteractiveTutorial.js"; currITutorialStep} from "./InteractiveTutorial.js";
import {showLiterature} from "./Literature.js"; import {showLiterature} from "./Literature.js";
import {showMessage, Message} from "./Message.js"; import {showMessage, Message} from "./Message.js";
import {scriptCalculateHackingTime,
scriptCalculateGrowTime,
scriptCalculateWeakenTime} from "./NetscriptEvaluator.js";
import {killWorkerScript, addWorkerScript} from "./NetscriptWorker.js"; import {killWorkerScript, addWorkerScript} from "./NetscriptWorker.js";
import {Player} from "./Player.js"; import {Player} from "./Player.js";
import {hackWorldDaemon} from "./RedPill.js"; import {hackWorldDaemon} from "./RedPill.js";
@ -1028,7 +1031,17 @@ let Terminal = {
if (commandArray.length == 1) { if (commandArray.length == 1) {
Terminal.executeScanAnalyzeCommand(1); Terminal.executeScanAnalyzeCommand(1);
} else if (commandArray.length == 2) { } else if (commandArray.length == 2) {
var depth = Number(commandArray[1]); var all = false;
if (commandArray[1].endsWith("-a")) {
all = true;
commandArray[1] = commandArray[1].replace("-a", "");
}
var depth;
if (commandArray[1].length === 0) {
depth = 1;
} else {
depth = Number(commandArray[1]);
}
if (isNaN(depth) || depth < 0) { if (isNaN(depth) || depth < 0) {
post("Incorrect usage of scan-analyze command. depth argument must be positive numeric"); post("Incorrect usage of scan-analyze command. depth argument must be positive numeric");
return; return;
@ -1044,7 +1057,7 @@ let Terminal = {
post("You cannot scan-analyze with that high of a depth. Maximum depth is 10"); post("You cannot scan-analyze with that high of a depth. Maximum depth is 10");
return; return;
} }
Terminal.executeScanAnalyzeCommand(depth); Terminal.executeScanAnalyzeCommand(depth, all);
} else { } else {
post("Incorrect usage of scan-analyze command. usage: scan-analyze [depth]"); post("Incorrect usage of scan-analyze command. usage: scan-analyze [depth]");
} }
@ -1372,12 +1385,13 @@ let Terminal = {
} }
}, },
executeScanAnalyzeCommand: function(depth=1) { executeScanAnalyzeCommand: function(depth=1, all=false) {
//We'll use the AllServersMap as a visited() array //We'll use the AllServersMap as a visited() array
//TODO Using array as stack for now, can make more efficient //TODO Using array as stack for now, can make more efficient
post("~~~~~~~~~~ Beginning scan-analyze ~~~~~~~~~~"); post("~~~~~~~~~~ Beginning scan-analyze ~~~~~~~~~~");
post(" "); post(" ");
var visited = new AllServersMap(); var visited = new AllServersMap();
var stack = []; var stack = [];
var depthQueue = [0]; var depthQueue = [0];
var currServ = Player.getCurrentServer(); var currServ = Player.getCurrentServer();
@ -1385,8 +1399,10 @@ let Terminal = {
while(stack.length != 0) { while(stack.length != 0) {
var s = stack.pop(); var s = stack.pop();
var d = depthQueue.pop(); var d = depthQueue.pop();
if (visited[s.ip] || d > depth) { if (!all && s.purchasedByPlayer && s.hostname != "home") {
continue; continue; //Purchased server
} else if (visited[s.ip] || d > depth) {
continue; //Already visited or out-of-depth
} else { } else {
visited[s.ip] = 1; visited[s.ip] = 1;
} }

@ -435,6 +435,19 @@ let Engine = {
displayCharacterOverviewInfo: function() { displayCharacterOverviewInfo: function() {
if (Player.hp == null) {Player.hp = Player.max_hp;} if (Player.hp == null) {Player.hp = Player.max_hp;}
if (Player.intelligence >= 1) {
document.getElementById("character-overview-text").innerHTML =
("Hp: " + Player.hp + " / " + Player.max_hp + "<br>" +
"Money: " + numeral(Player.money.toNumber()).format('($0.000a)') + "<br>" +
"Hack: " + (Player.hacking_skill).toLocaleString() + "<br>" +
"Str: " + (Player.strength).toLocaleString() + "<br>" +
"Def: " + (Player.defense).toLocaleString() + "<br>" +
"Dex: " + (Player.dexterity).toLocaleString() + "<br>" +
"Agi: " + (Player.agility).toLocaleString() + "<br>" +
"Cha: " + (Player.charisma).toLocaleString() + "<br>" +
"Int: " + (Player.intelligence).toLocaleString()
).replace( / /g, "&nbsp;" );
} else {
document.getElementById("character-overview-text").innerHTML = document.getElementById("character-overview-text").innerHTML =
("Hp: " + Player.hp + " / " + Player.max_hp + "<br>" + ("Hp: " + Player.hp + " / " + Player.max_hp + "<br>" +
"Money: " + numeral(Player.money.toNumber()).format('($0.000a)') + "<br>" + "Money: " + numeral(Player.money.toNumber()).format('($0.000a)') + "<br>" +
@ -445,6 +458,7 @@ let Engine = {
"Agi: " + (Player.agility).toLocaleString() + "<br>" + "Agi: " + (Player.agility).toLocaleString() + "<br>" +
"Cha: " + (Player.charisma).toLocaleString() "Cha: " + (Player.charisma).toLocaleString()
).replace( / /g, "&nbsp;" ); ).replace( / /g, "&nbsp;" );
}
}, },
/* Display character info */ /* Display character info */
@ -930,8 +944,12 @@ let Engine = {
if (Engine.Counters.messages <= 0) { if (Engine.Counters.messages <= 0) {
checkForMessagesToSend(); checkForMessagesToSend();
if (Augmentations[AugmentationNames.TheRedPill].owned) {
Engine.Counters.messages = 600; //2 minutes for Red pill message
} else {
Engine.Counters.messages = 150; Engine.Counters.messages = 150;
} }
}
if (Engine.Counters.stockTick <= 0) { if (Engine.Counters.stockTick <= 0) {
if (Player.hasWseAccount) { if (Player.hasWseAccount) {

@ -61,4 +61,4 @@ function dialogBoxCreate(txt) {
}, 400); }, 400);
} }
export {dialogBoxCreate}; export {dialogBoxCreate, dialogBoxOpened};

@ -39,13 +39,15 @@ var logBoxCurrentScript = null;
function logBoxCreate(script) { function logBoxCreate(script) {
logBoxCurrentScript = script; logBoxCurrentScript = script;
logBoxOpen(); logBoxOpen();
document.getElementById("log-box-text-header").innerHTML =
logBoxCurrentScript.filename + " " + printArray(logBoxCurrentScript.args) + ":<br><br>";
logBoxUpdateText(); logBoxUpdateText();
} }
function logBoxUpdateText() { function logBoxUpdateText() {
var txt = document.getElementById("log-box-text"); var txt = document.getElementById("log-box-text");
if (logBoxCurrentScript && logBoxOpened && txt) { if (logBoxCurrentScript && logBoxOpened && txt) {
txt.innerHTML = logBoxCurrentScript.filename + printArray(logBoxCurrentScript.args) + ":<br><br>"; txt.innerHTML = "";
for (var i = 0; i < logBoxCurrentScript.logs.length; ++i) { for (var i = 0; i < logBoxCurrentScript.logs.length; ++i) {
txt.innerHTML += logBoxCurrentScript.logs[i]; txt.innerHTML += logBoxCurrentScript.logs[i];
txt.innerHTML += "<br>"; txt.innerHTML += "<br>";