Fixed merge conflicts with dev

This commit is contained in:
danielyxie 2018-10-17 15:43:48 -05:00
commit c4dbfa43c9
19 changed files with 6674 additions and 6116 deletions

10393
dist/engine.bundle.js vendored

File diff suppressed because it is too large Load Diff

74
dist/engine.css vendored

@ -94,7 +94,8 @@ a:visited {
/* Tool tips (when hovering over an element */
.tooltip {
display: inline-block;
position: relative; }
position: relative;
/* Positioned to left of element rather than right */ }
.tooltip .tooltiptext {
visibility: hidden;
width: 300px;
@ -107,6 +108,24 @@ a:visited {
pointer-events: none;
position: absolute;
z-index: 99; }
.tooltip .tooltiptextleft {
visibility: hidden;
width: 300px;
background-color: var(--my-background-color);
border: 2px solid var(--my-highlight-color);
color: #fff;
text-align: center;
padding: 4px;
top: 50%;
left: 50%;
transform: translate(-100%, -100%);
/* Backwards compatibility */
-webkit-transform: translate(-100%, -100%);
-moz-transform: translate(-100%, -100%);
-o-transform: translate(-100%, -100%);
-ms-transform: translate(-100%, -100%);
position: absolute;
z-index: 99; }
/* Same thing as a normal tooltip except its a bit higher */
.tooltip .tooltiptexthigh {
@ -122,21 +141,6 @@ a:visited {
position: absolute;
z-index: 99; }
/* Similar to a normal tooltip except its positioned on the left of the element
rather than the right to avoid exceeding the elements normal width */
.tooltip .tooltiptextleft {
visibility: hidden;
width: 300px;
background-color: var(--my-background-color);
border: 2px solid var(--my-highlight-color);
color: #fff;
text-align: center;
padding: 4px;
left: 40%;
bottom: -10%;
position: absolute;
z-index: 99; }
.tooltip:hover .tooltiptext,
.tooltip:hover .tooltiptexthigh,
.tooltip:hover .tooltiptextleft {
@ -144,14 +148,14 @@ a:visited {
/* help tip. Question mark that opens popup with info/details */
.help-tip {
content: '?';
padding: 1px;
margin-top: 5px;
margin-left: 3px;
color: #fff;
background-color: black;
border: 1px solid #fff;
border-radius: 5px;
display: inline-block; }
color: #fff;
content: '?';
display: inline-block;
margin-left: 3px;
padding: 1px; }
.help-tip-big {
content: '?';
@ -419,7 +423,7 @@ a:visited {
.accordion-header:after {
content: '\2795';
/* "plus" sign (+) */
font-size: 13px;
font-size: 14px;
float: right;
color: transparent;
text-shadow: 0 0 0 #fff;
@ -473,6 +477,9 @@ a:visited {
.charisma-purple {
color: #a671d1; }
.smallfont {
font-size: 13px; }
/* COLORS */
/* Attributes */
/**
@ -563,8 +570,9 @@ button {
font-weight: bold;
margin: 4px;
padding: 4px;
background-color: #000; }
.accordion-button:hover, .accordion-button:focus {
background-color: #000;
/* TODO focus selector? */ }
.accordion-button:hover, .accordion-button:active {
color: #fff;
text-decoration: none;
cursor: pointer; }
@ -2041,6 +2049,8 @@ button {
#gang-container {
position: fixed;
padding: 6px; }
#gang-container p, #gang-container pre {
font-size: 15px; }
#gang-container select {
background-color: black;
color: white; }
@ -2054,5 +2064,19 @@ button {
float: left;
width: 30%; }
/**
* Showing owned upgrades in the Equipment Box
*/
.gang-owned-upgrades-div {
display: inline-block;
margin-left: 6px;
width: 75%; }
.gang-owned-upgrade {
border: 1px solid white;
font-size: 12px;
margin: 1px;
padding: 1px; }
/*# sourceMappingURL=engine.css.map*/

1017
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -13,6 +13,7 @@ hack
:param string hostname/ip: IP or hostname of the target server to hack
:returns: The amount of money stolen if the hack is successful, and zero otherwise
:RAM cost: 0.1 GB
Function that is used to try and hack servers to steal money and gain hacking experience. The runtime for this command depends
on your hacking level and the target server's security level. In order to hack a server you must first gain root access
@ -35,6 +36,7 @@ grow
:param string hostname/ip: IP or hostname of the target server to grow
:returns: The number by which the money on the server was multiplied for the growth
:RAM cost: 0.15 GB
Use your hacking skills to increase the amount of money available on a server. The runtime for this command depends on your hacking
level and the target server's security level. When grow() completes, the money available on a target server will be increased by a
@ -57,6 +59,7 @@ weaken
:param string hostname.ip: IP or hostname of the target server to weaken
:returns: The amount by which the target server's security level was decreased. This is equivalent to 0.05 multiplied
by the number of script threads
:RAM cost: 0.15 GB
Use your hacking skills to attack a server's security, lowering the server's security level. The runtime for this command
depends on your hacking level and the target server's security level. This function lowers the security level of the target
@ -75,6 +78,7 @@ sleep
.. js:function:: sleep(n)
:param number n: Number of milliseconds to sleep
:RAM cost: 0 GB
Suspends the script for n milliseconds.
@ -84,6 +88,7 @@ print
.. js:function:: print(x)
:param x: Value to be printed
:RAM cost: 0 GB
Prints a value or a variable to the script's logs.
@ -93,6 +98,7 @@ tprint
.. js:function:: tprint(x)
:param x: Value to be printed
:RAM cost: 0 GB
Prints a value or a variable to the Terminal
@ -101,6 +107,8 @@ clearLog
.. js:function:: clearLog()
:RAM cost: 0 GB
Clears the script's logs
disableLog
@ -109,6 +117,7 @@ disableLog
.. js:function:: disableLog(fn)
:param string fn: Name of function for which to disable logging
:RAM cost: 0 GB
Disables logging for the given function. Logging can be disabled for
all functions by passing 'ALL' as the argument.
@ -125,6 +134,7 @@ enableLog
.. js:function:: enableLog(fn)
:param string fn: Name of function for which to enable logging
:RAM cost: 0 GB
Re-enables logging for the given function. If 'ALL' is passed into this function
as an argument, then it will revert the effects of disableLog('ALL')
@ -135,6 +145,7 @@ isLogEnabled
.. js:function:: isLogEnabled(fn)
:param string fn: Name of function to check
:RAM cost: 0 GB
Returns a boolean indicating whether or not logging is enabled for that
function (or 'ALL')
@ -144,6 +155,8 @@ getScriptLogs
.. js:function:: getScriptLogs()
:RAM cost: 0 GB
Returns the script's logs. The logs are returned as an array, where each
line is an element in the array. The most recently logged line is at the
end of the array.
@ -158,6 +171,7 @@ scan
:param string hostname/ip: IP or hostname of the server to scan
:param boolean: Optional boolean specifying whether the function should output hostnames (if true) or IP addresses (if false)
:RAM cost: 0.2 GB
Returns an array containing the hostnames or IPs of all servers that are one node way from the specified target server. The
hostnames/IPs in the returned array are strings.
@ -168,6 +182,7 @@ nuke
.. js:function:: nuke(hostname/ip)
:param string hostname/ip: IP or hostname of the target server
:RAM cost: 0 GB
Runs the NUKE.exe program on the target server. NUKE.exe must exist on your home computer.
@ -181,6 +196,7 @@ brutessh
.. js:function:: brutessh(hostname/ip)
:param string hostname/ip: IP or hostname of the target server
:RAM cost: 0 GB
Runs the BruteSSH.exe program on the target server. BruteSSH.exe must exist on your home computer.
@ -194,6 +210,7 @@ ftpcrack
.. js:function:: ftpcrack(hostname/ip)
:param string hostname/ip: IP or hostname of the target server
:RAM cost: 0 GB
Runs the FTPCrack.exe program on the target server. FTPCrack.exe must exist on your home computer.
@ -207,6 +224,7 @@ relaysmtp
.. js:function:: relaysmtp(hostname/ip)
:param string hostname/ip: IP or hostname of the target server
:RAM cost: 0 GB
Runs the relaySMTP.exe program on the target server. relaySMTP.exe must exist on your home computer.
@ -220,6 +238,7 @@ httpworm
.. js:function:: httpworm(hostname/ip)
:param string hostname/ip: IP or hostname of the target server
:RAM cost: 0 GB
Runs the HTTPWorm.exe program on the target server. HTTPWorm.exe must exist on your home computer.
@ -233,6 +252,7 @@ sqlinject
.. js:function:: sqlinject(hostname/ip)
:param string hostname/ip: IP or hostname of the target server
:RAM cost: 0 GB
Runs the SQLInject.exe program on the target server. SQLInject.exe must exist on your home computer.
@ -250,6 +270,7 @@ run
:param args...:
Additional arguments to pass into the new script that is being run. Note that if any arguments are being
passed into the new script, then the second argument *numThreads* must be filled in with a value.
:RAM cost: 1 GB
Run a script as a separate process. This function can only be used to run scripts located on the current server (the server
running the script that calls this function).
@ -282,6 +303,7 @@ exec
:param args...:
Additional arguments to pass into the new script that is being run. Note that if any arguments are being
passed into the new script, then the third argument *numThreads* must be filled in with a value.
:RAM cost: 1.3 GB
Run a script as a separate process on a specified server. This is similar to the *run* function except
that it can be used to run a script on any server, instead of just the current server.
@ -311,6 +333,7 @@ spawn
:param number numThreads: Number of threads to spawn new script with. Will be rounded to nearest integer
:param args...:
Additional arguments to pass into the new script that is being run.
:RAM cost: 2 GB
Terminates the current script, and then after a delay of about 20 seconds it will execute the newly-specified script.
The purpose of this function is to execute a new script without being constrained by the RAM usage of the current one.
@ -330,6 +353,7 @@ kill
:param string script: Filename of the script to kill
:param string hostname/ip: IP or hostname of the server on which to kill the script
:param args...: Arguments to identify which script to kill
:RAM cost: 0.5 GB
Kills the script on the target server specified by the script's name and arguments. Remember that scripts
are uniquely identified by both their name and arguments. For example, if *foo.script* is run with the argument 1, then this
@ -357,6 +381,7 @@ killall
.. js:function:: killall(hostname/ip)
:param string hostname/ip: IP or hostname of the server on which to kill all scripts
:RAM cost: 0.5 GB
Kills all running scripts on the specified server. This function returns true if any scripts were killed, and
false otherwise. In other words, it will return true if there are any scripts running on the target server.
@ -367,6 +392,8 @@ exit
.. js:function:: exit()
:RAM cost: 0 GB
Terminates the current script immediately
scp
@ -379,6 +406,7 @@ scp
Hostname or IP of the source server, which is the server from which the file will be copied.
This argument is optional and if it's omitted the source will be the current server.
:param string destination: Hostname or IP of the destination server, which is the server to which the file will be copied.
:RAM cost: 0.6 GB
Copies a script or literature (.lit) file(s) to another server. The *files* argument can be either a string specifying a
single file to copy, or an array of strings specifying multiple files to copy.
@ -405,6 +433,7 @@ ls
:param string hostname/ip: Hostname or IP of the target server
:param string grep: a substring to search for in the filename
:RAM cost: 0 GB
Returns an array with the filenames of all files on the specified server (as strings). The returned array
is sorted in alphabetic order
@ -416,6 +445,7 @@ ps
:param string ip: Hostname or IP address of the target server.
If not specified, it will be the current server's IP by default
:RAM cost: 0 GB
Returns an array with general information about all scripts running on the specified
target server. The information for each server is given in an object with
@ -443,6 +473,7 @@ hasRootAccess
.. js:function:: hasRootAccess(hostname/ip)
:param string hostname/ip: Hostname or IP of the target server
:RAM cost: 0.05 GB
Returns a boolean indicating whether or not the player has root access to the specified target server.
@ -457,6 +488,8 @@ getHostname
.. js:function:: getHostname()
:RAM cost: 0.05 GB
Returns a string with the hostname of the server that the script is running on
getHackingLevel
@ -464,6 +497,8 @@ getHackingLevel
.. js:function:: getHackingLevel()
:RAM cost: 0.05 GB
Returns the player's current hacking level
getHackingMultipliers
@ -471,6 +506,8 @@ getHackingMultipliers
.. js:function:: getHackingMultipliers()
:RAM cost: 4 GB
Returns an object containing the Player's hacking related multipliers. These multipliers are
returned in fractional forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure::
@ -492,6 +529,8 @@ getHacknetMultipliers
.. js:function:: getHacknetMultipliers()
:RAM cost: 4 GB
Returns an object containing the Player's hacknet related multipliers. These multipliers are
returned in fractional forms, not percentages (e.g. 1.5 instead of 150%). The object has the following structure::
@ -517,6 +556,7 @@ getServerMoneyAvailable
.. js:function:: getServerMoneyAvailable(hostname/ip)
:param string hostname/ip: Hostname or IP of target server
:RAM cost: 0.1 GB
Returns the amount of money available on a server. **Running this function on the home computer will return
the player's money.**
@ -532,6 +572,7 @@ getServerMaxMoney
.. js:function:: getServerMaxMoney(hostname/ip)
:param string hostname/ip: Hostname or IP of target server
:RAM cost: 0.1 GB
Returns the maximum amount of money that can be available on a server
@ -541,6 +582,7 @@ getServerGrowth
.. js:function:: getServerGrowth(hostname/ip)
:param string hostname/ip: Hostname or IP of target server
:RAM cost: 0.1 GB
Returns the server's instrinsic "growth parameter". This growth parameter is a number
between 1 and 100 that represents how quickly the server's money grows. This parameter affects the
@ -553,6 +595,7 @@ getServerSecurityLevel
.. js:function:: getServerSecurityLevel(hostname/ip)
:param string hostname/ip: Hostname or IP of target server
:RAM cost: 0.1 GB
Returns the security level of the target server. A server's security level is denoted by a number, typically
between 1 and 100 (but it can go above 100).
@ -563,6 +606,7 @@ getServerBaseSecurityLevel
.. js:function:: getServerBaseSecurityLevel(hostname/ip)
:param string hostname/ip: Hostname or IP of target server
:RAM cost: 0.1 GB
Returns the base security level of the target server. This is the security level that the server starts out with.
This is different than *getServerSecurityLevel()* because *getServerSecurityLevel()* returns the current
@ -575,6 +619,7 @@ getServerMinSecurityLevel
.. js:function:: getServerMinSecurityLevel(hostname/ip)
:param string hostname/ip: Hostname or IP of target server
:RAM cost: 0.1 GB
Returns the minimum security level of the target server
@ -584,6 +629,7 @@ getServerRequiredHackingLevel
.. js:function:: getServerRequiredHackingLevel(hostname/ip)
:param string hostname/ip: Hostname or IP of target server
:RAM cost: 0.1 GB
Returns the required hacking level of the target server
@ -593,6 +639,7 @@ getServerNumPortsRequired
.. js:function:: getServerNumPortsRequired(hostname/ip)
:param string hostname/ip: Hostname or IP of target server
:RAM cost: 0.1 GB
Returns the number of open ports required to successfully run NUKE.exe on the specified server.
@ -602,6 +649,7 @@ getServerRam
.. js:function:: getServerRam(hostname/ip)
:param string hostname/ip: Hostname or IP of target server
:RAM cost: 0.1 GB
Returns an array with two elements that gives information about a server's memory (RAM). The first
element in the array is the amount of RAM that the server has total (in GB). The second element in
@ -619,6 +667,7 @@ serverExists
.. js:function:: serverExists(hostname/ip)
:param string hostname/ip: Hostname or IP of target server
:RAM cost: 0.1 GB
Returns a boolean denoting whether or not the specified server exists
@ -631,6 +680,7 @@ fileExists
:param string hostname/ip:
Hostname or IP of target server. This is optional. If it is not specified then the
function will use the current server as the target server
:RAM cost: 0.1 GB
Returns a boolean indicating whether the specified file exists on the target server. The filename
for scripts is case-sensitive, but for other types of files it is not. For example, *fileExists("brutessh.exe")*
@ -655,6 +705,7 @@ isRunning
:param string filename: Filename of script to check. This is case-sensitive.
:param string hostname/ip: Hostname or IP of target server
:param args...: Arguments to specify/identify which scripts to search for
:RAM cost: 0.1 GB
Returns a boolean indicating whether the specified script is running on the target server. Remember that a script is
uniquely identified by both its name and its arguments.
@ -681,6 +732,8 @@ getNextHacknetNodeCost
.. js:function:: getNextHacknetNodeCost()
:RAM cost: 0 GB
Deprecated (no longer usable). See :doc:`netscripthacknetnodeapi`
purchaseHacknetNode
@ -688,6 +741,8 @@ purchaseHacknetNode
.. js:function:: purchaseHacknetNode()
:RAM cost: 0 GB
Deprecated (no longer usable). See :doc:`netscripthacknetnodeapi`
getPurchasedServerCost
@ -695,6 +750,8 @@ getPurchasedServerCost
.. js:function:: getPurchasedServerCost(ram)
:RAM cost: 0.25 GB
:param number ram: Amount of RAM of a potential purchased server. Must be a power of 2 (2, 4, 8, 16, etc.). Maximum value of 1048576 (2^20)
Returns the cost to purchase a server with the specified amount of *ram*.
@ -712,6 +769,7 @@ purchaseServer
:param string hostname: Hostname of the purchased server
:param number ram: Amount of RAM of the purchased server. Must be a power of 2 (2, 4, 8, 16, etc.). Maximum value of 1048576 (2^20)
:RAM cost: 2.25 GB
Purchased a server with the specified hostname and amount of RAM.
@ -741,6 +799,7 @@ deleteServer
.. js:function:: deleteServer(hostname)
:param string hostname: Hostname of the server to delete
:RAM cost: 2.25 GB
Deletes one of your purchased servers, which is specified by its hostname.
@ -757,6 +816,7 @@ getPurchasedServers
:param boolean hostname:
Specifies whether hostnames or IP addresses should be returned. If it's true then hostnames will be returned, and if false
then IPs will be returned. If this argument is omitted then it is true by default
:RAM cost: 2.25 GB
Returns an array with either the hostnames or IPs of all of the servers you have purchased.
@ -765,6 +825,8 @@ getPurchasedServerLimit
.. js:function:: getPurchasedServerLimit()
:RAM cost: 0.05 GB
Returns the maximum number of servers you can purchase
getPurchasedServerMaxRam
@ -772,6 +834,8 @@ getPurchasedServerMaxRam
.. js:function:: getPurchasedServerMaxRam()
:RAM cost: 0.05 GB
Returns the maximum RAM that a purchased server can have
write
@ -782,6 +846,7 @@ write
:param string/number port/fn: Port or text file/script that will be written to
:param string data: Data to write
:param string mode: Defines the write mode. Only valid when writing to text files or scripts.
:RAM cost: 1 GB
This function can be used to either write data to a port, a text file (.txt), or a script (.script, .js, .ns)
@ -802,6 +867,7 @@ tryWrite
:param number port: Port to be written to
:param string data: Data to try to write
:returns: True if the data is successfully written to the port, and false otherwise
:RAM cost: 1 GB
Attempts to write data to the specified Netscript Port. If the port is full, the data will
not be written. Otherwise, the data will be written normally
@ -812,6 +878,7 @@ read
.. js:function:: read(port/fn)
:param string/number port/fn: Port or text file to read from
:RAM cost: 1 GB
This function is used to read data from a port, a text file (.txt), or a script (.script, .js, .ns)
@ -828,6 +895,7 @@ peek
.. js:function:: peek(port)
:param number port: Port to peek. Must be an integer between 1 and 20
:RAM cost: 1 GB
This function is used to peek at the data from a port. It returns the first element in the specified port
without removing that element. If the port is empty, the string "NULL PORT DATA" will be returned.
@ -840,6 +908,7 @@ clear
.. js:function:: clear(port/fn)
:param string/number port/fn: Port or text file to clear
:RAM cost: 1 GB
This function is used to clear data in a `Netscript Ports <http://bitburner.wikia.com/wiki/Netscript_Ports>`_ or a text file.
@ -853,6 +922,7 @@ getPortHandle
.. js:function:: getPortHandle(port)
:param number port: Port number
:RAM cost: 10 GB
Get a handle to a Netscript Port. See more details here: :ref:`netscript_ports`
@ -865,6 +935,7 @@ rm
:param string fn: Filename of file to remove. Must include the extension
:returns: True if it successfully deletes the file, and false otherwise
:RAM cost: 1 GB
Removes the specified file from the current server. This function works for every file type except message (.msg) files.
@ -875,6 +946,7 @@ scriptRunning
:param string scriptname: Filename of script to check. This is case-sensitive.
:param string hostname/ip: Hostname or IP of target server
:RAM cost: 1 GB
Returns a boolean indicating whether any instance of the specified script is running on the target server, regardless of
its arguments.
@ -899,6 +971,7 @@ scriptKill
:param string scriptname: Filename of script to kill. This is case-sensitive.
:param string hostname/ip: Hostname or IP of target server
:RAM cost: 1 GB
Kills all scripts with the specified filename on the target server specified by *hostname/ip*, regardless of arguments. Returns
true if one or more scripts were successfully killed, and false if none were.
@ -908,6 +981,8 @@ getScriptName
.. js:function:: getScriptName()
:RAM cost: 0 GB
Returns the current script name
getScriptRam
@ -917,6 +992,7 @@ getScriptRam
:param string scriptname: Filename of script. This is case-sensitive.
:param string hostname/ip: Hostname or IP of target server the script is located on. This is optional, If it is not specified then the function will se the current server as the target server.
:RAM cost: 0.1 GB
Returns the amount of RAM required to run the specified script on the target server. Returns
0 if the script does not exist.
@ -928,6 +1004,7 @@ getHackTime
:param string hostname/ip: Hostname or IP of target server
:param number hackLvl: Optional hacking level for the calculation. Defaults to player's current hacking level
:RAM cost: 0.05 GB
Returns the amount of time in seconds it takes to execute the *hack()* Netscript function on the target server.
@ -941,6 +1018,7 @@ getGrowTime
:param string hostname/ip: Hostname or IP of target server
:param number hackLvl: Optional hacking level for the calculation. Defaults to player's current hacking level
:RAM cost: 0.05 GB
Returns the amount of time in seconds it takes to execute the *grow()* Netscript function on the target server.
@ -954,6 +1032,7 @@ getWeakenTime
:param string hostname/ip: Hostname or IP of target server
:param number hackLvl: Optional hacking level for the calculation. Defaults to player's current hacking level
:RAM cost: 0.05 GB
Returns the amount of time in seconds it takes to execute the *weaken()* Netscript function on the target server.
@ -968,6 +1047,7 @@ getScriptIncome
:param string scriptname: Filename of script
:param string hostname/ip: Server on which script is running
:param args...: Arguments that the script is running with
:RAM cost: 0.1 GB
Returns the amount of income the specified script generates while online (when the game is open, does not apply for offline income).
Remember that a script is uniquely identified by both its name and its arguments. So for example if you ran a script with the arguments
@ -986,6 +1066,7 @@ getScriptExpGain
:param string scriptname: Filename of script
:param string hostname/ip: Server on which script is running
:param args...: Arguments that the script is running with
:RAM cost: 0.1 GB
Returns the amount of hacking experience the specified script generates while online (when the game is open, does not apply for offline experience gains).
Remember that a script is uniquely identified by both its name and its arguments.
@ -997,6 +1078,8 @@ getTimeSinceLastAug
.. js:function:: getTimeSinceLastAug()
:RAM cost: 0.05 GB
Returns the amount of time in milliseconds that have passed since you last installed Augmentations
sprintf
@ -1004,6 +1087,8 @@ sprintf
.. js:function:: sprintf()
:RAM cost: 0 GB
See `this link <https://github.com/alexei/sprintf.js>`_ for details.
vsprintf
@ -1011,6 +1096,8 @@ vsprintf
.. js:function:: vsprintf()
:RAM cost: 0 GB
See `this link <https://github.com/alexei/sprintf.js>`_ for details.
prompt
@ -1019,6 +1106,7 @@ prompt
.. js:function:: prompt(txt)
:param string txt: Text to appear in the prompt dialog box
:RAM cost: 0 GB
Prompts the player with a dialog box with two options: "Yes" and "No". This function will return true if the player click "Yes" and
false if the player clicks "No". The script's execution is halted until the player selects one of the options.
@ -1031,6 +1119,7 @@ wget
:param string url: URL to pull data from
:param string target: Filename to write data to. Must be script or text file
:param string ip: Optional hostname/ip of server for target file.
:RAM cost: 0 GB
Retrieves data from a URL and downloads it to a file on the specified server. The data can only
be downloaded to a script (.script, .ns, .js) or a text file (.txt). If the file already exists,
@ -1057,4 +1146,6 @@ wget
getFavorToDonate
^^^^^^^^^^^^^^^^
:RAM cost: 0.1 GB
Returns the amount of Faction favor required to be able to donate to a faction.

@ -14,7 +14,7 @@ You can use the Singularity Functions in other BitNodes if and only if you have
Source-File 4 will open up additional Singularity Functions that you can use in other BitNodes. If your Source-File 4 is upgraded all the way to
level 3, then you will be able to access all of the Singularity Functions.
Note that Singularity Functions require a lot of RAM outside of BitNode-4 (their RAM costs are multiplied by 10 if you are not in BitNode-4)
Note that Singularity Functions require twice as much RAM outside of BitNode-4
universityCourse
----------------
@ -422,7 +422,7 @@ donateToFaction
Attempts to donate money to the specified faction in exchange for reputation.
Returns true if you successfully donate the money, and false otherwise.
createProgram
-------------

@ -488,58 +488,6 @@
<p id="tutorial-text"> </p>
</div>
<!-- dev menu -->
<div id="dev-menu-container" class="generic-menupage-container">
<p id="dev-menu-text">If you see this menu you can pretty much break the game. It's recommended that you use this menu only to setup a save file appropriate to test a new feature or bug fix.</p>
<p id="dev-menu-text">Generic</p>
<a id="dev-need-money" class="a-link-button">Add $1000t</a>
<a id="dev-need-ram" class="a-link-button">Double home RAM</a>
<p id="dev-menu-text">Augmentation related: </p>
<!-- gets populated with the list of all augments -->
<select id="dev-menu-aug-dropdown" class="dropdown"></select>
<a id="dev-add-aug" class="a-link-button tooltip">Queue Augmentation<span class="tooltiptext">May require save + reload</span></a>
<input id="dev-sf-n" type="number" class="text-input" placeholder="SourceFile-N"><input id="dev-sf-lvl" type="number" class="text-input" placeholder="SourceFile-Lvl"><a id="dev-add-source-file" class="a-link-button tooltip"> Add/Remove source file <span class="tooltiptext">If Lvl == 0 the sf will be removed, calling it with another level will replace your current source file. You CAN set a source file higher than it's maximum level.</span></a>
<p id="dev-menu-text">Faction related: </p>
<select id="dev-menu-faction-dropdown" class="dropdown"></select>
<a id="dev-add-faction" class="a-link-button tooltip">Receive invite<span class="tooltiptext">May require save + reload</span></a>
<p id="dev-menu-text">Program related: </p>
<select id="dev-menu-connect-dropdown" class="dropdown"></select>
<a id="dev-connect" class="a-link-button tooltip">Connect<span class="tooltiptext">Connect to the target server.</span></a>
<select id="dev-menu-add-program-dropdown" class="dropdown"></select>
<a id="dev-add-program" class="a-link-button tooltip">Add Program<span class="tooltiptext">Add this program to the player home server, won't add the same program twice.</span></a>
<a id="dev-bit-flume" class="a-link-button tooltip">Trigger BitFlume<span class="tooltiptext">Quick escape to change BN, does not give SFs</span></a>
<p id="dev-menu-text">Server related: </p>
<a id="dev-open-all" class="a-link-button tooltip">NUKE + ports all servers<span class="tooltiptext">Opens all ports, nukes all servers, gains root access to everything (still need the appropriate hacking level)</span></a>
<a id="dev-min-security" class="a-link-button tooltip">minimize all servers security<span class="tooltiptext">All servers security will be set to their minimum security</span></a>
<a id="dev-max-money" class="a-link-button tooltip">maximize all servers money<span class="tooltiptext">Set all servers available money to maximum for that server</span></a>
<p id="dev-menu-text">Exp/stats related: </p>
<input id="dev-hacking-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-hacking" class="a-link-button tooltip">add hacking exp<span class="tooltiptext">Add that many hacking experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<input id="dev-strength-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-strength" class="a-link-button tooltip">add strength exp<span class="tooltiptext">Add that many strength experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<input id="dev-defense-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-defense" class="a-link-button tooltip">add defense exp<span class="tooltiptext">Add that many defense experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<input id="dev-dexterity-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-dexterity" class="a-link-button tooltip">add dexterity exp<span class="tooltiptext">Add that many dexterity experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<input id="dev-agility-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-agility" class="a-link-button tooltip">add agility exp<span class="tooltiptext">Add that many agility experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<input id="dev-charisma-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-charisma" class="a-link-button tooltip">add charisma exp<span class="tooltiptext">Add that many charisma experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<input id="dev-intelligence-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-intelligence" class="a-link-button tooltip">add intelligence exp<span class="tooltiptext">Add that many intelligence experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<a id="dev-enable-intelligence" class="a-link-button tooltip"> enable intelligence<span class="tooltiptext">Enables the intelligence stat</span></a>
<a id="dev-disable-intelligence" class="a-link-button tooltip"> disable intelligence<span class="tooltiptext">Disables the intelligence stat</span></a>
</div>
<!-- Location (visiting a location in World) -->
<div id="location-container" class="generic-menupage-container">
<a id="location-return-to-world-button" class="a-link-button"> Return to World </a>

@ -92,8 +92,9 @@ let NetscriptFunctions =
"installAugmentations|" +
// TIX API
"getStockPrice|getStockPosition|getStockSymbols|buyStock|sellStock|shortStock|sellShort|" +
"placeOrder|cancelOrder|" +
"getStockPrice|getStockPosition|getStockSymbols|buyStock|sellStock|" +
"shortStock|sellShort|" +
"placeOrder|cancelOrder|getStockVolatility|getStockForecast|" +
// Hacknet Node API
"hacknet|numNodes|purchaseNode|getPurchaseNodeCost|getNodeStats|" +

@ -1,8 +1,7 @@
import {BitNodeMultipliers} from "./BitNodeMultipliers";
import {CONSTANTS} from "./Constants";
import {Engine} from "./engine";
import {Factions, getNextNeurofluxLevel,
factionExists} from "./Faction";
import {Factions, factionExists} from "./Faction";
import {hasBladeburnerSF} from "./NetscriptFunctions";
import {addWorkerScript} from "./NetscriptWorker";
import {Player} from "./Player";
@ -1029,9 +1028,25 @@ function initAugmentations() {
"This is a special augmentation because it can be leveled up infinitely. Each level of this augmentation " +
"increases ALL of the player's multipliers by 1%."
});
var nextLevel = getNextNeurofluxLevel();
NeuroFluxGovernor.level = nextLevel - 1;
mult = Math.pow(CONSTANTS.NeuroFluxGovernorLevelMult, NeuroFluxGovernor.level);
// Set the Augmentation's level to the currently-installed level
let currLevel = 0;
for (let i = 0; i < Player.augmentations.length; ++i) {
if (Player.augmentations[i].name === AugmentationNames.NeuroFluxGovernor) {
currLevel = Player.augmentations[i].level;
}
}
NeuroFluxGovernor.level = currLevel;
// To set the price/rep req of the NeuroFlux, we have to take into account NeuroFlux
// levels that are purchased but not yet installed
let nextLevel = currLevel;
for (let i = 0; i < Player.queuedAugmentations.length; ++i) {
if (Player.queuedAugmentations[i].name === AugmentationNames.NeuroFluxGovernor) {
++nextLevel;
}
}
mult = Math.pow(CONSTANTS.NeuroFluxGovernorLevelMult, nextLevel);
NeuroFluxGovernor.baseRepRequirement = 500 * mult * CONSTANTS.AugmentationRepMultiplier * BitNodeMultipliers.AugmentationRepCost;
NeuroFluxGovernor.baseCost = 750e3 * mult * CONSTANTS.AugmentationCostMultiplier * BitNodeMultipliers.AugmentationMoneyCost;
if (augmentationExists(AugmentationNames.NeuroFluxGovernor)) {
@ -2380,7 +2395,7 @@ function applyAugmentation(aug, reapply=false) {
return;
}
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
if (aug.name === AugmentationNames.NeuroFluxGovernor) {
for (var i = 0; i < Player.augmentations.length; ++i) {
if (Player.augmentations[i].name == AugmentationNames.NeuroFluxGovernor) {
//Already have this aug, just upgrade the level

@ -3336,6 +3336,38 @@ Bladeburner.prototype.startActionNetscriptFn = function(type, name, workerScript
return false;
}
// Special logic for Black Ops
if (actionId.type === ActionTypes["BlackOp"]) {
// Can't start a BlackOp if you don't have the required rank
let action = this.getActionObject(actionId);
if (action.reqdRank > this.rank) {
workerScript.log(`Failed to start Black Op ${actionId.name} due to insufficient rank`);
return false;
}
// Can't start a BlackOp if you haven't done the one before it
var blackops = [];
for (const nm in BlackOperations) {
if (BlackOperations.hasOwnProperty(nm)) {
blackops.push(nm);
}
}
blackops.sort(function(a, b) {
return (BlackOperations[a].reqdRank - BlackOperations[b].reqdRank); // Sort black ops in intended order
});
let i = blackops.indexOf(actionId.name);
if (i === -1) {
workerScript.log("ERROR: Invalid Black Operation name passed into bladeburner.startAction(). Note that this name is case-sensitive & whitespace-sensitive");
return false;
}
if (i > 0 && this.blackops[blackops[i-1]] == null) {
workerScript.log(`ERROR: Cannot attempt Black Operation ${actionId.name} because you have not done the preceding one`);
return false;
}
}
try {
this.startAction(actionId);
if (workerScript.shouldLog("startAction")) {
@ -3437,9 +3469,14 @@ Bladeburner.prototype.getActionCountRemainingNetscriptFn = function(type, name,
switch (actionId.type) {
case ActionTypes["Contract"]:
case ActionTypes["Operation"]:
return actionObj.count;
case ActionTypes["BlackOp"]:
case ActionTypes["BlackOperation"]:
return actionObj.count;
if (this.blackops[name] != null) {
return 0;
} else {
return 1;
}
case ActionTypes["Training"]:
case ActionTypes["Field Analysis"]:
case ActionTypes["FieldAnalysis"]:

@ -48,7 +48,7 @@ let CONSTANTS = {
/* Netscript Constants */
//RAM Costs for different commands
ScriptBaseRamCost: 1.6,
ScriptDomRamCost: 100,
ScriptDomRamCost: 25,
ScriptWhileRamCost: 0,
ScriptForRamCost: 0,
ScriptIfRamCost: 0,
@ -91,6 +91,8 @@ let CONSTANTS = {
ScriptSingularityFn2RamCost: 2,
ScriptSingularityFn3RamCost: 3,
ScriptSingularityFnRamMult: 2, // Multiplier for RAM cost outside of BN-4
ScriptBladeburnerApiBaseRamCost: 4,
NumNetscriptPorts: 20,
@ -500,6 +502,7 @@ let CONSTANTS = {
LatestUpdate:
`
v0.41.0
* WARNING: In NetscriptJS, defining a function called print() is no longer possible
* Gang Mechanic Changes (BitNode-2):
*** Added new 'ascension' mechanic for Gang Members
*** The first three gang members are now 'free' (can be recruited instantly)
@ -508,9 +511,18 @@ let CONSTANTS = {
*** Added a new category of upgrades for Gang Members: Augmentations
*** Non-Augmentation Gang member upgrades are now significantly weaker
*** Reputation for your Gang faction can no longer be gained through Infiltration
* RAM Cost of accessing the global document object lowered from 100 GB to 25 GB
* RAM Cost to use Singularity Functions outside of BitNode-4 lowered by 75%. They now only cost twice as much as they do in BitNode-4
* b1t_flum3.exe now takes significantly less time to create
* Improved number formatting for Player 'work' actions (including crimes, etc.). These numbers should also adhere to locale settings now (by Kline-)
* Bug Fix: Calling print() in NetscriptJS no longer brings up the print dialog
* Bug Fix: Fixed a bug that sometimes caused a blank black screen when destroying/resetting/switching BitNodes
* Bug Fix: Netscript calls that throw errors will now no longer cause the 'concurrent calls' error if they are caught in the script. i.e. try/catch should now work properly in scripts
* Bug Fix: Fixed a bug where sometimes the NeuroFlux Governor Augmentation level would be incorrectly calculated when the game was loaded
* Bug Fix: Fixed a bug where calling the scp() Netscript function with invalid hostname/ips would throw an unclear error message
* Bug Fix: Bladeburner API function getActionCountRemaining() should now work properly for BlackOps
* Bug Fix: Black Ops can no longer be attempted out-of-order or without the required rank via Bladeburner API
* RAM cost for basic Netscript functions added to documentation (by CBJamo)
`
}

395
src/DevMenu.js Normal file

@ -0,0 +1,395 @@
import {AugmentationNames} from "./Augmentations"
import {Programs} from "./CreateProgram"
import {Factions} from "./Faction";
import {Player} from "./Player";
import {AllServers} from "./Server";
import {Terminal} from "./Terminal";
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
import {createElement} from "../utils/uiHelpers/createElement";
import {removeElementById} from "../utils/uiHelpers/removeElementById";
const devMenuContainerId = "dev-menu-container";
export function createDevMenu() {
if (process.env.NODE_ENV !== "development") {
throw new Error("Cannot create Dev Menu because you are not in a dev build");
}
const devMenuText = createElement("h1", {
display: "block",
innerText: "Development Menu - Only meant to be used for testing/debugging",
});
// Generic
const genericHeader = createElement("h2", {
display: "block",
innerText: "Generic"
});
const addMoney = createElement("button", {
class: "std-button",
clickListener: () => {
Player.gainMoney(1e15);
},
display: "block",
innerText: "Add $1000t",
});
const addRam = createElement("button", {
class: "std-button",
clickListener: () => {
Player.getHomeComputer().maxRam *= 2;
},
display: "block",
innerText: "Double Home Computer RAM",
});
const triggerBitflume = createElement("button", {
class: "std-button",
clickListener: () => {
hackWorldDaemon(Player.bitNodeN, true);
},
innerText: "Trigger BitFlume",
});
const destroyCurrentBitnode = createElement("button", {
class: "std-button",
clickListener: () => {
hackWorldDaemon(Player.bitNodeN);
},
innerText: "Destroy Current BitNode",
tooltip: "Will grant Source-File for the BitNode",
})
// Experience / stats
const statsHeader = createElement("h2", {
display: "block",
innerText: "Experience/Stats"
});
const statsHackingExpInput = createElement("input", {
class: "text-input",
display: "block",
placeholder: "+/- hacking exp",
type: "number",
});
const statsHackingExpButton = createElement("button", {
class: "std-button",
clickListener: () => {
const exp = parseInt(statsHackingExpInput.value);
Player.gainHackingExp(exp);
Player.updateSkillLevels();
},
display: "block",
innerText: "Add Hacking Exp",
});
const statsStrengthExpInput = createElement("input", {
class: "text-input",
display: "block",
placeholder: "+/- hacking exp",
type: "number",
});
const statsStrengthExpButton = createElement("button", {
class: "std-button",
clickListener: () => {
const exp = parseInt(statsStrengthExpInput.value);
Player.gainStrengthExp(exp);
Player.updateSkillLevels();
},
display: "block",
innerText: "Add Hacking Exp",
});
const statsDefenseExpInput = createElement("input", {
class: "text-input",
display: "block",
placeholder: "+/- hacking exp",
type: "number",
});
const statsDefenseExpButton = createElement("button", {
class: "std-button",
clickListener: () => {
const exp = parseInt(statsDefenseExpInput.value);
Player.gainDefenseExp(exp);
Player.updateSkillLevels();
},
display: "block",
innerText: "Add Hacking Exp",
});
const statsDexterityExpInput = createElement("input", {
class: "text-input",
display: "block",
placeholder: "+/- hacking exp",
type: "number",
});
const statsDexterityExpButton = createElement("button", {
class: "std-button",
clickListener: () => {
const exp = parseInt(statsDexterityExpInput.value);
Player.gainDexterityExp(exp);
Player.updateSkillLevels();
},
display: "block",
innerText: "Add Hacking Exp",
});
const statsAgilityExpInput = createElement("input", {
class: "text-input",
display: "block",
placeholder: "+/- hacking exp",
type: "number",
});
const statsAgilityExpButton = createElement("button", {
class: "std-button",
clickListener: () => {
const exp = parseInt(statsAgilityExpButton.value);
Player.gainAgilityExp(exp);
Player.updateSkillLevels();
},
display: "block",
innerText: "Add Hacking Exp",
});
const statsCharismaExpInput = createElement("input", {
class: "text-input",
display: "block",
placeholder: "+/- hacking exp",
type: "number",
});
const statsCharismaExpButton = createElement("button", {
class: "std-button",
clickListener: () => {
const exp = parseInt(statsCharismaExpInput.value);
Player.gainCharismaExp(exp);
Player.updateSkillLevels();
},
display: "block",
innerText: "Add Hacking Exp",
});
const statsIntelligenceExpInput = createElement("input", {
class: "text-input",
display: "block",
placeholder: "+/- hacking exp",
type: "number",
});
const statsIntelligenceExpButton = createElement("button", {
class: "std-button",
clickListener: () => {
const exp = parseInt(statsIntelligenceExpInput.value);
Player.gainIntelligenceExp(exp);
Player.updateSkillLevels();
},
display: "block",
innerText: "Add Hacking Exp",
});
const statsEnableIntelligenceButton = createElement("button", {
class: "std-button",
clickListener: () => {
Player.intelligence = 1;
},
innerText: "Enable Intelligence"
});
const statsDisableIntelligenceButton = createElement("button", {
class: "std-button",
clickListener: () => {
Player.intelligence = 0;
},
innerText: "Disable Intelligence"
});
// Factions
const factionsHeader = createElement("h2", {innerText: "Factions"});
const factionsDropdown = createElement("select", {class: "dropdown"});
for (const i in Factions) {
factionsDropdown.options[factionsDropdown.options.length] = new Option(Factions[i].name, Factions[i].name);
}
const factionsAddButton = createElement("button", {
class: "std-button",
clickListener: () => {
const facName = factionsDropdown.options[factionsDropdown.selectedIndex].value;
Player.receiveInvite(facName);
},
innerText: "Receive Invite to Faction",
});
// Augmentations / Source Files
const augmentationsHeader = createElement("h2", {innerText: "Augmentations"});
const augmentationsDropdown = createElement("select", {class: "dropdown"});
for (const i in AugmentationNames) {
const augName = AugmentationNames[i];
augmentationsDropdown.options[augmentationsDropdown.options.length] = new Option(augName, augName);
}
const augmentationsQueueButton = createElement("button", {
class: "std-button",
clickListener: () => {
Player.queueAugmentation(augmentationsDropdown.options[augmentationsDropdown.selectedIndex].value);
},
innerText: "Queue Augmentation",
})
// Programs
const programsHeader = createElement("h2", {innerText: "Programs"});
const programsAddDropdown = createElement("select", {class: "dropdown"});
for (const i in Programs) {
const progName = Programs[i].name;
programsAddDropdown.options[programsAddDropdown.options.length] = new Option(progName, progName);
}
const programsAddButton = createElement("button", {
class: "std-button",
clickListener: () => {
const program = programsAddDropdown.options[programsAddDropdown.selectedIndex].value;
if(!Player.hasProgram(program)) {
Player.getHomeComputer().programs.push(program);
}
},
innerText: "Add Program",
})
// Servers
const serversHeader = createElement("h2", {innerText: "Servers"});
const serversOpenAll = createElement("button", {
class: "std-button",
clickListener: () => {
for (const i in AllServers) {
AllServers[i].hasAdminRights = true;
AllServers[i].sshPortOpen = true;
AllServers[i].ftpPortOpen = true;
AllServers[i].smtpPortOpen = true;
AllServers[i].httpPortOpen = true;
AllServers[i].sqlPortOpen = true;
AllServers[i].openPortCount = 5;
}
},
display: "block",
innerText: "Get Admin Rights to all servers",
});
const serversMinSecurityAll = createElement("button", {
class: "std-button",
clickListener: () => {
for (const i in AllServers) {
AllServers[i].hackDifficulty = AllServers[i].minDifficulty;
}
},
display: "block",
innerText: "Set all servers to min security",
});
const serversMaxMoneyAll = createElement("button", {
class: "std-button",
clickListener: () => {
for (const i in AllServers) {
AllServers[i].moneyAvailable = AllServers[i].moneyMax;
}
},
display: "block",
innerText: "Set all servers to max money",
});
const serversConnectToDropdown = createElement("select", {class: "dropdown"});
for (const i in AllServers) {
const hn = AllServers[i].hostname;
serversConnectToDropdown.options[serversConnectToDropdown.options.length] = new Option(hn, hn);
}
const serversConnectToButton = createElement("button", {
class: "std-button",
clickListener: () => {
const host = serversConnectToDropdown.options[serversConnectToDropdown.selectedIndex].value;
Terminal.connectToServer(host);
},
innerText: "Connect to server",
});
// Add everything to container, then append to main menu
const devMenuContainer = createElement("div", {
class: "generic-menupage-container",
id: devMenuContainerId,
});
const bladeburnerHeader = createElement("h2", {innerText: "Bladeburner"});
const bladeburnerGainRankInput = createElement("input", {
class: "text-input",
display: "block",
placeholder: "Rank to gain (or negative to lose rank)",
type: "number",
});
const bladeburnerGainRankButton = createElement("button", {
class: "std-button",
clickListener: () => {
try {
const rank = parseInt(bladeburnerGainRankInput.value);
Player.bladeburner.changeRank(rank);
} catch(e) {
exceptionAlert(`Failed to change Bladeburner Rank in dev menu: ${e}`);
}
},
display: "block",
innerText: "Gain Bladeburner Rank",
})
devMenuContainer.appendChild(devMenuText);
devMenuContainer.appendChild(genericHeader);
devMenuContainer.appendChild(addMoney);
devMenuContainer.appendChild(addRam);
devMenuContainer.appendChild(triggerBitflume);
devMenuContainer.appendChild(destroyCurrentBitnode);
devMenuContainer.appendChild(statsHeader);
devMenuContainer.appendChild(statsHackingExpInput);
devMenuContainer.appendChild(statsHackingExpButton);
devMenuContainer.appendChild(statsStrengthExpInput);
devMenuContainer.appendChild(statsStrengthExpButton);
devMenuContainer.appendChild(statsDefenseExpInput);
devMenuContainer.appendChild(statsDefenseExpButton);
devMenuContainer.appendChild(statsDexterityExpInput);
devMenuContainer.appendChild(statsDexterityExpButton);
devMenuContainer.appendChild(statsAgilityExpInput);
devMenuContainer.appendChild(statsAgilityExpButton);
devMenuContainer.appendChild(statsCharismaExpInput);
devMenuContainer.appendChild(statsCharismaExpButton);
devMenuContainer.appendChild(statsIntelligenceExpInput);
devMenuContainer.appendChild(statsIntelligenceExpButton);
devMenuContainer.appendChild(statsEnableIntelligenceButton);
devMenuContainer.appendChild(statsDisableIntelligenceButton);
devMenuContainer.appendChild(factionsHeader);
devMenuContainer.appendChild(factionsDropdown);
devMenuContainer.appendChild(factionsAddButton);
devMenuContainer.appendChild(augmentationsHeader);
devMenuContainer.appendChild(augmentationsQueueButton);
devMenuContainer.appendChild(programsHeader);
devMenuContainer.appendChild(programsAddDropdown);
devMenuContainer.appendChild(programsAddButton);
devMenuContainer.appendChild(serversHeader);
devMenuContainer.appendChild(serversOpenAll);
devMenuContainer.appendChild(serversMinSecurityAll);
devMenuContainer.appendChild(serversMaxMoneyAll);
devMenuContainer.appendChild(serversConnectToDropdown);
devMenuContainer.appendChild(serversConnectToButton);
devMenuContainer.appendChild(bladeburnerHeader);
devMenuContainer.appendChild(bladeburnerGainRankInput);
devMenuContainer.appendChild(bladeburnerGainRankButton);
const entireGameContainer = document.getElementById("entire-game-container");
if (entireGameContainer == null) {
throw new Error("Could not find entire-game-container DOM element");
}
entireGameContainer.appendChild(devMenuContainer);
}
export function closeDevMenu() {
removeElementById(devMenuContainerId);
}

@ -734,27 +734,21 @@ function purchaseAugmentation(aug, fac, sing=false) {
}
function getNextNeurofluxLevel() {
var aug = Augmentations[AugmentationNames.NeuroFluxGovernor];
if (aug == null) {
for (var i = 0; i < Player.augmentations.length; ++i) {
if (Player.augmentations[i].name == AugmentationNames.NeuroFluxGovernor) {
aug = Player.augmentations[i];
}
}
if (aug == null) {
console.log("WARNING: Could not find NeuroFlux Governor aug. This is OK if " +
"it happens during the loading/initialization of the game, but probably " +
"indicates something seriously wrong at other times");
return 1;
// Get current Neuroflux level based on Player's augmentations
let currLevel = 0;
for (var i = 0; i < Player.augmentations.length; ++i) {
if (Player.augmentations[i].name === AugmentationNames.NeuroFluxGovernor) {
currLevel = Player.augmentations[i].level;
}
}
var nextLevel = aug.level + 1;
// Account for purchased but uninstalled Augmentations
for (var i = 0; i < Player.queuedAugmentations.length; ++i) {
if (Player.queuedAugmentations[i].name == AugmentationNames.NeuroFluxGovernor) {
++nextLevel;
++currLevel;
}
}
return nextLevel;
return currLevel + 1;
}
function processPassiveFactionRepGain(numCycles) {

@ -882,12 +882,12 @@ function NetscriptFunctions(workerScript) {
}
destServer = getServer(ip2);
if (destServer == null) {
throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid hostname/ip passed into scp() command: " + ip);
throw makeRuntimeRejectMsg(workerScript, `ERROR: Invalid hostname/ip passed into scp() command: ${ip2}`);
}
currServ = getServer(ip1);
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, `ERROR: Invalid hostname/ip passed into scp() command: ${ip1}`);
}
} else if (arguments.length === 2) { //scriptname, destination
if (scriptname === undefined || ip1 === undefined) {
@ -895,7 +895,7 @@ function NetscriptFunctions(workerScript) {
}
destServer = getServer(ip1);
if (destServer == null) {
throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid hostname/ip passed into scp() command: " + ip);
throw makeRuntimeRejectMsg(workerScript, `ERROR: Invalid hostname/ip passed into scp() command: ${ip1}`);
}
currServ = getServer(workerScript.serverIp);
@ -2313,7 +2313,7 @@ function NetscriptFunctions(workerScript) {
/* Singularity Functions */
universityCourse : function(universityName, className) {
var ramCost = CONSTANTS.ScriptSingularityFn1RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("universityCourse", ramCost);
}
@ -2402,7 +2402,7 @@ function NetscriptFunctions(workerScript) {
gymWorkout : function(gymName, stat) {
var ramCost = CONSTANTS.ScriptSingularityFn1RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("gymWorkout", ramCost);
}
@ -2504,7 +2504,7 @@ function NetscriptFunctions(workerScript) {
travelToCity(cityname) {
var ramCost = CONSTANTS.ScriptSingularityFn1RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("travelToCity", ramCost);
}
@ -2541,7 +2541,7 @@ function NetscriptFunctions(workerScript) {
purchaseTor() {
var ramCost = CONSTANTS.ScriptSingularityFn1RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("purchaseTor", ramCost);
}
@ -2585,7 +2585,7 @@ function NetscriptFunctions(workerScript) {
},
purchaseProgram(programName) {
var ramCost = CONSTANTS.ScriptSingularityFn1RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("purchaseProgram", ramCost);
}
@ -2637,7 +2637,7 @@ function NetscriptFunctions(workerScript) {
},
getStats : function() {
var ramCost = CONSTANTS.ScriptSingularityFn1RamCost / 4;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getStats", ramCost);
}
@ -2661,7 +2661,7 @@ function NetscriptFunctions(workerScript) {
},
getCharacterInformation : function() {
var ramCost = CONSTANTS.ScriptSingularityFn1RamCost / 4;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getCharacterInformation", ramCost);
}
@ -2697,7 +2697,7 @@ function NetscriptFunctions(workerScript) {
},
isBusy : function() {
var ramCost = CONSTANTS.ScriptSingularityFn1RamCost / 4;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("isBusy", ramCost);
}
@ -2712,7 +2712,7 @@ function NetscriptFunctions(workerScript) {
},
stopAction : function() {
var ramCost = CONSTANTS.ScriptSingularityFn1RamCost / 2;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("stopAction", ramCost);
}
@ -2734,7 +2734,7 @@ function NetscriptFunctions(workerScript) {
},
upgradeHomeRam : function() {
var ramCost = CONSTANTS.ScriptSingularityFn2RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("upgradeHomeRam", ramCost);
}
@ -2766,7 +2766,7 @@ function NetscriptFunctions(workerScript) {
},
getUpgradeHomeRamCost : function() {
var ramCost = CONSTANTS.ScriptSingularityFn2RamCost / 2;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getUpgradeHomeRamCost", ramCost);
}
@ -2782,7 +2782,7 @@ function NetscriptFunctions(workerScript) {
},
workForCompany : function() {
var ramCost = CONSTANTS.ScriptSingularityFn2RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("workForCompany", ramCost);
}
@ -2823,7 +2823,7 @@ function NetscriptFunctions(workerScript) {
},
applyToCompany : function(companyName, field) {
var ramCost = CONSTANTS.ScriptSingularityFn2RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("applyToCompany", ramCost);
}
@ -2904,7 +2904,7 @@ function NetscriptFunctions(workerScript) {
},
getCompanyRep : function(companyName) {
var ramCost = CONSTANTS.ScriptSingularityFn2RamCost / 2;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getCompanyRep", ramCost);
}
@ -2925,7 +2925,7 @@ function NetscriptFunctions(workerScript) {
},
getCompanyFavor : function(companyName) {
var ramCost = CONSTANTS.ScriptSingularityFn2RamCost / 4;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getCompanyFavor", ramCost);
}
@ -2946,7 +2946,7 @@ function NetscriptFunctions(workerScript) {
},
getCompanyFavorGain : function(companyName) {
var ramCost = CONSTANTS.ScriptSingularityFn2RamCost / 4;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getCompanyFavorGain", ramCost);
}
@ -2967,7 +2967,7 @@ function NetscriptFunctions(workerScript) {
},
checkFactionInvitations : function() {
var ramCost = CONSTANTS.ScriptSingularityFn2RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("checkFactionInvitations", ramCost);
}
@ -2983,7 +2983,7 @@ function NetscriptFunctions(workerScript) {
},
joinFaction : function(name) {
var ramCost = CONSTANTS.ScriptSingularityFn2RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("joinFaction", ramCost);
}
@ -3022,7 +3022,7 @@ function NetscriptFunctions(workerScript) {
},
workForFaction : function(name, type) {
var ramCost = CONSTANTS.ScriptSingularityFn2RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("workForFaction", ramCost);
}
@ -3122,7 +3122,7 @@ function NetscriptFunctions(workerScript) {
},
getFactionRep : function(name) {
var ramCost = CONSTANTS.ScriptSingularityFn2RamCost / 4;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getFactionRep", ramCost);
}
@ -3143,7 +3143,7 @@ function NetscriptFunctions(workerScript) {
},
getFactionFavor : function(name) {
var ramCost = CONSTANTS.ScriptSingularityFn2RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getFactionFavor", ramCost);
}
@ -3164,7 +3164,7 @@ function NetscriptFunctions(workerScript) {
},
getFactionFavorGain: function(name) {
var ramCost = CONSTANTS.ScriptSingularityFn2RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getFactionFavorGain", ramCost);
}
@ -3185,7 +3185,7 @@ function NetscriptFunctions(workerScript) {
},
donateToFaction : function(name, amt) {
var ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("donateToFaction", ramCost);
}
@ -3224,7 +3224,7 @@ function NetscriptFunctions(workerScript) {
},
createProgram : function(name) {
var ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("createProgram", ramCost);
}
@ -3278,7 +3278,7 @@ function NetscriptFunctions(workerScript) {
},
commitCrime : function(crimeRoughName) {
var ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("commitCrime", ramCost);
}
@ -3335,7 +3335,7 @@ function NetscriptFunctions(workerScript) {
},
getCrimeChance : function(crimeRoughName) {
var ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getCrimeChance", ramCost);
}
@ -3356,7 +3356,7 @@ function NetscriptFunctions(workerScript) {
},
getOwnedAugmentations : function(purchased=false) {
var ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getOwnedAugmentations", ramCost);
}
@ -3380,7 +3380,7 @@ function NetscriptFunctions(workerScript) {
},
getOwnedSourceFiles : function() {
let ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getOwnedSourceFiles", ramCost);
}
@ -3399,7 +3399,7 @@ function NetscriptFunctions(workerScript) {
},
getAugmentationsFromFaction : function(facname) {
var ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getAugmentationsFromFaction", ramCost);
}
@ -3425,7 +3425,7 @@ function NetscriptFunctions(workerScript) {
},
getAugmentationCost : function(name) {
var ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("getAugmentationCost", ramCost);
}
@ -3447,7 +3447,7 @@ function NetscriptFunctions(workerScript) {
},
purchaseAugmentation : function(faction, name) {
var ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("purchaseAugmentation", ramCost);
}
@ -3512,7 +3512,7 @@ function NetscriptFunctions(workerScript) {
},
installAugmentations : function(cbScript) {
var ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
if (Player.bitNodeN !== 4) {ramCost *= 8;}
if (Player.bitNodeN !== 4) {ramCost *= CONSTANTS.ScriptSingularityFnRamMult;}
if (workerScript.checkingRam) {
return updateStaticRam("installAugmentations", ramCost);
}

@ -31,8 +31,6 @@ export async function executeJSScript(scripts = [], workerScript) {
loadedModule = script.module;
let ns = workerScript.env.vars;
//ns.threads = workerScript.threads;
//ns.args = workerScript.args;
try {
// TODO: putting await in a non-async function yields unhelpful
@ -75,7 +73,7 @@ export function _getScriptUrls(script, scripts, seen) {
// import {foo} from "blob://<uuid>"
//
// Where the blob URL contains the script content.
const transformedCode = script.code.replace(/((?:from|import)\s+(?:'|"))([^'"]+)('|";)/g,
let transformedCode = script.code.replace(/((?:from|import)\s+(?:'|"))([^'"]+)('|";)/g,
(unmodified, prefix, filename, suffix) => {
const isAllowedImport = scripts.some(s => s.filename == filename);
if (!isAllowedImport) return unmodified;
@ -92,6 +90,9 @@ export function _getScriptUrls(script, scripts, seen) {
}
);
// We automatically define a print function() in the NetscriptJS module so that
// accidental calls to window.print() do not bring up the "print screen" dialog
transformedCode += `\n\nfunction print() {throw new Error("Invalid call to window.print(). Did you mean to use Netscript's print()?");}`
// If we successfully transformed the code, create a blob url for it and
// push that URL onto the top of the stack.

@ -14,7 +14,6 @@ import {NetscriptPort} from "./NetscriptPort";
import {AllServers} from "./Server";
import {Settings} from "./Settings";
//TODO Maybe escodegen might be better?
import {generate} from 'escodegen';
import {parse, Node} from "../utils/acorn";

@ -20,17 +20,14 @@ import {AllServers, Server, AddToAllServers} from "./Server";
import {Settings} from "./Settings";
import {SpecialServerIps, SpecialServerNames} from "./SpecialServerIps";
import {SourceFiles, applySourceFile} from "./SourceFile";
import Decimal from "decimal.js";
import {numeralWrapper} from "./ui/numeralFormat";
import {dialogBoxCreate} from "../utils/DialogBox";
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";
import {createRandomIp} from "../utils/IPAddress";
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver";
import {formatNumber,
convertTimeMsToTimeElapsedString} from "../utils/StringHelperFunctions";
import {convertTimeMsToTimeElapsedString} from "../utils/StringHelperFunctions";
const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle;
@ -721,17 +718,17 @@ PlayerObject.prototype.work = function(numCycles) {
var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
" at " + this.companyName + " (Current Company Reputation: " +
formatNumber(companyRep, 0) + ")<br><br>" +
numeralWrapper.format(companyRep, '0,0') + ")<br><br>" +
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
"You have earned: <br><br>" +
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * CYCLES_PER_SEC, 2) + " / sec) <br><br>" +
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * CYCLES_PER_SEC, 4) + " / sec) reputation for this company <br><br>" +
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * CYCLES_PER_SEC, 4) + " / sec) hacking exp <br><br>" +
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * CYCLES_PER_SEC, 4) + " / sec) strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * CYCLES_PER_SEC, 4) + " / sec) defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * CYCLES_PER_SEC, 4) + " / sec) dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * CYCLES_PER_SEC, 4) + " / sec) agility exp <br><br> " +
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * CYCLES_PER_SEC, 4) + " / sec) charisma exp <br><br>" +
"$" + numeralWrapper.format(this.workMoneyGained, '0,0.00') + " ($" + numeralWrapper.format(this.workMoneyGainRate * CYCLES_PER_SEC, '0,0.00') + " / sec) <br><br>" +
numeralWrapper.format(this.workRepGained, '0,0.0000') + " (" + numeralWrapper.format(this.workRepGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) reputation for this company <br><br>" +
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workHackExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) hacking exp <br><br>" +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workStrExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) strength exp <br>" +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workDefExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) defense exp <br>" +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workDexExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) dexterity exp <br>" +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workAgiExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) agility exp <br><br> " +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workChaExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) charisma exp <br><br>" +
"You will automatically finish after working for 8 hours. You can cancel earlier if you wish, " +
"but you will only gain half of the reputation you've earned so far."
}
@ -750,14 +747,14 @@ PlayerObject.prototype.finishWork = function(cancelled, sing=false) {
this.updateSkillLevels();
var txt = "You earned a total of: <br>" +
"$" + formatNumber(this.workMoneyGained, 2) + "<br>" +
formatNumber(this.workRepGained, 4) + " reputation for the company <br>" +
formatNumber(this.workHackExpGained, 4) + " hacking exp <br>" +
formatNumber(this.workStrExpGained, 4) + " strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " agility exp <br>" +
formatNumber(this.workChaExpGained, 4) + " charisma exp<br>";
"$" + numeralWrapper.format(this.workMoneyGained, '0,0.00') + "<br>" +
numeralWrapper.format(this.workRepGained, '0,0.0000') + " reputation for the company <br>" +
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " hacking exp <br>" +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " strength exp <br>" +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " defense exp <br>" +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " dexterity exp <br>" +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " agility exp <br>" +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " charisma exp<br>";
if (cancelled) {
txt = "You worked a short shift of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " <br><br> " +
@ -774,14 +771,14 @@ PlayerObject.prototype.finishWork = function(cancelled, sing=false) {
if (sing) {
var res = "You worked a short shift of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " and " +
"earned $" + formatNumber(this.workMoneyGained, 2) + ", " +
formatNumber(this.workRepGained, 4) + " reputation, " +
formatNumber(this.workHackExpGained, 4) + " hacking exp, " +
formatNumber(this.workStrExpGained, 4) + " strength exp, " +
formatNumber(this.workDefExpGained, 4) + " defense exp, " +
formatNumber(this.workDexExpGained, 4) + " dexterity exp, " +
formatNumber(this.workAgiExpGained, 4) + " agility exp, and " +
formatNumber(this.workChaExpGained, 4) + " charisma exp.";
"earned $" + numeralWrapper.format(this.workMoneyGained, '0,0.00') + ", " +
numeralWrapper.format(this.workRepGained, '0,0.0000') + " reputation, " +
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " hacking exp, " +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " strength exp, " +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " defense exp, " +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " dexterity exp, " +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " agility exp, and " +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " charisma exp.";
this.resetWorkStatus();
return res;
}
@ -843,17 +840,17 @@ PlayerObject.prototype.workPartTime = function(numCycles) {
var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
" at " + Player.companyName + " (Current Company Reputation: " +
formatNumber(companyRep, 0) + ")<br><br>" +
numeralWrapper.format(companyRep, '0,0') + ")<br><br>" +
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
"You have earned: <br><br>" +
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * CYCLES_PER_SEC, 2) + " / sec) <br><br>" +
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * CYCLES_PER_SEC, 4) + " / sec) reputation for this company <br><br>" +
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * CYCLES_PER_SEC, 4) + " / sec) hacking exp <br><br>" +
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * CYCLES_PER_SEC, 4) + " / sec) strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * CYCLES_PER_SEC, 4) + " / sec) defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * CYCLES_PER_SEC, 4) + " / sec) dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * CYCLES_PER_SEC, 4) + " / sec) agility exp <br><br> " +
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * CYCLES_PER_SEC, 4) + " / sec) charisma exp <br><br>" +
"$" + numeralWrapper.format(this.workMoneyGained, '0,0.00') + " ($" + numeralWrapper.format(this.workMoneyGainRate * CYCLES_PER_SEC, '0,0.00') + " / sec) <br><br>" +
numeralWrapper.format(this.workRepGained, '0,0.0000') + " (" + numeralWrapper.format(this.workRepGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) reputation for this company <br><br>" +
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workHackExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) hacking exp <br><br>" +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workStrExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) strength exp <br>" +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workDefExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) defense exp <br>" +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workDexExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) dexterity exp <br>" +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workAgiExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) agility exp <br><br> " +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workChaExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) charisma exp <br><br>" +
"You will automatically finish after working for 8 hours. You can cancel earlier if you wish, <br>" +
"and there will be no penalty because this is a part-time job.";
@ -868,14 +865,14 @@ PlayerObject.prototype.finishWorkPartTime = function(sing=false) {
this.updateSkillLevels();
var txt = "You earned a total of: <br>" +
"$" + formatNumber(this.workMoneyGained, 2) + "<br>" +
formatNumber(this.workRepGained, 4) + " reputation for the company <br>" +
formatNumber(this.workHackExpGained, 4) + " hacking exp <br>" +
formatNumber(this.workStrExpGained, 4) + " strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " agility exp <br>" +
formatNumber(this.workChaExpGained, 4) + " charisma exp<br>";
"$" + numeralWrapper.format(this.workMoneyGained, '0,0.00') + "<br>" +
numeralWrapper.format(this.workRepGained, '0,0.0000') + " reputation for the company <br>" +
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " hacking exp <br>" +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " strength exp <br>" +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " defense exp <br>" +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " dexterity exp <br>" +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " agility exp <br>" +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " charisma exp<br>";
txt = "You worked for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br> " + txt;
if (!sing) {dialogBoxCreate(txt);}
@ -886,14 +883,14 @@ PlayerObject.prototype.finishWorkPartTime = function(sing=false) {
if (sing) {
var res = "You worked for " + convertTimeMsToTimeElapsedString(this.timeWorked) + " and " +
"earned a total of " +
"$" + formatNumber(this.workMoneyGained, 2) + ", " +
formatNumber(this.workRepGained, 4) + " reputation, " +
formatNumber(this.workHackExpGained, 4) + " hacking exp, " +
formatNumber(this.workStrExpGained, 4) + " strength exp, " +
formatNumber(this.workDefExpGained, 4) + " defense exp, " +
formatNumber(this.workDexExpGained, 4) + " dexterity exp, " +
formatNumber(this.workAgiExpGained, 4) + " agility exp, and " +
formatNumber(this.workChaExpGained, 4) + " charisma exp";
"$" + numeralWrapper.format(this.workMoneyGained, '0,0.00') + ", " +
numeralWrapper.format(this.workRepGained, '0,0.0000') + " reputation, " +
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " hacking exp, " +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " strength exp, " +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " defense exp, " +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " dexterity exp, " +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " agility exp, and " +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " charisma exp";
this.resetWorkStatus();
return res;
}
@ -1012,17 +1009,17 @@ PlayerObject.prototype.workForFaction = function(numCycles) {
var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are currently " + this.currentWorkFactionDescription + " for your faction " + faction.name +
" (Current Faction Reputation: " + formatNumber(faction.playerReputation, 0) + "). <br>" +
" (Current Faction Reputation: " + numeralWrapper.format(faction.playerReputation, '0,0') + "). <br>" +
"You have been doing this for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
"You have earned: <br><br>" +
"$" + formatNumber(this.workMoneyGained, 2) + " (" + formatNumber(this.workMoneyGainRate * CYCLES_PER_SEC, 2) + " / sec) <br><br>" +
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * CYCLES_PER_SEC, 4) + " / sec) reputation for this faction <br><br>" +
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * CYCLES_PER_SEC, 4) + " / sec) hacking exp <br><br>" +
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * CYCLES_PER_SEC, 4) + " / sec) strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * CYCLES_PER_SEC, 4) + " / sec) defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * CYCLES_PER_SEC, 4) + " / sec) dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * CYCLES_PER_SEC, 4) + " / sec) agility exp <br><br> " +
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * CYCLES_PER_SEC, 4) + " / sec) charisma exp <br><br>" +
"$" + numeralWrapper.format(this.workMoneyGained, '0,0.00') + " (" + numeralWrapper.format(this.workMoneyGainRate * CYCLES_PER_SEC, '0,0.00') + " / sec) <br><br>" +
numeralWrapper.format(this.workRepGained, '0,0.0000') + " (" + numeralWrapper.format(this.workRepGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) reputation for this faction <br><br>" +
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workHackExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) hacking exp <br><br>" +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workStrExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) strength exp <br>" +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workDefExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) defense exp <br>" +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workDexExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) dexterity exp <br>" +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workAgiExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) agility exp <br><br> " +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workChaExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) charisma exp <br><br>" +
"You will automatically finish after working for 20 hours. You can cancel earlier if you wish.<br>" +
"There is no penalty for cancelling earlier.";
@ -1038,14 +1035,14 @@ PlayerObject.prototype.finishFactionWork = function(cancelled, sing=false) {
var txt = "You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " <br><br> " +
"You earned a total of: <br>" +
"$" + formatNumber(this.workMoneyGained, 2) + "<br>" +
formatNumber(this.workRepGained, 4) + " reputation for the faction <br>" +
formatNumber(this.workHackExpGained, 4) + " hacking exp <br>" +
formatNumber(this.workStrExpGained, 4) + " strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " agility exp <br>" +
formatNumber(this.workChaExpGained, 4) + " charisma exp<br>";
"$" + numeralWrapper.format(this.workMoneyGained, '0,0.00') + "<br>" +
numeralWrapper.format(this.workRepGained, '0,0.0000') + " reputation for the faction <br>" +
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " hacking exp <br>" +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " strength exp <br>" +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " defense exp <br>" +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " dexterity exp <br>" +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " agility exp <br>" +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " charisma exp<br>";
if (!sing) {dialogBoxCreate(txt);}
var mainMenu = document.getElementById("mainmenu-container");
@ -1058,13 +1055,13 @@ PlayerObject.prototype.finishFactionWork = function(cancelled, sing=false) {
if (sing) {
var res="You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + ". " +
"You earned " +
formatNumber(this.workRepGained, 4) + " rep, " +
formatNumber(this.workHackExpGained, 4) + " hacking exp, " +
formatNumber(this.workStrExpGained, 4) + " str exp, " +
formatNumber(this.workDefExpGained, 4) + " def exp, " +
formatNumber(this.workDexExpGained, 4) + " dex exp, " +
formatNumber(this.workAgiExpGained, 4) + " agi exp, and " +
formatNumber(this.workChaExpGained, 4) + " cha exp.";
numeralWrapper.format(this.workRepGained, '0,0.0000') + " rep, " +
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " hacking exp, " +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " str exp, " +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " def exp, " +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " dex exp, " +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " agi exp, and " +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " cha exp.";
this.resetWorkStatus();
return res;
}
@ -1350,14 +1347,14 @@ PlayerObject.prototype.takeClass = function(numCycles) {
var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You have been " + className + " for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
"This has cost you: <br>" +
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyLossRate * CYCLES_PER_SEC, 2) + " / sec) <br><br>" +
"$" + numeralWrapper.format(this.workMoneyGained, '0,0.00') + " ($" + numeralWrapper.format(this.workMoneyLossRate * CYCLES_PER_SEC, '0,0.00') + " / sec) <br><br>" +
"You have gained: <br>" +
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * CYCLES_PER_SEC, 4) + " / sec) hacking exp <br>" +
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * CYCLES_PER_SEC, 4) + " / sec) strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * CYCLES_PER_SEC, 4) + " / sec) defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * CYCLES_PER_SEC, 4) + " / sec) dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * CYCLES_PER_SEC, 4) + " / sec) agility exp <br>" +
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * CYCLES_PER_SEC, 4) + " / sec) charisma exp <br>" +
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workHackExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) hacking exp <br>" +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workStrExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) strength exp <br>" +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workDefExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) defense exp <br>" +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workDexExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) dexterity exp <br>" +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workAgiExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) agility exp <br>" +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " (" + numeralWrapper.format(this.workChaExpGainRate * CYCLES_PER_SEC, '0,0.0000') + " / sec) charisma exp <br>" +
"You may cancel at any time";
}
@ -1373,14 +1370,14 @@ PlayerObject.prototype.finishClass = function(sing=false) {
this.updateSkillLevels();
var txt = "After " + this.className + " for " + convertTimeMsToTimeElapsedString(this.timeWorked) + ", <br>" +
"you spent a total of $" + formatNumber(this.workMoneyGained * -1, 2) + ". <br><br>" +
"you spent a total of $" + numeralWrapper.format(this.workMoneyGained * -1, '0,0.00') + ". <br><br>" +
"You earned a total of: <br>" +
formatNumber(this.workHackExpGained, 4) + " hacking exp <br>" +
formatNumber(this.workStrExpGained, 4) + " strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " agility exp <br>" +
formatNumber(this.workChaExpGained, 4) + " charisma exp<br>";
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " hacking exp <br>" +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " strength exp <br>" +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " defense exp <br>" +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " dexterity exp <br>" +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " agility exp <br>" +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " charisma exp<br>";
if (!sing) {dialogBoxCreate(txt);}
var mainMenu = document.getElementById("mainmenu-container");
@ -1391,14 +1388,14 @@ PlayerObject.prototype.finishClass = function(sing=false) {
Engine.loadLocationContent();
if (sing) {
var res="After " + this.className + " for " + convertTimeMsToTimeElapsedString(this.timeWorked) + ", " +
"you spent a total of $" + formatNumber(this.workMoneyGained * -1, 2) + ". " +
"you spent a total of $" + numeralWrapper.format(this.workMoneyGained * -1, '0,0.00') + ". " +
"You earned a total of: " +
formatNumber(this.workHackExpGained, 3) + " hacking exp, " +
formatNumber(this.workStrExpGained, 3) + " strength exp, " +
formatNumber(this.workDefExpGained, 3) + " defense exp, " +
formatNumber(this.workDexExpGained, 3) + " dexterity exp, " +
formatNumber(this.workAgiExpGained, 3) + " agility exp, and " +
formatNumber(this.workChaExpGained, 3) + " charisma exp";
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " hacking exp, " +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " strength exp, " +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " defense exp, " +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " dexterity exp, " +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " agility exp, and " +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " charisma exp";
this.resetWorkStatus();
return res;
}
@ -1489,23 +1486,23 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
if(this.singFnCrimeWorkerScript.disableLogs.ALL == null && this.singFnCrimeWorkerScript.disableLogs.commitCrime == null) {
this.singFnCrimeWorkerScript.scriptRef.log("Crime successful! Gained " +
numeralWrapper.format(this.workMoneyGained, "$0.000a") + ", " +
formatNumber(this.workHackExpGained, 3) + " hack exp, " +
formatNumber(this.workStrExpGained, 3) + " str exp, " +
formatNumber(this.workDefExpGained, 3) + " def exp, " +
formatNumber(this.workDexExpGained, 3) + " dex exp, " +
formatNumber(this.workAgiExpGained, 3) + " agi exp, " +
formatNumber(this.workChaExpGained, 3) + " cha exp.");
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " hack exp, " +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " str exp, " +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " def exp, " +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " dex exp, " +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " agi exp, " +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " cha exp.");
}
} else {
dialogBoxCreate("Crime successful! <br><br>" +
"You gained:<br>"+
numeralWrapper.format(this.workMoneyGained, "$0.000a") + "<br>" +
formatNumber(this.workHackExpGained, 4) + " hacking experience <br>" +
formatNumber(this.workStrExpGained, 4) + " strength experience<br>" +
formatNumber(this.workDefExpGained, 4) + " defense experience<br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity experience<br>" +
formatNumber(this.workAgiExpGained, 4) + " agility experience<br>" +
formatNumber(this.workChaExpGained, 4) + " charisma experience");
"$" + numeralWrapper.format(this.workMoneyGained, '0,0.00') + "<br>" +
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " hacking experience <br>" +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " strength experience<br>" +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " defense experience<br>" +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " dexterity experience<br>" +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " agility experience<br>" +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " charisma experience");
}
} else {
@ -1519,22 +1516,22 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
if (this.committingCrimeThruSingFn) {
if(this.singFnCrimeWorkerScript.disableLogs.ALL == null && this.singFnCrimeWorkerScript.disableLogs.commitCrime == null) {
this.singFnCrimeWorkerScript.scriptRef.log("Crime failed! Gained " +
formatNumber(this.workHackExpGained, 3) + " hack exp, " +
formatNumber(this.workStrExpGained, 3) + " str exp, " +
formatNumber(this.workDefExpGained, 3) + " def exp, " +
formatNumber(this.workDexExpGained, 3) + " dex exp, " +
formatNumber(this.workAgiExpGained, 3) + " agi exp, " +
formatNumber(this.workChaExpGained, 3) + " cha exp.");
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " hack exp, " +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " str exp, " +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " def exp, " +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " dex exp, " +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " agi exp, " +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " cha exp.");
}
} else {
dialogBoxCreate("Crime failed! <br><br>" +
"You gained:<br>"+
formatNumber(this.workHackExpGained, 4) + " hacking experience <br>" +
formatNumber(this.workStrExpGained, 4) + " strength experience<br>" +
formatNumber(this.workDefExpGained, 4) + " defense experience<br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity experience<br>" +
formatNumber(this.workAgiExpGained, 4) + " agility experience<br>" +
formatNumber(this.workChaExpGained, 4) + " charisma experience");
numeralWrapper.format(this.workHackExpGained, '0,0.0000') + " hacking experience <br>" +
numeralWrapper.format(this.workStrExpGained, '0,0.0000') + " strength experience<br>" +
numeralWrapper.format(this.workDefExpGained, '0,0.0000') + " defense experience<br>" +
numeralWrapper.format(this.workDexExpGained, '0,0.0000') + " dexterity experience<br>" +
numeralWrapper.format(this.workAgiExpGained, '0,0.0000') + " agility experience<br>" +
numeralWrapper.format(this.workChaExpGained, '0,0.0000') + " charisma experience");
}
}
@ -1912,10 +1909,10 @@ PlayerObject.prototype.reapplyAllAugmentations = function(resetMultipliers=true)
this.augmentations[i].name = "Hacknet Node NIC Architecture Neural-Upload";
}
var augName = this.augmentations[i].name;
const augName = this.augmentations[i].name;
var aug = Augmentations[augName];
if (aug == null) {
console.log("WARNING: Invalid augmentation name");
console.log(`WARNING: Invalid augmentation name in Player.reapplyAllAugmentations(). Aug ${augName} will be skipped`);
continue;
}
aug.owned = true;

6
src/SaveObject.js Normal file → Executable file

@ -24,7 +24,7 @@ import {Reviver, Generic_toJSON,
import {createElement} from "../utils/uiHelpers/createElement";
import {createPopup} from "../utils/uiHelpers/createPopup";
import {createStatusText} from "./ui/createStatusText";
import {formatNumber} from "../utils/StringHelperFunctions";
import {numeralWrapper} from "./ui/numeralFormat";
import {removeElementById} from "../utils/uiHelpers/removeElementById";
import Decimal from "decimal.js";
@ -517,8 +517,8 @@ function loadImportedGame(saveObj, saveString) {
Player.lastUpdate = Engine._lastUpdate;
Engine.start(); //Run main game loop and Scripts loop
dialogBoxCreate("While you were offline, your scripts generated <span class='money-gold'>$" +
formatNumber(offlineProductionFromScripts, 2) + "</span> and your Hacknet Nodes generated <span class='money-gold'>$" +
formatNumber(offlineProductionFromHacknetNodes, 2) + "</span>");
numeralWrapper.format(offlineProductionFromScripts, '0,0.00') + "</span> and your Hacknet Nodes generated <span class='money-gold'>$" +
numeralWrapper.format(offlineProductionFromHacknetNodes, '0,0.00') + "</span>");
return true;
}

@ -33,6 +33,7 @@ import {displayCreateProgramContent,
getNumAvailableCreateProgram,
initCreateProgramButtons,
Programs} from "./CreateProgram";
import {createDevMenu, closeDevMenu} from "./DevMenu";
import {displayFactionContent, joinFaction,
processPassiveFactionRepGain, Factions,
inviteToFaction, initFactions} from "./Faction";
@ -193,41 +194,6 @@ const Engine = {
tutorialFactionsButton: null,
tutorialAugmentationsButton: null,
tutorialBackButton: null,
//Dev menu
devMenuGiveMoney: null,
devMenuGiveRam: null,
devMenuAugDropdown: null,
devMenuAddAug: null,
devMenuTriggerBitFlume: null,
devMenuFactionDropdown: null,
devMenuAddFaction: null,
devMenuOpen: null,
devMenuMinSecurity: null,
devMenuMaxMoney: null,
devMenuConnectDropdown: null,
devMenuConnect: null,
devMenuProgramsDropdown: null,
devMenuAddProgram: null,
devMenuHackingExp: null,
devMenuAddHacking: null,
devMenuStrengthExp: null,
devMenuAddStrength: null,
devMenuDefenseExp: null,
devMenuAddDefense: null,
devMenuDexterityExp: null,
devMenuAddDexterity: null,
devMenuAgilityExp: null,
devMenuAddAgility: null,
devMenuCharismaExp: null,
devMenuAddCharisma: null,
devMenuIntelligenceExp: null,
devMenuAddIntelligence: null,
devMenuEnableIntelligence: null,
devMenuDisableIntelligence: null,
devMenuSFN: null,
devMenuSFLvl: null,
devMenuAddSF: null,
},
//Display objects
@ -253,7 +219,6 @@ const Engine = {
factionAugmentationsContent: null,
augmentationsContent: null,
tutorialContent: null,
devMenuContent: null,
infiltrationContent: null,
stockMarketContent: null,
locationContent: null,
@ -364,8 +329,7 @@ const Engine = {
loadDevMenuContent: function() {
Engine.hideAllContent();
Engine.Display.devMenuContent.style.display = "block";
Engine.displayDevMenuContent();
createDevMenu();
routing.navigateTo(Page.DevMenu);
document.getElementById("dev-menu-link").classList.add("active");
},
@ -506,7 +470,6 @@ const Engine = {
Engine.Display.factionAugmentationsContent.style.display = "none";
Engine.Display.augmentationsContent.style.display = "none";
Engine.Display.tutorialContent.style.display = "none";
Engine.Display.devMenuContent.style.display = "none";
Engine.Display.locationContent.style.display = "none";
Engine.Display.workInProgressContent.style.display = "none";
Engine.Display.redPillContent.style.display = "none";
@ -553,6 +516,9 @@ const Engine = {
document.getElementById("bladeburner-menu-link").classList.remove("active");
document.getElementById("corporation-menu-link").classList.remove("active");
document.getElementById("gang-menu-link").classList.remove("active");
// Close dev menu
closeDevMenu();
},
displayCharacterOverviewInfo: function() {
@ -845,43 +811,6 @@ const Engine = {
document.getElementById("tutorial-text").style.display = "none";
},
displayDevMenuContent: function() {
Engine.Clickables.devMenuGiveMoney.style.display = "block";
Engine.Clickables.devMenuGiveRam.style.display = "block";
Engine.Clickables.devMenuAugDropdown.style.display = "block";
Engine.Clickables.devMenuAddAug.style.display = "block";
Engine.Clickables.devMenuTriggerBitFlume.style.display = "block";
Engine.Clickables.devMenuFactionDropdown.style.display = "block";
Engine.Clickables.devMenuAddFaction.style.display = "block";
Engine.Clickables.devMenuOpen.style.display = "block";
Engine.Clickables.devMenuMinSecurity.style.display = "block";
Engine.Clickables.devMenuMaxMoney.style.display = "block";
Engine.Clickables.devMenuConnectDropdown.style.display = "block";
Engine.Clickables.devMenuConnect.style.display = "block";
Engine.Clickables.devMenuProgramsDropdown.style.display = "block";
Engine.Clickables.devMenuAddProgram.style.display = "block";
Engine.Clickables.devMenuHackingExp.style.display = "block";
Engine.Clickables.devMenuAddHacking.style.display = "block";
Engine.Clickables.devMenuStrengthExp.style.display = "block";
Engine.Clickables.devMenuAddStrength.style.display = "block";
Engine.Clickables.devMenuDefenseExp.style.display = "block";
Engine.Clickables.devMenuAddDefense.style.display = "block";
Engine.Clickables.devMenuDexterityExp.style.display = "block";
Engine.Clickables.devMenuAddDexterity.style.display = "block";
Engine.Clickables.devMenuAgilityExp.style.display = "block";
Engine.Clickables.devMenuAddAgility.style.display = "block";
Engine.Clickables.devMenuCharismaExp.style.display = "block";
Engine.Clickables.devMenuAddCharisma.style.display = "block";
Engine.Clickables.devMenuIntelligenceExp.style.display = "block";
Engine.Clickables.devMenuAddIntelligence.style.display = "block";
Engine.Clickables.devMenuEnableIntelligence.style.display = "block";
Engine.Clickables.devMenuDisableIntelligence.style.display = "block";
Engine.Clickables.devMenuSFN.style.display = "block";
Engine.Clickables.devMenuSFLvl.style.display = "block";
Engine.Clickables.devMenuAddSF.style.display = "block";
},
//Displays the text when a section of the Tutorial is opened
displayTutorialPage: function(text) {
document.getElementById("tutorial-getting-started-link").style.display = "none";
@ -1526,9 +1455,6 @@ const Engine = {
Engine.Display.tutorialContent = document.getElementById("tutorial-container");
Engine.Display.tutorialContent.style.display = "none";
Engine.Display.devMenuContent = document.getElementById("dev-menu-container");
Engine.Display.devMenuContent.style.display = "none";
Engine.Display.infiltrationContent = document.getElementById("infiltration-container");
Engine.Display.infiltrationContent.style.display = "none";
@ -1615,190 +1541,6 @@ const Engine = {
Engine.Clickables.tutorialBackButton.addEventListener("click", function() {
Engine.displayTutorialContent();
});
// dev menu buttons
Engine.Clickables.devMenuGiveMoney = document.getElementById("dev-need-money");
Engine.Clickables.devMenuGiveMoney.addEventListener("click", function() {
Player.gainMoney(1e15);
});
Engine.Clickables.devMenuGiveRam = document.getElementById("dev-need-ram");
Engine.Clickables.devMenuGiveRam.addEventListener("click", function() {
Player.getHomeComputer().maxRam *= 2;
});
Engine.Clickables.devMenuAugDropdown = document.getElementById("dev-menu-aug-dropdown");
const augDD = Engine.Clickables.devMenuAugDropdown;
for(const i in AugmentationNames) {
augDD.options[augDD.options.length] = new Option(AugmentationNames[i], AugmentationNames[i]);
}
Engine.Clickables.devMenuAddAug = document.getElementById("dev-add-aug");
Engine.Clickables.devMenuAddAug.addEventListener("click", function() {
Player.queueAugmentation(augDD.options[augDD.selectedIndex].value);
});
Engine.Clickables.devMenuTriggerBitFlume = document.getElementById("dev-bit-flume");
Engine.Clickables.devMenuTriggerBitFlume.addEventListener("click", function() {
hackWorldDaemon(Player.bitNodeN, true);
});
Engine.Clickables.devMenuFactionDropdown = document.getElementById("dev-menu-faction-dropdown");
const facDD = Engine.Clickables.devMenuFactionDropdown;
for(const i in Factions) {
facDD.options[facDD.options.length] = new Option(Factions[i].name, Factions[i].name);
}
Engine.Clickables.devMenuAddFaction = document.getElementById("dev-add-faction");
Engine.Clickables.devMenuAddFaction.addEventListener("click", function() {
const factionName = facDD.options[facDD.selectedIndex].value;
Player.receiveInvite(factionName);
});
Engine.Clickables.devMenuOpen = document.getElementById("dev-open-all");
Engine.Clickables.devMenuOpen.addEventListener("click", function() {
for(const i in AllServers) {
AllServers[i].hasAdminRights = true;
AllServers[i].sshPortOpen = true;
AllServers[i].ftpPortOpen = true;
AllServers[i].smtpPortOpen = true;
AllServers[i].httpPortOpen = true;
AllServers[i].sqlPortOpen = true;
AllServers[i].openPortCount = 5;
}
});
Engine.Clickables.devMenuMinSecurity = document.getElementById("dev-min-security");
Engine.Clickables.devMenuMinSecurity.addEventListener("click", function() {
for(const i in AllServers) {
AllServers[i].hackDifficulty = AllServers[i].minDifficulty;
}
});
Engine.Clickables.devMenuMaxMoney = document.getElementById("dev-max-money");
Engine.Clickables.devMenuMaxMoney.addEventListener("click", function() {
for(const i in AllServers) {
AllServers[i].moneyAvailable = AllServers[i].moneyMax;
}
});
Engine.Clickables.devMenuConnectDropdown = document.getElementById("dev-menu-connect-dropdown");
const connectDD = Engine.Clickables.devMenuConnectDropdown;
for(const i in AllServers) {
connectDD.options[connectDD.options.length] = new Option(AllServers[i].hostname, AllServers[i].hostname);
}
Engine.Clickables.devMenuConnect = document.getElementById("dev-connect");
Engine.Clickables.devMenuConnect.addEventListener("click", function() {
const host = connectDD.options[connectDD.selectedIndex].value;
Terminal.connectToServer(host);
});
Engine.Clickables.devMenuProgramsDropdown = document.getElementById("dev-menu-add-program-dropdown");
const programsDD = Engine.Clickables.devMenuProgramsDropdown;
for(const i in Programs) {
programsDD.options[programsDD.options.length] = new Option(Programs[i].name, Programs[i].name);
}
Engine.Clickables.devMenuAddProgram = document.getElementById("dev-add-program");
Engine.Clickables.devMenuAddProgram.addEventListener("click", function() {
const program = programsDD.options[programsDD.selectedIndex].value;
if(!Player.hasProgram(program)) {
Player.getHomeComputer().programs.push(program);
}
});
Engine.Clickables.devMenuHackingExp = document.getElementById("dev-hacking-exp");
Engine.Clickables.devMenuAddHacking = document.getElementById("dev-add-hacking");
Engine.Clickables.devMenuAddHacking.addEventListener("click", function() {
const exp = parseInt(Engine.Clickables.devMenuHackingExp.value);
Player.gainHackingExp(exp);
Player.updateSkillLevels();
});
Engine.Clickables.devMenuStrengthExp = document.getElementById("dev-strength-exp");
Engine.Clickables.devMenuAddStrength = document.getElementById("dev-add-strength");
Engine.Clickables.devMenuAddStrength.addEventListener("click", function() {
const exp = parseInt(Engine.Clickables.devMenuStrengthExp.value);
Player.gainStrengthExp(exp);
Player.updateSkillLevels();
});
Engine.Clickables.devMenuDefenseExp = document.getElementById("dev-defense-exp");
Engine.Clickables.devMenuAddDefense = document.getElementById("dev-add-defense");
Engine.Clickables.devMenuAddDefense.addEventListener("click", function() {
const exp = parseInt(Engine.Clickables.devMenuDefenseExp.value);
Player.gainDefenseExp(exp);
Player.updateSkillLevels();
});
Engine.Clickables.devMenuDexterityExp = document.getElementById("dev-dexterity-exp");
Engine.Clickables.devMenuAddDexterity = document.getElementById("dev-add-dexterity");
Engine.Clickables.devMenuAddDexterity.addEventListener("click", function() {
const exp = parseInt(Engine.Clickables.devMenuDexterityExp.value);
Player.gainDexterityExp(exp);
Player.updateSkillLevels();
});
Engine.Clickables.devMenuAgilityExp = document.getElementById("dev-agility-exp");
Engine.Clickables.devMenuAddAgility = document.getElementById("dev-add-agility");
Engine.Clickables.devMenuAddAgility.addEventListener("click", function() {
const exp = parseInt(Engine.Clickables.devMenuAgilityExp.value);
Player.gainAgilityExp(exp);
Player.updateSkillLevels();
});
Engine.Clickables.devMenuCharismaExp = document.getElementById("dev-charisma-exp");
Engine.Clickables.devMenuAddCharisma = document.getElementById("dev-add-charisma");
Engine.Clickables.devMenuAddCharisma.addEventListener("click", function() {
const exp = parseInt(Engine.Clickables.devMenuCharismaExp.value);
Player.gainCharismaExp(exp);
Player.updateSkillLevels();
});
Engine.Clickables.devMenuIntelligenceExp = document.getElementById("dev-intelligence-exp");
Engine.Clickables.devMenuAddIntelligence = document.getElementById("dev-add-intelligence");
Engine.Clickables.devMenuAddIntelligence.addEventListener("click", function() {
const exp = parseInt(Engine.Clickables.devMenuIntelligenceExp.value);
Player.gainIntelligenceExp(exp);
Player.updateSkillLevels();
});
Engine.Clickables.devMenuEnableIntelligence = document.getElementById("dev-enable-intelligence");
Engine.Clickables.devMenuEnableIntelligence.addEventListener("click", function() {
Player.intelligence = 1;
});
Engine.Clickables.devMenuDisableIntelligence = document.getElementById("dev-disable-intelligence");
Engine.Clickables.devMenuDisableIntelligence.addEventListener("click", function() {
Player.intelligence = 0;
});
Engine.Clickables.devMenuSFN = document.getElementById("dev-sf-n");
Engine.Clickables.devMenuSFLvl = document.getElementById("dev-sf-lvl");
Engine.Clickables.devMenuAddSF = document.getElementById("dev-add-source-file");
Engine.Clickables.devMenuAddSF.addEventListener("click", function() {
const sfN = parseInt(Engine.Clickables.devMenuSFN.value);
const sfLvl = parseInt(Engine.Clickables.devMenuSFLvl.value);
let sfIndex = -1;
for(const i in Player.sourceFiles) {
if(Player.sourceFiles[i].n === sfN) {
sfIndex = i;
break;
}
}
if(sfIndex === -1) { // add fresh source file
Player.sourceFiles.push(new PlayerOwnedSourceFile(sfN, sfLvl));
} else if(sfLvl === 0) { // remove a source file.
if(sfIndex === -1) { // doesn't have it anyway.
return;
}
Player.sourceFiles.splice(sfIndex, 1);
} else { // set source file level
Player.sourceFiles[sfIndex].lvl=sfLvl;
}
});
},
/* Initialization */
@ -1900,7 +1642,7 @@ const Engine = {
this.classList.toggle("opened");
const elems = [tutorial, options];
const links = [tutorialLink, optionsLink];
if(process.env.NODE_ENV === "development") {
if (process.env.NODE_ENV === "development") {
elems.push(document.getElementById("dev-tab"));
links.push(document.getElementById("dev-menu-link"));
}

@ -490,58 +490,6 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
<p id="tutorial-text"> </p>
</div>
<!-- dev menu -->
<div id="dev-menu-container" class="generic-menupage-container">
<p id="dev-menu-text">If you see this menu you can pretty much break the game. It's recommended that you use this menu only to setup a save file appropriate to test a new feature or bug fix.</p>
<p id="dev-menu-text">Generic</p>
<a id="dev-need-money" class="a-link-button">Add $1000t</a>
<a id="dev-need-ram" class="a-link-button">Double home RAM</a>
<p id="dev-menu-text">Augmentation related: </p>
<!-- gets populated with the list of all augments -->
<select id="dev-menu-aug-dropdown" class="dropdown"></select>
<a id="dev-add-aug" class="a-link-button tooltip">Queue Augmentation<span class="tooltiptext">May require save + reload</span></a>
<input id="dev-sf-n" type="number" class="text-input" placeholder="SourceFile-N"><input id="dev-sf-lvl" type="number" class="text-input" placeholder="SourceFile-Lvl"><a id="dev-add-source-file" class="a-link-button tooltip"> Add/Remove source file <span class="tooltiptext">If Lvl == 0 the sf will be removed, calling it with another level will replace your current source file. You CAN set a source file higher than it's maximum level.</span></a>
<p id="dev-menu-text">Faction related: </p>
<select id="dev-menu-faction-dropdown" class="dropdown"></select>
<a id="dev-add-faction" class="a-link-button tooltip">Receive invite<span class="tooltiptext">May require save + reload</span></a>
<p id="dev-menu-text">Program related: </p>
<select id="dev-menu-connect-dropdown" class="dropdown"></select>
<a id="dev-connect" class="a-link-button tooltip">Connect<span class="tooltiptext">Connect to the target server.</span></a>
<select id="dev-menu-add-program-dropdown" class="dropdown"></select>
<a id="dev-add-program" class="a-link-button tooltip">Add Program<span class="tooltiptext">Add this program to the player home server, won't add the same program twice.</span></a>
<a id="dev-bit-flume" class="a-link-button tooltip">Trigger BitFlume<span class="tooltiptext">Quick escape to change BN, does not give SFs</span></a>
<p id="dev-menu-text">Server related: </p>
<a id="dev-open-all" class="a-link-button tooltip">NUKE + ports all servers<span class="tooltiptext">Opens all ports, nukes all servers, gains root access to everything (still need the appropriate hacking level)</span></a>
<a id="dev-min-security" class="a-link-button tooltip">minimize all servers security<span class="tooltiptext">All servers security will be set to their minimum security</span></a>
<a id="dev-max-money" class="a-link-button tooltip">maximize all servers money<span class="tooltiptext">Set all servers available money to maximum for that server</span></a>
<p id="dev-menu-text">Exp/stats related: </p>
<input id="dev-hacking-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-hacking" class="a-link-button tooltip">add hacking exp<span class="tooltiptext">Add that many hacking experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<input id="dev-strength-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-strength" class="a-link-button tooltip">add strength exp<span class="tooltiptext">Add that many strength experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<input id="dev-defense-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-defense" class="a-link-button tooltip">add defense exp<span class="tooltiptext">Add that many defense experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<input id="dev-dexterity-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-dexterity" class="a-link-button tooltip">add dexterity exp<span class="tooltiptext">Add that many dexterity experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<input id="dev-agility-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-agility" class="a-link-button tooltip">add agility exp<span class="tooltiptext">Add that many agility experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<input id="dev-charisma-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-charisma" class="a-link-button tooltip">add charisma exp<span class="tooltiptext">Add that many charisma experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<input id="dev-intelligence-exp" type="number" class="text-input" placeholder="+exp/-exp (int)">
<a id="dev-add-intelligence" class="a-link-button tooltip">add intelligence exp<span class="tooltiptext">Add that many intelligence experience point, use negative numbers to remove, don't worry about going under 0 exp</span></a>
<a id="dev-enable-intelligence" class="a-link-button tooltip"> enable intelligence<span class="tooltiptext">Enables the intelligence stat</span></a>
<a id="dev-disable-intelligence" class="a-link-button tooltip"> disable intelligence<span class="tooltiptext">Disables the intelligence stat</span></a>
</div>
<!-- Location (visiting a location in World) -->
<div id="location-container" class="generic-menupage-container">
<a id="location-return-to-world-button" class="a-link-button"> Return to World </a>