Merge pull request #50 from danielyxie/dev

Dev v0.20.0
This commit is contained in:
danielyxie 2017-06-06 23:11:02 -05:00 committed by GitHub
commit 91a360bc7f
20 changed files with 1493 additions and 1198 deletions

@ -144,27 +144,113 @@ background-color: #555;
padding: 4px;
}
.active-scripts-list > li {
margin: 6px;
width: 70%;
.active-scripts-server-header {
background-color: #444;
font-size: 20px;
color: white;
margin: 6px 6px 0px 6px;
padding: 6px;
cursor: pointer;
width: 60%;
text-align: left;
border: none;
outline: none;
}
.active-scripts-list>li h2{
.active-scripts-server-header.active,
.active-scripts-server-header:hover {
background-color: #555;
}
.active-scripts-server-header.active:hover {
background-color: #666;
}
.active-scripts-server-header:after {
content: '\02795'; /* "plus" sign (+) */
font-size: 13px;
color: white;
float: right;
margin-left: 5px;
}
.active-scripts-server-header.active:after {
content: "\2796"; /* "minus" sign (-) */
font-size: 13px;
color: white;
float: right;
margin-left: 5px;
}
.active-scripts-server-panel {
margin: 0px 6px 6px 6px;
padding: 0px 6px 6px 6px;
width: 55%;
margin-left: 5%;
display: none;
}
.active-scripts-server-panel div,
.active-scripts-server-panel ul,
.active-scripts-server-panel ul > li {
background-color: #555;
}
.active-scripts-script-header {
background-color: #555;
color: #66ff33;
padding-top: 10px;
padding-left: 10px;
background-color: #333;
text-decoration: none;
padding: 4px;
padding-left: 10px;
cursor: pointer;
width: auto;
text-align: left;
border: none;
outline: none;
}
.active-scripts-list>li p {
color: #66ff33;
padding: 10px;
padding-left: 40px;
background-color: #333;
text-decoration: none;
.active-scripts-script-header:hover,
.active-scripts-script-header.active:hover {
background-color: #666;
}
.active-scripts-script-header.active {
background-color: #555;
}
.active-scripts-script-header:after {
content: '\02795'; /* "plus" sign (+) */
font-size: 13px;
color: #66ff33;
float: right;
margin-left: 5px;
}
.active-scripts-script-header.active:after {
content: "\2796"; /* "minus" sign (-) */
font-size: 13px;
color: #66ff33;
float: right;
margin-left: 5px;
}
.active-scripts-script-panel {
padding: 0 18px;
background-color: #555;
width: auto;
display: none;
}
.active-scripts-script-panel p,
.active-scripts-script-panel h2,
.active-scripts-script-panel ul,
.active-scripts-script-panel li {
background-color: #555;
width: auto;
color: white;
margin-left: 5%;
}
/* Hacknet Nodes */
#hacknet-nodes-container {
position: fixed;
@ -299,7 +385,8 @@ background-color: #555;
padding-left: 10px;
height: 100%;
margin-left: 10%;
width: 90%;
width: 99%;
overflow: auto;
overflow-y: auto;
}
@ -308,8 +395,6 @@ background-color: #555;
margin: 6px;
}
#faction-hack-div,
#faction-fieldwork-div,
#faction-securitywork-div,

@ -18,19 +18,20 @@
z-index: 2;
width: 50%;
height: auto;
top: 50%;
max-height: 40%;
top: 40%;
left: 50%;
margin: -10% 0 0 -25%;
overflow: auto;
background-color: black;
background-color: rgba(0,0,0,0.4);
border: 5px solid #FFFFFF;
}
.dialog-box-content {
z-index: 2;
background-color: black;
padding: 10px;
border: 5px solid #FFFFFF;
}
.dialog-box-close-button {

@ -33,6 +33,7 @@
<script src="src/NetscriptParser.js"></script>
<script src="src/NetscriptEvaluator.js"></script>
<script src="src/NetscriptEnvironment.js"></script>
<script src="src/NetscriptFunctions.js"></script>
<!-- Main game files -->
<script src="src/Constants.js"></script>
@ -58,6 +59,7 @@
<script src="src/InteractiveTutorial.js"></script>
<script src="src/Alias.js"></script>
<script src="src/Message.js"></script>
<script src="src/ActiveScriptsUI.js"></script>
<script src="src/engine.js"></script>
@ -163,8 +165,9 @@
<!-- Active scripts info page -->
<div id="active-scripts-container">
<p id="active-scripts-text"> This page displays a list of all scripts that are currently running across every machine. It also gives
information about their production </p>
<p id="active-scripts-text"> This page displays a list of all of your scripts that are currently running across every machine. It also
provides information about each script's production. The scripts are categorized by the hostname of the servers on which
they are running. </p>
<p id="active-scripts-total-prod"> Total online production rate: </p>
<ul class="active-scripts-list" id="active-scripts-list" style="list-style: none;">
</ul>
@ -516,12 +519,13 @@
</div>
<p>
<br><br><br>
<br>
As your reputation with this faction rises, you will unlock Augmentations, which you
can purchase to enhance your abilities.
<br><br>
</p>
<a id="faction-purchase-augmentations" class="a-link-button">Purchase Augmentations</a>
<br><br><br><br>
</div>
<div id="faction-augmentations-container">

222
src/ActiveScriptsUI.js Normal file

@ -0,0 +1,222 @@
/* Active Scripts UI*/
function setActiveScriptsClickHandlers() {
//Server panel click handlers
var serverPanels = document.getElementsByClassName("active-scripts-server-header");
if (serverPanels == null) {
console.log("ERROR: Could not find Active Scripts server panels");
return;
}
for (i = 0; i < serverPanels.length; ++i) {
serverPanels[i].onclick = function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
}
}
//Script Panel click handlers
var scriptPanels = document.getElementsByClassName("active-scripts-script-header");
if (scriptPanels == null) {
console.log("ERROR: Could not find Active Scripts panels for individual scripts");
return;
}
for (var i = 0; i < scriptPanels.length; ++i) {
scriptPanels[i].onclick = function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
}
}
}
//Returns the ul element containins all script items for a specific server
function getActiveScriptsServerList(server) {
if (server == null) {return null;}
var panelname = "active-scripts-server-panel-" + server.hostname;
var item = document.getElementById(panelname + "-script-list");
if (item == null) {
console.log("ERROR: Cannot find list for: " + server.hostname);
}
return item;
}
function createActiveScriptsServerPanel(server) {
var panelname = "active-scripts-server-panel-" + server.hostname;
var activeScriptsList = document.getElementById("active-scripts-list");
//Div of entire Panel
var panelDiv = document.createElement("div");
panelDiv.setAttribute("id", panelname);
//Panel Header
var panelHdr = document.createElement("button");
panelHdr.setAttribute("class", "active-scripts-server-header")
panelHdr.setAttribute("id", panelname + "-hdr");
panelHdr.innerHTML = server.hostname;
//Panel content
var panelContentDiv = document.createElement("div");
panelContentDiv.setAttribute("class", "active-scripts-server-panel");
panelContentDiv.setAttribute("id", panelname + "-content");
//List of scripts
var panelScriptList = document.createElement("ul");
panelScriptList.setAttribute("id", panelname + "-script-list");
panelContentDiv.appendChild(panelScriptList);
panelDiv.appendChild(panelHdr);
panelDiv.appendChild(panelContentDiv);
activeScriptsList.appendChild(panelDiv);
setActiveScriptsClickHandlers() //Reset click handlers
return panelDiv;
//TODO Alphabetize Active Scripts list?
}
//Deletes the info for a particular server (Dropdown header + Panel with all info)
//in the Active Scripts page if it exists
function deleteActiveScriptsServerPanel(server) {
var panelname = "active-scripts-server-panel-" + server.hostname;
var panel = document.getElementById(panelname);
if (panel == null) {
console.log("No such panel exists: " + panelname);
return;
}
//Remove the panel if it has no elements
var scriptList = document.getElementById(panelname + "-script-list");
if (scriptList.childNodes.length == 0) {
panel.parentNode.removeChild(panel);
}
}
function addActiveScriptsItem(workerscript) {
//Get server panel
var server = getServer(workerscript.serverIp);
if (server == null) {
console.log("ERROR: Invalid server IP for workerscript.");
return;
}
var panelname = "active-scripts-server-panel-" + server.hostname;
var panel = document.getElementById(panelname);
if (panel == null) {
panel = createActiveScriptsServerPanel(server);
}
//Create the element itself. Each element is an accordion collapsible
var itemName = "active-scripts-" + server.hostname + "-" + workerscript.name;
var item = document.createElement("li");
item.setAttribute("id", itemName);
var btn = document.createElement("button");
btn.setAttribute("class", "active-scripts-script-header");
btn.innerHTML = workerscript.name;
var itemContentDiv = document.createElement("div");
itemContentDiv.setAttribute("class", "active-scripts-script-panel");
itemContentDiv.setAttribute("id", itemName + "-content");
item.appendChild(btn);
item.appendChild(itemContentDiv);
createActiveScriptsText(workerscript, itemContentDiv);
//Append element to list
var list = getActiveScriptsServerList(server);
list.appendChild(item);
setActiveScriptsClickHandlers() //Reset click handlers
}
function deleteActiveScriptsItem(workerscript) {
var server = getServer(workerscript.serverIp);
if (server == null) {
console.log("ERROR: Invalid server IP for workerscript.");
return;
}
var itemName = "active-scripts-" + server.hostname + "-" + workerscript.name;
var li = document.getElementById(itemName);
if (li == null) {
console.log("could not find Active scripts li element for: " + workerscript.name);
return;
}
li.parentNode.removeChild(li);
deleteActiveScriptsServerPanel(server);
}
//Update the ActiveScriptsItems array
function updateActiveScriptsItems() {
var total = 0;
for (var i = 0; i < workerScripts.length; ++i) {
total += updateActiveScriptsItemContent(workerScripts[i]);
}
document.getElementById("active-scripts-total-prod").innerHTML =
"Total online production rate: $" + formatNumber(total, 2) + " / second";
}
//Updates the content of the given item in the Active Scripts list
function updateActiveScriptsItemContent(workerscript) {
var server = getServer(workerscript.serverIp);
if (server == null) {
console.log("ERROR: Invalid server IP for workerscript.");
return;
}
var itemName = "active-scripts-" + server.hostname + "-" + workerscript.name;
var itemContent = document.getElementById(itemName + "-content")
//Clear the item
while (itemContent.firstChild) {
itemContent.removeChild(itemContent.firstChild);
}
//Add the updated text back. Returns the total online production rate
return createActiveScriptsText(workerscript, itemContent);
}
function createActiveScriptsText(workerscript, item) {
var itemText = document.createElement("p");
//Server ip/hostname
var hostname = workerscript.getServer().hostname;
var serverIpHostname = "Server: " + hostname + "(" + workerscript.serverIp + ")";
//Online
var onlineTotalMoneyMade = "Total online production: $" + formatNumber(workerscript.scriptRef.onlineMoneyMade, 2);
var onlineTotalExpEarned = (Array(26).join(" ") + formatNumber(workerscript.scriptRef.onlineExpGained, 2) + " hacking exp").replace( / /g, "&nbsp;");
var onlineMps = workerscript.scriptRef.onlineMoneyMade / workerscript.scriptRef.onlineRunningTime;
var onlineMpsText = "Online production rate: $" + formatNumber(onlineMps, 2) + "/second";
var onlineEps = workerscript.scriptRef.onlineExpGained / workerscript.scriptRef.onlineRunningTime;
var onlineEpsText = (Array(25).join(" ") + formatNumber(onlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;");
//Offline
var offlineTotalMoneyMade = "Total offline production: $" + formatNumber(workerscript.scriptRef.offlineMoneyMade, 2);
var offlineTotalExpEarned = (Array(27).join(" ") + formatNumber(workerscript.scriptRef.offlineExpGained, 2) + " hacking exp").replace( / /g, "&nbsp;");
var offlineMps = workerscript.scriptRef.offlineMoneyMade / workerscript.scriptRef.offlineRunningTime;
var offlineMpsText = "Offline production rate: $" + formatNumber(offlineMps, 2) + "/second";
var offlineEps = workerscript.scriptRef.offlineExpGained / workerscript.scriptRef.offlineRunningTime;
var offlineEpsText = (Array(26).join(" ") + formatNumber(offlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;");
itemText.innerHTML = serverIpHostname + "<br>" + onlineTotalMoneyMade + "<br>" + onlineTotalExpEarned + "<br>" +
onlineMpsText + "<br>" + onlineEpsText + "<br>" + offlineTotalMoneyMade + "<br>" + offlineTotalExpEarned + "<br>" +
offlineMpsText + "<br>" + offlineEpsText + "<br>";
item.appendChild(itemText);
//Return total online production rate
return onlineMps;
}

@ -1,5 +1,5 @@
CONSTANTS = {
Version: "0.19.7",
Version: "0.20.0",
//Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
//and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@ -11,14 +11,14 @@ CONSTANTS = {
/* Base costs */
BaseCostFor1GBOfRamHome: 40000,
BaseCostFor1GBOfRamServer: 35000, //1 GB of RAM
BaseCostFor1GBOfRamServer: 50000, //1 GB of RAM
BaseCostFor1GBOfRamHacknetNode: 30000,
BaseCostForHacknetNode: 1000,
BaseCostForHacknetNodeCore: 500000,
/* Hacknet Node constants */
HacknetNodeMoneyGainPerLevel: 1.6,
HacknetNodeMoneyGainPerLevel: 1.55,
HacknetNodePurchaseNextMult: 1.42, //Multiplier when purchasing an additional hacknet node
HacknetNodeUpgradeLevelMult: 1.045, //Multiplier for cost when upgrading level
HacknetNodeUpgradeRamMult: 1.28, //Multiplier for cost when upgrading RAM
@ -34,15 +34,15 @@ CONSTANTS = {
/* Script related things */
//Time (ms) it takes to run one operation in Netscript.
CodeInstructionRunTime: 1500,
CodeInstructionRunTime: 500,
//RAM Costs for differenc commands
ScriptWhileRamCost: 0.4,
ScriptForRamCost: 0.4,
//RAM Costs for different commands
ScriptWhileRamCost: 0.2,
ScriptForRamCost: 0.2,
ScriptIfRamCost: 0.1,
ScriptHackRamCost: 0.25,
ScriptGrowRamCost: 0.25,
ScriptWeakenRamCost: 0.25,
ScriptHackRamCost: 0.1,
ScriptGrowRamCost: 0.15,
ScriptWeakenRamCost: 0.15,
ScriptNukeRamCost: 0.05,
ScriptBrutesshRamCost: 0.05,
ScriptFtpcrackRamCost: 0.05,
@ -53,10 +53,13 @@ CONSTANTS = {
ScriptExecRamCost: 1.1,
ScriptScpRamCost: 0.5,
ScriptHasRootAccessRamCost: 0.05,
ScriptGetHostnameRamCost: 0.1,
ScriptGetHackingLevelRamCost: 0.1,
ScriptGetHostnameRamCost: 0.05,
ScriptGetHackingLevelRamCost: 0.05,
ScriptGetServerMoneyRamCost: 0.1,
ScriptGetServerSecurityRamCost: 0.2,
ScriptGetServerSecurityRamCost: 0.1,
ScriptGetServerReqdHackRamCost: 0.1,
ScriptFileExistsRamCost: 0.1,
ScriptIsRunningRamCost: 0.1,
ScriptOperatorRamCost: 0.01,
ScriptPurchaseHacknetRamCost: 1.5,
ScriptHacknetNodesRamCost: 1.0, //Base cost for accessing hacknet nodes array
@ -65,13 +68,14 @@ CONSTANTS = {
ScriptHNUpgCoreRamCost: 0.8,
//Server constants
ServerGrowthRate: 1.002, //Growth rate
ServerFortifyAmount: 0.002, //Amount by which server's security increases when its hacked
ServerWeakenAmount: 0.1, //Amount by which server's security decreases when weakened
ServerBaseGrowthRate: 1.02, //Unadjusted Growth rate
ServerMaxGrowthRate: 1.003, //Maximum possible growth rate (max rate accounting for server security)
ServerFortifyAmount: 0.002, //Amount by which server's security increases when its hacked/grown
ServerWeakenAmount: 0.1, //Amount by which server's security decreases when weakened
//Augmentation Constants
AugmentationCostMultiplier: 4.5, //Used for balancing costs without having to readjust every Augmentation cost
AugmentationRepMultiplier: 1.2, //Used for balancing rep cost without having to readjust every value
AugmentationCostMultiplier: 5, //Used for balancing costs without having to readjust every Augmentation cost
AugmentationRepMultiplier: 1.5, //Used for balancing rep cost without having to readjust every value
//Maximum number of log entries for a script
MaxLogCapacity: 40,
@ -159,6 +163,7 @@ CONSTANTS = {
"hostname Displays the hostname of the machine<br>" +
"ifconfig Displays the IP address of the machine<br>" +
"kill [script] Stops a script that is running on the current machine<br>" +
"killall Stops all running scripts on the current machine<br>" +
"ls Displays all programs and scripts on the machine<br>" +
"mem [script] Displays the amount of RAM the script requires to run<br>" +
"nano [script] Text editor - Open up and edit a script<br>" +
@ -216,8 +221,8 @@ CONSTANTS = {
"When you successfully hack a server. You steal a certain percentage of that server's total money. This " +
"percentage is determined by the server's security and your hacking skill level. The amount of money " +
"on a server is not limitless. So, if you constantly hack a server and deplete its money, then you will " +
"encounter diminishing returns in your hacking (since you are only hacking a certain percentage). A server " +
"will regain money at a slow rate over time. <br><br>" +
"encounter diminishing returns in your hacking (since you are only hacking a certain percentage). You can " +
"increase the amount of money on a server using a script and the grow() function in Netscript.<br><br>" +
"<h1>Server Security</h1><br>" +
"Each server has a security level, which is denoted by a number between 1 and 100. A higher number means " +
"the server has stronger security. As mentioned above, a server's security level is an important factor " +
@ -225,7 +230,8 @@ CONSTANTS = {
"only gives an estimate (with 5% uncertainty). You can also check a server's security in a script, using the " +
"<i>getServerSecurityLevel(server)</i> function in Netscript. See the Netscript documentation for more details. " +
"This function will give you an exact value for a server's security. <br><br>" +
"Whenever a server is hacked manually or through a script, its security level increases by a small amount. This will " +
"Whenever a server is hacked manually or through a script, its security level increases by a small amount. Calling " +
"the grow() command in a script will also increase security level of the target server. These actions will " +
"make it harder for you to hack the server, and decrease the amount of money you can steal. You can lower a " +
"server's security level in a script using the <i>weaken(server)</i> function in Netscript. See the Netscript " +
"documentation for more details",
@ -301,17 +307,27 @@ CONSTANTS = {
"<i>hack(hostname/ip)</i><br>Core function that is used to try and hack servers to steal money and gain hacking experience. The argument passed in must be a string with " +
"either the IP or hostname of the server you want to hack. The runtime for this command depends on your hacking level and the target server's security level. " +
" A script can hack a server from anywhere. It does not need to be running on the same server to hack that server. " +
"For example, you can create a script that hacks the 'foodnstuff' server and run it on your home computer. <br>" +
"For example, you can create a script that hacks the 'foodnstuff' server and run that script on any server in the game. A successful hack() on " +
"a server will raise that server's security level by 0.002. Returns true if the hack is successful and " +
"false otherwise. <br>" +
"Examples: hack('foodnstuff'); or hack('148.192.0.12');<br><br>" +
"<i>sleep(n)</i><br>Suspends the script for n milliseconds. <br>Example: sleep(5000);<br><br>" +
"<i>grow(hostname/ip)</i><br>Use your hacking skills to increase the amount of money available on a server. The argument passed in " +
"must be a string with either the IP or hostname of the target server. The runtime for this command depends on your hacking level and the target server's security level. " +
"The grow() command requires root access to the target server, but " +
"there is no required hacking level to run the command. " +
"Grants 1 hacking exp when it completes. Works offline at a slower rate. <br> Example: grow('foodnstuff');<br><br>" +
"When grow() completes, the money available on a target server will be increased by a certain, fixed percentage. This percentage " +
"is determined by the server's growth rate and varies between servers. Generally, higher-level servers have higher growth rates. <br><br> " +
"Like hack(), grow() can be called on any server, regardless of where the script is running. " +
"The grow() command requires root access to the target server, but there is no required hacking level to run the command. " +
"It grants 0.5 hacking exp when it completes. It also raises the security level of the target server by 0.004. " +
"Returns the number by which the money on the server was multiplied for the growth. " +
"Works offline at a slower rate. <br> Example: grow('foodnstuff');<br><br>" +
"<i>weaken(hostname/ip)</i><br>Use your hacking skills to attack a server's security, lowering the server's security level. The argument passed " +
"in must be a string with either the IP or hostname of the target server. This command requires root access to the target server, but " +
"there is no required hacking level to run the command. Grants 5 hacking exp when it completes. Works offline at a slower rate<br> Example: weaken('foodnstuff');<br><br>" +
"in must be a string with either the IP or hostname of the target server. 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 server by " +
"0.1.<br><br> Like hack() and grow(), weaken() can be called on " +
"any server, regardless of where the script is running. This command requires root access to the target server, but " +
"there is no required hacking level to run the command. Grants 3 hacking exp when it completes. Returns " +
"0.1. Works offline at a slower rate<br> Example: weaken('foodnstuff');<br><br>" +
"<i>print(x)</i> <br> Prints a value or a variable to the scripts logs (which can be viewed with the 'tail [script]' terminal command )<br><br>" +
"<i>nuke(hostname/ip)</i><br>Run NUKE.exe on the target server. NUKE.exe must exist on your home computer. Does NOT work while offline <br> Example: nuke('foodnstuff'); <br><br>" +
"<i>brutessh(hostname/ip)</i><br>Run BruteSSH.exe on the target server. BruteSSH.exe must exist on your home computer. Does NOT work while offline <br> Example: brutessh('foodnstuff');<br><br>" +
@ -327,6 +343,18 @@ CONSTANTS = {
"second argument is a string with the hostname or IP of the 'target server' on which to run the script. The specified script must exist on the target server. Returns " +
"true if the script is successfully started, and false otherwise. Does NOT work while offline<br> " +
"Example: exec('generic-hack.script', 'foodnstuff'); <br> The example above will try to launch the script 'generic-hack.script' on the 'foodnstuff' server.<br><br>" +
"<i>kill(script, [hostname/ip])</i><br> Kills a script on a server. The first argument must be a string with the name of the script. The name is case-sensitive. " +
"The second argument must be a string with the hostname or IP of the target server. The function will try to kill the specified script on the target server. " +
"The second argument is optional. If it is omitted, then the function will try to kill the specified script on the current server (the server running " +
"the script that calls this function). If the script is found on the specified server and is running, then it will be killed and this function " +
"will return true. Otherwise, this function will return false. <br> " +
"Example: kill('foo.script', 'foodnstuff');<br>" +
"Example: kill('foo.script');<br>" +
"The first example above will look for a script called 'foo.script' on the 'foodnstuff' server. If the script exists and is running, then it will " +
"be killed and the function will return true. Otherwise false will be returned. The second example above will do the same thing, except on the " +
"current server (the server running the script that calls the kill() function).<br><br>" +
"<i>killall(hostname/ip)</i><br> Kills all running scripts on the specified server. This function takes a single argument which " +
"must be a string containing the hostname or IP of the target server. This function will always return true. <br><br>" +
"<i>scp(script, hostname/ip)</i><br>Copies a script to another server. The first argument is a string with the filename of the script " +
"to be copied. The second argument is a string with the hostname or IP of the destination server. Returns true if the script is successfully " +
"copied over and false otherwise. <br> Example: scp('hack-template.script', 'foodnstuff');<br><br>" +
@ -339,6 +367,25 @@ CONSTANTS = {
"hostname or IP of the target server. Does NOT work while offline <br> Example: getServerMoneyAvailable('foodnstuff');<br><br>" +
"<i>getServerSecurityLevel(hostname/ip)</i><br>Returns the security level of a server. The argument passed in must be a string with either the " +
"hostname or IP of the target server. A server's security is denoted by a number between 1 and 100. Does NOT work while offline.<br><br>" +
"<i>getServerRequiredHackingLevel(hostname/ip)</i><br> Returns the required hacking level of a server. The argument passed in must be a string with either the " +
"hostname or IP or the target server. Does NOT work while offline <br><br>" +
"<i>fileExists(filename, [hostname/ip])</i><br> Returns a boolean (true or false) indicating whether the specified file exists on a server. " +
"The first argument must be a string with the name of the file. A file can either be a script or a program. A script name is case-sensitive, but a " +
"program is not. For example, fileExists('brutessh.exe') will work fine, even though the actual program is named BruteSSH.exe. <br><br> " +
"The second argument is a string with the hostname or IP of the server on which to search for the program. This second argument is optional. " +
"If it is omitted, then the function will search through the current server (the server running the script that calls this function) for the file. <br> " +
"Example: fileExists('foo.script', 'foodnstuff');<br>" +
"Example: fileExists('ftpcrack.exe');<br><br>" +
"The first example above will return true if the script named 'foo.script' exists on the 'foodnstuff' server, and false otherwise. The second example above will " +
"return true if the current server (the server on which this function runs) contains the FTPCrack.exe program, and false otherwise. <br><br>" +
"<i>isRunning(filename, [hostname/ip])</i><br> Returns a boolean (true or false) indicating whether the specified script is running on a server. " +
"The first argument must be a string with the name of the script. The script name is case sensitive. The second argument is a string with the " +
"hostname or IP of the target server. The function will check whether the script is running on that target server. The second argument is optional. " +
"If it is omitted, then the function will check if the script is running on the current server (the server running the script that calls this function). <br>" +
"Example: isRunning('foo.script', 'foodnstuff');<br>" +
"Example: isRunning('foo.script'); <br><br>" +
"The first example above will return true if there is a script called 'foo.script' is running on the 'foodnstuff' server, and false otherwise. The second " +
"example above will return true if there is a script called 'foo.script' running on the current server, and false otherwise. <br><br>" +
"<i>purchaseHacknetNode()</i><br> Purchases a new Hacknet Node. Returns a number with the index of the Hacknet Node. This index is equivalent to the number " +
"at the end of the Hacknet Node's name (e.g The Hacknet Node named 'hacknet-node-4' will have an index of 4). If the player cannot afford to purchase " +
"a new Hacknet Node then the function will return false. Does NOT work offline<br><br>" +
@ -488,61 +535,42 @@ CONSTANTS = {
"RAM Upgrades on your home computer",
Changelog:
"v0.15 <br>" +
"-Slightly reduced production multiplier for Hacknet Node RAM<br>" +
"-Faction pages now scroll<br>" +
"-Slightly increased amount of money gained from hacking<br>" +
"-Added 'alias' command<br>" +
"-Added 'scan-analyze' terminal command - used to get basic hacking info about all immediate network connections<br>" +
"-Fixed bugs with upgradeHacknetNode() and purchaseHacknetNode() commands<br>" +
"-Added getNumHacknetNodes() and hasRootAccess(hostname/ip) commands to Netscript<br>" +
"-Increased Cost of university classes/gym<br>" +
"-You can now see what an Augmentation does and its price even while its locked<br><br>" +
"v0.16<br>" +
"-New Script Editor interface <br>" +
"-Rebalanced hacknet node - Increased base production but halved the multiplier from additional cores. This should boost its early-game production but nerf its late-game production<br>" +
"-Player now starts with 8GB of RAM on home computer<br>" +
"-'scan-analyze' terminal command displays RAM on servers<br>" +
"-Slightly buffed the amount of money the player steals when hacking servers (by about ~8%)<br>" +
"-Time to execute grow() now depends on hacking skill and server security, rather than taking a flat 2 minutes.<br>" +
"-Clicking outside of a pop-up dialog box will now close it<br>" +
"-BruteSSH.exe takes 33% less time to create<br>" +
"-'iron-gym' and 'max-hardware' servers now have 2GB of RAM<br>" +
"-Buffed job salaries across the board<br>" +
"-Updated Tutorial<br>" +
"-Created a Hacknet Node API for Netscript that allows you to access and upgrade your Hacknet Nodes. See the Netscript documentation for more details. WARNING The old upgradeHacknetNode() and getNumHacknetNodes() functions waere removed so any script that has these will no longer work <br><br>" +
"v0.17<br>" +
"-Greatly increased amount of money gained for crimes (by about 400% for most crimes)<br>" +
"-Criminal factions require slightly less negative karma to get invited to<br>" +
"-Increased the percentage of money stolen from servers when hacking<br>" +
"-Increased the starting amount of money available on beginning servers (servers with <50 required hacking))<br>" +
"-Increased the growth rate of servers (both naturally and manually when using the grow() command in a script)<br>" +
"-Added getHostname() command in Netscript that returns the hostname of the server a script is running on<br>" +
"-jQuery preventDefault() called when pressing ctrl+b in script editor<br>" +
"-The Neuroflux Governor augmentation (the one that can be repeatedly leveled up) now increases ALL multipliers by 1%. To balance it out, it's price multiplier when it levels up was increased<br>" +
"-Hacknet Node base production decreased from $1.75/s to $1.65/s<br>" +
"-Fixed issue with nested for loops in Netscript (stupid Javascript references)<br>" +
"-Added 'scp' command to Terminal and Netscript<br>" +
"-Slightly nerfed Hacknet Node Kernel DNI and Hacknet Node Core DNI Augmentations<br>" +
"-Increased TOR Router cost to $200k<br><br>" +
"v0.17.1 <br>" +
"-Fixed issue with purchasing Augmentations that are 'upgrades' and require previous Augmentations to be installed<br>" +
"-Increased the percentage of money stolen from servers when hacking<br><br>" +
"v0.18<br>" +
"-Major rebalancing (sorry didn't record specifics. But in general hacking gives more money " +
"and hacknet nodes give less)<br>" +
"-Server growth rate (both natural and manual using grow()) doubled<br>" +
"-Added option to Soft Reset<br>" +
"-Cancelling a full time job early now only results in halved gains for reputation. Exp and money earnings are gained in full<br>" +
"-Added exec() Netscript command, used to run scripts on other servers. <br>" +
"-NEW HACKING MECHANICS: Whenever a server is hacked, its 'security level' is increased by a very small amount. " +
"The security level is denoted by a number between 1-100. A higher security level makes it harder " +
"to hack a server and also decreases the amount of money you steal from it. Two Netscript functions, " +
"weaken() and getServerSecurityLevel() level, were added. The weaken(server) function lowers a server's " +
"security level. See the Netscript documentation for more details<br>" +
"-When donating to factions, the base rate is now $1,000,000 for 1 reputation point. Before, it was " +
"$1,000 for 1 reputation point.<br>" +
"-Monetary costs for all Augmentations increased. They are now about ~3.3 - 3.75 times more expensive than before<br><br>" +
"v0.20.0<br>" +
"-Refactored Netscript Interpreter code. Operations in Netscript should now run significantly faster (Every operation " +
"such as a variable assignment, a function call, a binary operator, getting a variable's value, etc. used to take up to several seconds, " +
"now each one should only take ~500 milliseconds). <br><br>" +
"-Percentage money stolen when hacking lowered to compensate for faster script speeds<br><br>" +
"-Hacking experience granted by grow() halved<br><br>" +
"-Weaken() is now ~11% faster, but only grants 3 base hacking exp upon completion instead of 5 <br><br>" +
"-Rebalancing of script RAM costs. Base RAM Cost for a script increased from 1GB to 1.5GB. Loops, hack(), grow() " +
"and weaken() all cost slightly less RAM than before <br><br>" +
"-Added getServerRequiredHackingLevel(server) Netscript command. <br><br>" +
"-Added fileExists(file, [server]) Netscript command, which is used to check if a script/program exists on a " +
"specified server<br><br>" +
"-Added isRunning(script, [server]) Netscript command, which is used to check if a script is running on the specified server<br><br>" +
"-Added killall Terminal command. Kills all running scripts on the current machine<br><br>" +
"-Added kill() and killall() Netscript commands. Used to kill scripts on specified machines. See Netscript documentation<br><br>" +
"-Re-designed 'Active Scripts' tab<br><br>" +
"-Hacknet Node base production rate lowered from 1.6 to 1.55 ($/second)<br><br>" +
"-Increased monetary cost of RAM (Upgrading home computer and purchasing servers will now be more expensive)<br><br>" +
"-NEW GROWTH MECHANICS - The rate of growth on a server now depends on a server's security level. A higher security level " +
"will result in lower growth on a server when using the grow() command. Furthermore, calling grow() on a server raises that " +
"server's security level by 0.004. For reference, if a server has a security level of 10 " +
"it will have approximately the same growth rate as before. <br><br>" +
"-Server growth no longer happens naturally<br><br>" +
"-Servers now have a maximum limit to their money. This limit is 50 times it's starting money<br><br>" +
"-Hacking now grants 10% less hacking experience<br><br>" +
"-You can now edit scripts that are running<br><br>" +
"-Augmentations cost ~11% more money and 25% more faction reputation<br><br>" +
"v0.19.7<br>" +
"-Added changelog to Options menu<br>" +
"-Bug fix with autocompletion (wasn't working properly for capitalized filenames/programs<br><br>" +
"v0.19.6<br>" +
"-Script editor now saves its state even when you change tabs <br>" +
"-scp() command in Terminal/script will now overwrite files at the destination <br>" +
"-Terminal commands are no longer case-sensitive (only the commands themselves such as 'run' or 'nano'. Filenames are " +
"still case sensitive<br>" +
"-Tab automcompletion will now work on commands<br><br>" +
"v0.19<br>" +
"-Hacknet Nodes have slightly higher base production, and slightly increased RAM multiplier. " +
"But they are also a bit more expensive at higher levels<br>" +
@ -560,15 +588,88 @@ CONSTANTS = {
"-Gyms and classes are now significantly more expensive<br>" +
"-Doubled the amount by which a server's security increases when it is hacked. Now, it will " +
"increase by 0.002. Calling weaken() on a server will lower the security by 0.1.<br><br>" +
"v0.19.6<br>" +
"-Script editor now saves its state even when you change tabs <br>" +
"-scp() command in Terminal/script will now overwrite files at the destination <br>" +
"-Terminal commands are no longer case-sensitive (only the commands themselves such as 'run' or 'nano'. Filenames are " +
"still case sensitive<br>" +
"-Tab automcompletion will now work on commands<br><br>" +
"v0.19.7<br>" +
"-Added changelog to Options menu<br>" +
"-Bug fix with autocompletion (wasn't working properly for capitalized filenames/programs",
"v0.18<br>" +
"-Major rebalancing (sorry didn't record specifics. But in general hacking gives more money " +
"and hacknet nodes give less)<br>" +
"-Server growth rate (both natural and manual using grow()) doubled<br>" +
"-Added option to Soft Reset<br>" +
"-Cancelling a full time job early now only results in halved gains for reputation. Exp and money earnings are gained in full<br>" +
"-Added exec() Netscript command, used to run scripts on other servers. <br>" +
"-NEW HACKING MECHANICS: Whenever a server is hacked, its 'security level' is increased by a very small amount. " +
"The security level is denoted by a number between 1-100. A higher security level makes it harder " +
"to hack a server and also decreases the amount of money you steal from it. Two Netscript functions, " +
"weaken() and getServerSecurityLevel() level, were added. The weaken(server) function lowers a server's " +
"security level. See the Netscript documentation for more details<br>" +
"-When donating to factions, the base rate is now $1,000,000 for 1 reputation point. Before, it was " +
"$1,000 for 1 reputation point.<br>" +
"-Monetary costs for all Augmentations increased. They are now about ~3.3 - 3.75 times more expensive than before<br><br>" +
"v0.17.1 <br>" +
"-Fixed issue with purchasing Augmentations that are 'upgrades' and require previous Augmentations to be installed<br>" +
"-Increased the percentage of money stolen from servers when hacking<br><br>" +
"v0.17<br>" +
"-Greatly increased amount of money gained for crimes (by about 400% for most crimes)<br>" +
"-Criminal factions require slightly less negative karma to get invited to<br>" +
"-Increased the percentage of money stolen from servers when hacking<br>" +
"-Increased the starting amount of money available on beginning servers (servers with <50 required hacking))<br>" +
"-Increased the growth rate of servers (both naturally and manually when using the grow() command in a script)<br>" +
"-Added getHostname() command in Netscript that returns the hostname of the server a script is running on<br>" +
"-jQuery preventDefault() called when pressing ctrl+b in script editor<br>" +
"-The Neuroflux Governor augmentation (the one that can be repeatedly leveled up) now increases ALL multipliers by 1%. To balance it out, it's price multiplier when it levels up was increased<br>" +
"-Hacknet Node base production decreased from $1.75/s to $1.65/s<br>" +
"-Fixed issue with nested for loops in Netscript (stupid Javascript references)<br>" +
"-Added 'scp' command to Terminal and Netscript<br>" +
"-Slightly nerfed Hacknet Node Kernel DNI and Hacknet Node Core DNI Augmentations<br>" +
"-Increased TOR Router cost to $200k<br><br>" +
"v0.16<br>" +
"-New Script Editor interface <br>" +
"-Rebalanced hacknet node - Increased base production but halved the multiplier from additional cores. This should boost its early-game production but nerf its late-game production<br>" +
"-Player now starts with 8GB of RAM on home computer<br>" +
"-'scan-analyze' terminal command displays RAM on servers<br>" +
"-Slightly buffed the amount of money the player steals when hacking servers (by about ~8%)<br>" +
"-Time to execute grow() now depends on hacking skill and server security, rather than taking a flat 2 minutes.<br>" +
"-Clicking outside of a pop-up dialog box will now close it<br>" +
"-BruteSSH.exe takes 33% less time to create<br>" +
"-'iron-gym' and 'max-hardware' servers now have 2GB of RAM<br>" +
"-Buffed job salaries across the board<br>" +
"-Updated Tutorial<br>" +
"-Created a Hacknet Node API for Netscript that allows you to access and upgrade your Hacknet Nodes. See the Netscript documentation for more details. WARNING The old upgradeHacknetNode() and getNumHacknetNodes() functions waere removed so any script that has these will no longer work <br><br>" +
"v0.15 <br>" +
"-Slightly reduced production multiplier for Hacknet Node RAM<br>" +
"-Faction pages now scroll<br>" +
"-Slightly increased amount of money gained from hacking<br>" +
"-Added 'alias' command<br>" +
"-Added 'scan-analyze' terminal command - used to get basic hacking info about all immediate network connections<br>" +
"-Fixed bugs with upgradeHacknetNode() and purchaseHacknetNode() commands<br>" +
"-Added getNumHacknetNodes() and hasRootAccess(hostname/ip) commands to Netscript<br>" +
"-Increased Cost of university classes/gym<br>" +
"-You can now see what an Augmentation does and its price even while its locked<br><br>",
LatestUpdate:
"v0.20.0<br>" +
"-Refactored Netscript Interpreter code. Operations in Netscript should now run significantly faster (Every operation " +
"such as a variable assignment, a function call, a binary operator, getting a variable's value, etc. used to take up to several seconds, " +
"now each one should only take ~500 milliseconds). <br><br>" +
"-Percentage money stolen when hacking lowered to compensate for faster script speeds<br><br>" +
"-Hacking experience granted by grow() halved<br><br>" +
"-Weaken() is now ~11% faster, but only grants 3 base hacking exp upon completion instead of 5 <br><br>" +
"-Rebalancing of script RAM costs. Base RAM Cost for a script increased from 1GB to 1.5GB. Loops, hack(), grow() " +
"and weaken() all cost slightly less RAM than before <br><br>" +
"-Added getServerRequiredHackingLevel(server) Netscript command. <br><br>" +
"-Added fileExists(file, [server]) Netscript command, which is used to check if a script/program exists on a " +
"specified server<br><br>" +
"-Added isRunning(script, [server]) Netscript command, which is used to check if a script is running on the specified server<br><br>" +
"-Added killall Terminal command. Kills all running scripts on the current machine<br><br>" +
"-Added kill() and killall() Netscript commands. Used to kill scripts on specified machines. See Netscript documentation<br><br>" +
"-Re-designed 'Active Scripts' tab<br><br>" +
"-Hacknet Node base production rate lowered from 1.6 to 1.55 ($/second)<br><br>" +
"-Increased monetary cost of RAM (Upgrading home computer and purchasing servers will now be more expensive)<br><br>" +
"-NEW GROWTH MECHANICS - The rate of growth on a server now depends on a server's security level. A higher security level " +
"will result in lower growth on a server when using the grow() command. Furthermore, calling grow() on a server raises that " +
"server's security level by 0.004. For reference, if a server has a security level of 10 " +
"it will have approximately the same growth rate as before. <br><br>" +
"-Server growth no longer happens naturally<br><br>" +
"-Servers now have a maximum limit to their money. This limit is 50 times it's starting money<br><br>" +
"-Hacking now grants 10% less hacking experience<br><br>" +
"-You can now edit scripts that are running<br><br>" +
"-Augmentations cost ~11% more money and 25% more faction reputation<br><br>",
}

@ -814,7 +814,7 @@ displayFactionAugmentations = function(factionName) {
pElem.innerHTML = "UNLOCKED - $" + formatNumber(aug.baseCost * faction.augmentationPriceMult, 2);
} else {
aElem.setAttribute("class", "a-link-button-inactive");
pElem.innerHTML = "LOCKED (Requires " + formatNumber(req, 4) + " faction reputation) - $" + formatNumber(aug.baseCost * faction.augmentationPriceMult, 2);
pElem.innerHTML = "LOCKED (Requires " + formatNumber(req, 1) + " faction reputation) - $" + formatNumber(aug.baseCost * faction.augmentationPriceMult, 2);
pElem.style.color = "red";
}
aElem.style.display = "inline";

@ -43,7 +43,6 @@ function addMessageToServer(msg, serverHostname) {
//Checks if any of the 'timed' messages should be sent
function checkForMessagesToSend() {
console.log("checkForMessagesToSend() called");
var jumper0 = Messages[MessageFilenames.Jumper0];
var jumper1 = Messages[MessageFilenames.Jumper1];
var jumper2 = Messages[MessageFilenames.Jumper2];

File diff suppressed because it is too large Load Diff

338
src/NetscriptFunctions.js Normal file

@ -0,0 +1,338 @@
/* Netscript Functions
* Implementation for Netscript features */
function netscriptAssign(exp, workerScript) {
var env = workerScript.env;
return new Promise(function(resolve, reject) {
if (env.stopFlag) {return reject(workerScript);}
if (exp.left.type != "var") {
return reject(makeRuntimeRejectMsg(workerScript, "Cannot assign to " + JSON.stringify(exp.left)));
}
var expRightPromise = evaluate(exp.right, workerScript);
expRightPromise.then(function(expRight) {
try {
env.set(exp.left.value, expRight);
} catch (e) {
return reject(makeRuntimeRejectMsg(workerScript, "Failed to set environment variable: " + e.toString()));
}
resolve(false); //Return false so this doesnt cause conditionals to evaluate
}, function(e) {
reject(e);
});
});
}
function netscriptBinary(exp, workerScript) {
var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);}
var opPromises = [evaluate(exp.left, workerScript), evaluate(exp.right, workerScript)];
return Promise.all(opPromises).then(function (ops) {
try {
var result = apply_op(exp.operator, ops[0], ops[1]);
return Promise.resolve(result);
} catch(e) {
return Promise.reject(e);
}
}).catch(function(e) {
return Promise.reject(e);
});
}
function netscriptHack(exp, workerScript) {
var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);}
if (exp.args.length != 1) {
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Hack() call has incorrect number of arguments. Takes 1 argument"));
}
var ipPromise = evaluate(exp.args[0], workerScript);
return ipPromise.then(function(ip) {
var server = getServer(ip);
if (server == null) {
workerScript.scriptRef.log("hack() error. Invalid IP or hostname passed in: " + ip + ". Stopping...");
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Invalid IP or hostname passed into hack() command"));
}
//Calculate the hacking time
var hackingTime = scriptCalculateHackingTime(server); //This is in seconds
//No root access or skill level too low
if (server.hasAdminRights == false) {
workerScript.scriptRef.log("Cannot hack this server (" + server.hostname + ") because user does not have root access");
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Script crashed because it did not have root access to " + server.hostname));
}
if (server.requiredHackingSkill > Player.hacking_skill) {
workerScript.scriptRef.log("Cannot hack this server (" + server.hostname + ") because user's hacking skill is not high enough");
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Script crashed because player's hacking skill is not high enough to hack " + server.hostname));
}
workerScript.scriptRef.log("Attempting to hack " + ip + " in " + hackingTime.toFixed(3) + " seconds");
return Promise.resolve([server, hackingTime]);
}).then(function([server, hackingTime]) {
console.log("Hacking " + server.hostname + " after " + hackingTime.toString() + " seconds.");
return netscriptDelay(hackingTime* 1000).then(function() {
if (env.stopFlag) {return Promise.reject(workerScript);}
var hackChance = scriptCalculateHackingChance(server);
var rand = Math.random();
var expGainedOnSuccess = scriptCalculateExpGain(server);
var expGainedOnFailure = (expGainedOnSuccess / 4);
if (rand < hackChance) { //Success!
var moneyGained = scriptCalculatePercentMoneyHacked(server);
moneyGained = Math.floor(server.moneyAvailable * moneyGained);
//Safety check
if (moneyGained <= 0) {moneyGained = 0;}
server.moneyAvailable -= moneyGained;
Player.gainMoney(moneyGained);
workerScript.scriptRef.onlineMoneyMade += moneyGained;
workerScript.scriptRef.recordHack(server.ip, moneyGained);
Player.gainHackingExp(expGainedOnSuccess);
workerScript.scriptRef.onlineExpGained += expGainedOnSuccess;
console.log("Script successfully hacked " + server.hostname + " for $" + formatNumber(moneyGained, 2) + " and " + formatNumber(expGainedOnSuccess, 4) + " exp");
workerScript.scriptRef.log("Script SUCCESSFULLY hacked " + server.hostname + " for $" + formatNumber(moneyGained, 2) + " and " + formatNumber(expGainedOnSuccess, 4) + " exp");
server.fortify(CONSTANTS.ServerFortifyAmount);
return Promise.resolve(true);
} else {
//Player only gains 25% exp for failure? TODO Can change this later to balance
Player.gainHackingExp(expGainedOnFailure);
workerScript.scriptRef.onlineExpGained += expGainedOnFailure;
console.log("Script unsuccessful to hack " + server.hostname + ". Gained " + formatNumber(expGainedOnFailure, 4) + " exp");
workerScript.scriptRef.log("Script FAILED to hack " + server.hostname + ". Gained " + formatNumber(expGainedOnFailure, 4) + " exp");
return Promise.resolve(false);
}
});
}).then(function(res) {
return Promise.resolve(res);
}).catch(function(e) {
return Promise.reject(e);
});
}
function netscriptGrow(exp, workerScript) {
var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);}
if (exp.args.length != 1) {
return Promise.reject(makeRuntimeRejectMsg(workerScript, "grow() call has incorrect number of arguments. Takes 1 argument"));
}
var ipPromise = evaluate(exp.args[0], workerScript);
return ipPromise.then(function(ip) {
if (env.stopFlag) {return Promise.reject(workerScript);}
var server = getServer(ip);
if (server == null) {
workerScript.scriptRef.log("Cannot grow(). Invalid IP or hostname passed in: " + ip);
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Invalid IP or hostname passed into grow() command"));
}
//No root access or skill level too low
if (server.hasAdminRights == false) {
workerScript.scriptRef.log("Cannot grow this server (" + server.hostname + ") because user does not have root access");
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Script crashed because it did not have root access to " + server.hostname));
}
var growTime = scriptCalculateGrowTime(server);
console.log("Executing grow() on server " + server.hostname + " in " + formatNumber(growTime/1000, 3) + " seconds")
workerScript.scriptRef.log("Executing grow() on server " + server.hostname + " in " + formatNumber(growTime/1000, 3) + " seconds");
return Promise.resolve([server, growTime]);
}).then(function([server, growTime]) {
if (env.stopFlag) {return Promise.reject(workerScript);}
return netscriptDelay(growTime).then(function() {
if (env.stopFlag) {return Promise.reject(workerScript);}
server.moneyAvailable += 1; //It can be grown even if it has no money
var growthPercentage = processSingleServerGrowth(server, 450);
workerScript.scriptRef.recordGrow(server.ip);
var expGain = 0.5 * Player.hacking_exp_mult;
workerScript.scriptRef.log("Available money on " + server.hostname + " grown by "
+ formatNumber(growthPercentage*100 - 100, 6) + "%. Gained " +
formatNumber(expGain, 4) + " hacking exp");
workerScript.scriptRef.onlineExpGained += expGain;
Player.gainHackingExp(expGain);
return Promise.resolve(growthPercentage);
});
}).then(function(res) {
return Promise.resolve(res);
}).catch(function(e) {
return Promise.reject(e);
})
}
function netscriptWeaken(exp, workerScript) {
var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);}
if (exp.args.length != 1) {
return Promise.reject(makeRuntimeRejectMsg(workerScript, "weaken() call has incorrect number of arguments. Takes 1 argument"));
}
var ipPromise = evaluate(exp.args[0], workerScript);
return ipPromise.then(function(ip) {
if (env.stopFlag) {return Promise.reject(workerScript);}
var server = getServer(ip);
if (server == null) {
workerScript.scriptRef.log("Cannot weaken(). Invalid IP or hostname passed in: " + ip);
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Invalid IP or hostname passed into weaken() command"));
}
//No root access or skill level too low
if (server.hasAdminRights == false) {
workerScript.scriptRef.log("Cannot weaken this server (" + server.hostname + ") because user does not have root access");
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Script crashed because it did not have root access to " + server.hostname));
}
var weakenTime = scriptCalculateWeakenTime(server);
console.log("Executing weaken() on server " + server.hostname + " in " + formatNumber(weakenTime/1000, 3) + " seconds")
workerScript.scriptRef.log("Executing weaken() on server " + server.hostname + " in " + formatNumber(weakenTime/1000, 3) + " seconds");
return Promise.resolve([server, weakenTime]);
}).then(function([server, weakenTime]) {
if (env.stopFlag) {return Promise.reject(workerScript);}
return netscriptDelay(weakenTime).then(function() {
if (env.stopFlag) {return Promise.reject(workerScript);}
server.weaken(CONSTANTS.ServerWeakenAmount);
workerScript.scriptRef.recordWeaken(server.ip);
var expGain = 3 * Player.hacking_exp_mult;
workerScript.scriptRef.log("Server security level on " + server.hostname + " weakened to " + server.hackDifficulty +
". Gained " + formatNumber(expGain, 4) + " hacking exp");
workerScript.scriptRef.onlineExpGained += expGain;
Player.gainHackingExp(expGain);
return Promise.resolve(CONSTANTS.ServerWeakenAmount);
});
}).then(function(res) {
return Promise.resolve(res);
}).catch(function(e) {
return Promise.reject(e);
});
}
function netscriptRunProgram(exp, workerScript, programName) {
var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);}
if (exp.args.length != 1) {
return Promise.reject(makeRuntimeRejectMsg(workerScript, "nuke() call has incorrect number of arguments. Takes 1 argument"));
}
var ipPromise = evaluate(exp.args[0], workerScript);
return ipPromise.then(function(ip) {
if (env.stopFlag) {return Promise.reject(workerScript);}
var server = getServer(ip);
if (server == null) {
workerScript.scriptRef.log("Cannot call " + programName + ". Invalid IP or hostname passed in: " + ip);
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Invalid IP or hostname passed into " + programName + " command"));
}
if (!Player.hasProgram(programName)) {
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Player does not have " + programName + " on home computer"));
}
switch(programName) {
case Programs.NukeProgram:
return netscriptRunNukeProgram(exp, workerScript, server);
break;
case Programs.BruteSSHProgram:
return netscriptRunBrutesshProgram(exp, workerScript, server);
break;
case Programs.FTPCrackProgram:
return netscriptRunFtpcrackProgram(exp, workerScript, server);
break;
case Programs.RelaySMTPProgram:
return netscriptRunRelaysmtpProgram(exp, workerScript, server);
break;
case Programs.HTTPWormProgram:
return netscriptRunHttpwormProgram(exp, workerScript, server);
break;
case Programs.SQLInjectProgram:
return netscriptRunSqlinjectProgram(exp, workerScript, server);
break;
default:
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Invalid program. This is a bug please contact game dev"));
break;
}
}).then(function(res) {
return Promise.resolve(res);
}).catch(function(e) {
return Promise.reject(e);
});
}
function netscriptRunNukeProgram(exp, workerScript, server) {
var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);}
if (server.openPortCount < server.numOpenPortsRequired) {
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Not enough ports opened to use NUKE.exe virus"));
}
if (server.hasAdminRights) {
workerScript.scriptRef.log("Already have root access to " + server.hostname);
} else {
server.hasAdminRights = true;
workerScript.scriptRef.log("Executed NUKE.exe virus on " + server.hostname + " to gain root access");
}
return Promise.resolve(true);
}
function netscriptRunBrutesshProgram(exp, workerScript, server) {
var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);}
if (!server.sshPortOpen) {
workerScript.scriptRef.log("Executed BruteSSH.exe virus on " + server.hostname + " to open SSH port (22)");
server.sshPortOpen = true;
++server.openPortCount;
} else {
workerScript.scriptRef.log("SSH Port (22) already opened on " + server.hostname);
}
return Promise.resolve(true);
}
function netscriptRunFtpcrackProgram(exp, workerScript, server) {
var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);}
if (!server.ftpPortOpen) {
workerScript.scriptRef.log("Executed FTPCrack.exe virus on " + server.hostname + " to open FTP port (21)");
server.ftpPortOpen = true;
++server.openPortCount;
} else {
workerScript.scriptRef.log("FTP Port (21) already opened on " + server.hostname);
}
return Promise.resolve(true);
}
function netscriptRunRelaysmtpProgram(exp, workerScript, server) {
var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);}
if (!server.smtpPortOpen) {
workerScript.scriptRef.log("Executed relaySMTP.exe virus on " + server.hostname + " to open SMTP port (25)");
server.smtpPortOpen = true;
++server.openPortCount;
} else {
workerScript.scriptRef.log("SMTP Port (25) already opened on " + server.hostname);
}
return Promise.resolve(true);
}
function netscriptRunHttpwormProgram(exp, workerScript, server) {
var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);}
if (!server.httpPortOpen) {
workerScript.scriptRef.log("Executed HTTPWorm.exe virus on " + server.hostname + " to open HTTP port (25)");
server.httpPortOpen = true;
++server.openPortCount;
} else {
workerScript.scriptRef.log("HTTP Port (80) already opened on " + server.hostname);
}
return Promise.resolve(true);
}
function netscriptRunSqlinjectProgram(exp, workerScript, server) {
var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);}
if (!server.sqlPortOpen) {
workerScript.scriptRef.log("Executed SQLInject.exe virus on " + server.hostname + " to open SQL port (1433)");
server.sqlPortOpen = true;
++server.openPortCount;
} else {
workerScript.scriptRef.log("SQL Port (1433) already opened on " + server.hostname);
}
return Promise.resolve(true);
}

@ -111,6 +111,8 @@ function runScriptsLoop() {
return;
}
}
} else {
dialogBoxCreate("An unknown script died for an unknown reason. This is a bug please contact game dev");
}
});
}
@ -133,12 +135,12 @@ function runScriptsLoop() {
//Free RAM
AllServers[ip].ramUsed -= workerScripts[i].ramUsage;
//Delete script from Active Scripts
deleteActiveScriptsItem(workerScripts[i]);
//Delete script from workerScripts
workerScripts.splice(i, 1);
//Delete script from Active Scripts
Engine.deleteActiveScriptsItem(i);
}
}
@ -152,8 +154,10 @@ function killWorkerScript(scriptName, serverIp) {
for (var i = 0; i < workerScripts.length; i++) {
if (workerScripts[i].name == scriptName && workerScripts[i].serverIp == serverIp) {
workerScripts[i].env.stopFlag = true;
return true;
}
}
return false;
}
//Queues a script to be run
@ -171,7 +175,7 @@ function addWorkerScript(script, server) {
s.ramUsage = script.ramUsage;
//Add the WorkerScript to the Active Scripts list
Engine.addActiveScriptsItem(s);
addActiveScriptsItem(s);
//Add the WorkerScript
workerScripts.push(s);

@ -243,7 +243,7 @@ PlayerObject.prototype.calculateHackingTime = function() {
PlayerObject.prototype.calculatePercentMoneyHacked = function() {
var difficultyMult = (100 - this.getCurrentServer().hackDifficulty) / 100;
var skillMult = (this.hacking_skill - (this.getCurrentServer().requiredHackingSkill - 1)) / this.hacking_skill;
var percentMoneyHacked = difficultyMult * skillMult * this.hacking_money_mult / 150;
var percentMoneyHacked = difficultyMult * skillMult * this.hacking_money_mult / 200;
console.log("Percent money hacked calculated to be: " + percentMoneyHacked);
if (percentMoneyHacked < 0) {return 0;}
if (percentMoneyHacked > 1) {return 1;}
@ -254,7 +254,7 @@ PlayerObject.prototype.calculatePercentMoneyHacked = function() {
//The formula is:
// difficulty * requiredLevel * hacking_multiplier
PlayerObject.prototype.calculateExpGain = function() {
return (this.getCurrentServer().hackDifficulty * this.hacking_exp_mult);
return (this.getCurrentServer().hackDifficulty * this.hacking_exp_mult * 0.9);
}
//Hack/Analyze a server. Return the amount of time the hack will take. This lets the Terminal object know how long to disable itself for
@ -274,7 +274,7 @@ PlayerObject.prototype.analyze = function() {
PlayerObject.prototype.hasProgram = function(programName) {
var home = Player.getHomeComputer();
for (var i = 0; i < home.programs.length; ++i) {
if (programName == home.programs[i]) {return true;}
if (programName.toLowerCase() == home.programs[i].toLowerCase()) {return true;}
}
return false;
}

@ -109,8 +109,10 @@ function prestigeAugmentation() {
//Delete all running scripts objects
for (var i = 0; i < workerScripts.length; ++i) {
deleteActiveScriptsItem(workerScripts[i]);
workerScripts[i].env.stopFlag = true;
}
workerScripts.length = 0;
var homeComp = Player.getHomeComputer();
//Delete all servers except home computer
@ -161,13 +163,6 @@ function prestigeAugmentation() {
//Delete messages on home computer
homeComp.messages.length = 0;
//Delete active scripts display elements
var list = Engine.ActiveScriptsList.querySelectorAll('#active-scripts-list li');
for (var i = list.length-1; i >= 0; --i) {
Engine.deleteActiveScriptsItem(i);
}
workerScripts.length = 0;
//Delete Hacknet Nodes
Player.hacknetNodes.length = 0;
Player.totalHacknetNodeProduction = 0;

@ -12,6 +12,7 @@ function BitburnerSaveObject() {
this.AugmentationsSave = "";
this.AliasesSave = "";
this.MessagesSave = "";
this.VersionSave = "";
}
BitburnerSaveObject.prototype.saveGame = function() {
@ -23,6 +24,7 @@ BitburnerSaveObject.prototype.saveGame = function() {
this.AugmentationsSave = JSON.stringify(Augmentations);
this.AliasesSave = JSON.stringify(Aliases);
this.MessagesSave = JSON.stringify(Messages);
this.VersionSave = JSON.stringify(CONSTANTS.Version);
var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this))));
window.localStorage.setItem("bitburnerSave", saveString);
@ -63,6 +65,18 @@ loadGame = function(saveObj) {
} else {
initMessages();
}
if (saveObj.hasOwnProperty("VersionSave")) {
try {
var ver = JSON.parse(saveObj.VersionSave, Reviver);
if (ver != CONSTANTS.Version) {
createNewUpdateText();
}
} catch(e) {
createNewUpdateText();
}
} else {
createNewUpdateText();
}
return true;
}
@ -74,6 +88,13 @@ BitburnerSaveObject.prototype.deleteGame = function() {
Engine.createStatusText("Game deleted!");
}
createNewUpdateText = function() {
dialogBoxCreate("New update!<br>" +
"Please report any bugs/issues through the github repository " +
"or the Bitburner subreddit (reddit.com/r/bitburner).<br><br>" +
CONSTANTS.LatestUpdate);
}
BitburnerSaveObject.prototype.toJSON = function() {
return Generic_toJSON("BitburnerSaveObject", this);

@ -150,6 +150,8 @@ Script.prototype.saveScript = function() {
}
Script.prototype.reset = function() {
this.updateRamUsage();
this.offlineRunningTime = 0.01; //Seconds
this.offlineMoneyMade = 0;
this.offlineExpGained = 0;
@ -202,7 +204,7 @@ Script.prototype.reset = function() {
//Updates how much RAM the script uses when it is running.
Script.prototype.updateRamUsage = function() {
var baseRam = 1; //Each script requires 1GB to run regardless
var baseRam = 1.4;
var codeCopy = this.code.repeat(1);
codeCopy = codeCopy.replace(/\s/g,''); //Remove all whitespace
@ -226,6 +228,9 @@ Script.prototype.updateRamUsage = function() {
var getHackingLevelCount = numOccurrences(codeCopy, "getHackingLevel(");
var getServerMoneyAvailableCount = numOccurrences(codeCopy, "getServerMoneyAvailable(");
var getServerSecurityCount = numOccurrences(codeCopy, "getServerSecurityLevel(");
var getServerReqdHackingCount = numOccurrences(codeCopy, "getServerRequiredHackingLevel(");
var fileExistsCount = numOccurrences(codeCopy, "fileExists(");
var isRunningCount = numOccurrences(codeCopy, "isRunning(");
var numOperators = numNetscriptOperators(codeCopy);
var purchaseHacknetCount = numOccurrences(codeCopy, "purchaseHacknetNode(");
var hacknetnodesArrayCount = numOccurrences(codeCopy, "hacknetnodes[");
@ -254,6 +259,9 @@ Script.prototype.updateRamUsage = function() {
(getHackingLevelCount * CONSTANTS.ScriptGetHackingLevelRamCost) +
(getServerMoneyAvailableCount * CONSTANTS.ScriptGetServerMoneyRamCost) +
(getServerSecurityCount * CONSTANTS.ScriptGetServerSecurityRamCost) +
(getServerReqdHackingCount * CONSTANTS.ScriptGetServerReqdHackRamCost) +
(fileExistsCount * CONSTANTS.ScriptFileExistsRamCost) +
(isRunningCount * CONSTANTS.ScriptIsRunningRamCost) +
(numOperators * CONSTANTS.ScriptOperatorRamCost) +
(purchaseHacknetCount * CONSTANTS.ScriptPurchaseHacknetRamCost) +
(hacknetnodesArrayCount * CONSTANTS.ScriptHacknetNodesRamCost) +

@ -31,10 +31,9 @@ function Server() {
//by a separate formula
this.requiredHackingSkill = 1;
//Total money available on this server. How much of this you hack will be determined
//by a formula related to hacking skill. The money available on a server will steadily increase
//over time, and it will decrease when you hack it
//Total money available on this server
this.moneyAvailable = 0;
this.moneyMax = 0;
//Parameters used in formulas that dictate how moneyAvailable and requiredHackingSkill change.
this.hackDifficulty = 1; //Affects hack success rate and how the requiredHackingSkill increases over time (1-100)
@ -79,6 +78,7 @@ Server.prototype.init = function(ip, hostname, organizationName, onlineStatus, i
Server.prototype.setHackingParameters = function(requiredHackingSkill, moneyAvailable, hackDifficulty, serverGrowth) {
this.requiredHackingSkill = requiredHackingSkill;
this.moneyAvailable = moneyAvailable;
this.moneyMax = 50 * moneyAvailable;
this.hackDifficulty = hackDifficulty;
this.serverGrowth = serverGrowth;
}
@ -675,52 +675,34 @@ initForeignServers = function() {
}
}
//Server growth
processServerGrowth = function(numCycles) {
//Server growth processed once every 450 game cycles
var numServerGrowthCycles = Math.max(Math.floor(numCycles / 450), 0);
for (var ip in AllServers) {
if (AllServers.hasOwnProperty(ip)) {
var server = AllServers[ip];
//Get the number of server growth cycles that will be applied based on the
//server's serverGrowth property
var serverGrowthPercentage = server.serverGrowth / 100;
var numServerGrowthCyclesAdjusted = numServerGrowthCycles * serverGrowthPercentage;
//Apply serverGrowth for the calculated number of growth cycles
var serverGrowth = Math.pow(CONSTANTS.ServerGrowthRate, numServerGrowthCyclesAdjusted * Player.hacking_grow_mult) ;
if (serverGrowth < 1) {
console.log("WARN: serverGrowth calculated to be less than 1");
serverGrowth = 1;
}
//console.log("serverGrowth ratio: " + serverGrowth);
server.moneyAvailable *= serverGrowth;
}
}
console.log("Server growth processed for " + numServerGrowthCycles + " cycles");
}
//Applied server growth for a single server. Returns the percentage growth
processSingleServerGrowth = function(server, numCycles) {
//Server growth processed once every 450 game cycles
var numServerGrowthCycles = Math.max(Math.floor(numCycles / 450), 0);
//Get the number of server growth cycles that will be applied based on the
//server's serverGrowth property
//Get adjusted growth rate, which accounts for server security
var growthRate = CONSTANTS.ServerBaseGrowthRate;
var adjGrowthRate = 1 + (growthRate - 1) / server.hackDifficulty;
if (adjGrowthRate > CONSTANTS.ServerMaxGrowthRate) {adjGrowthRate = CONSTANTS.ServerMaxGrowthRate;}
console.log("Adjusted growth rate: " + adjGrowthRate);
//Calculate adjusted server growth rate based on parameters
var serverGrowthPercentage = server.serverGrowth / 100;
var numServerGrowthCyclesAdjusted = numServerGrowthCycles * serverGrowthPercentage;
//Apply serverGrowth for the calculated number of growth cycles
var serverGrowth = Math.pow(CONSTANTS.ServerGrowthRate, numServerGrowthCyclesAdjusted * Player.hacking_grow_mult) ;
var serverGrowth = Math.pow(adjGrowthRate, numServerGrowthCyclesAdjusted * Player.hacking_grow_mult) ;
if (serverGrowth < 1) {
console.log("WARN: serverGrowth calculated to be less than 1");
serverGrowth = 1;
}
server.moneyAvailable *= serverGrowth;
if (server.moneyMax && server.moneyAvailable >= server.moneyMax) {
server.moneyAvailable = server.moneyMax;
return 1;
}
server.fortify(2 * CONSTANTS.ServerFortifyAmount);
return serverGrowth;
}

@ -11,6 +11,7 @@ purchaseServer = function(ram, cost) {
var newServ = new Server();
var hostname = document.getElementById("purchase-server-box-input").value;
hostname = hostname.replace(/\s\s+/g, '');
if (hostname == "") {
dialogBoxCreate("You must enter a hostname for your new server!");
return;

@ -236,7 +236,7 @@ function determineAllPossibilitiesForTabCompletion(input, index=0) {
//Autocomplete the command
if (index == -1) {
return ["alias", "analyze", "cat", "clear", "cls", "connect", "free",
"hack", "help", "home", "hostname", "ifconfig", "kill",
"hack", "help", "home", "hostname", "ifconfig", "kill", "killall",
"ls", "mem", "nano", "ps", "rm", "run", "scan", "scan-analyze",
"scp", "sudov", "tail", "top"];
}
@ -412,9 +412,12 @@ var Terminal = {
//Replace all extra whitespace in command with a single space
command = command.replace(/\s\s+/g, ' ');
Terminal.commandHistory.push(command);
if (Terminal.commandHistory.length > 50) {
Terminal.commandHistory.splice(0, 1);
//Terminal history
if (Terminal.commandHistory[Terminal.commandHistory.length-1] != command) {
Terminal.commandHistory.push(command);
if (Terminal.commandHistory.length > 50) {
Terminal.commandHistory.splice(0, 1);
}
}
Terminal.commandHistoryIndex = Terminal.commandHistory.length;
@ -715,6 +718,13 @@ var Terminal = {
}
post("No such script is running. Nothing to kill");
break;
case "killall":
var s = Player.getCurrentServer();
for (var i = s.runningScripts.length; i >= 0; --i) {
killWorkerScript(s.runningScripts[i], s.ip);
}
post("Killing all running scripts. May take up to a few minutes for the scripts to die...");
break;
case "ls":
Terminal.executeListCommand(commandArray);
break;
@ -747,13 +757,6 @@ var Terminal = {
//Script name is the filename without the .script at the end
var scriptname = filename.substr(0, filename.indexOf(".script"));
//Cannot edit scripts that are currently running
for (var i = 0; i < Player.getCurrentServer().runningScripts.length; i++) {
if (filename == Player.getCurrentServer().runningScripts[i]) {
post("Cannot open/edit scripts that are currently running!"); return;
}
}
//Check if the script already exists
for (var i = 0; i < Player.getCurrentServer().scripts.length; i++) {
if (filename == Player.getCurrentServer().scripts[i].filename) {

@ -1,4 +1,5 @@
var Engine = {
version: "",
Debug: true,
//Clickable objects
@ -116,6 +117,7 @@ var Engine = {
loadActiveScriptsContent: function() {
Engine.hideAllContent();
Engine.Display.activeScriptsContent.style.visibility = "visible";
setActiveScriptsClickHandlers();
Engine.currentPage = Engine.Page.ActiveScripts;
},
@ -334,100 +336,6 @@ var Engine = {
}
},
/* Functions used to update information on the Active Scripts page */
ActiveScriptsList: null,
//Creates and adds the <li> object for a given workerScript
addActiveScriptsItem: function(workerscript) {
var item = document.createElement("li");
Engine.createActiveScriptsText(workerscript, item);
//Add the li element onto the list
if (Engine.ActiveScriptsList == null) {
Engine.ActiveScriptsList = document.getElementById("active-scripts-list");
}
Engine.ActiveScriptsList.appendChild(item);
},
deleteActiveScriptsItem: function(i) {
var list = Engine.ActiveScriptsList.querySelectorAll('#active-scripts-list li');
if (i >= list.length) {
throw new Error("Trying to delete an out-of-range Active Scripts item");
}
var li = list[i];
li.parentNode.removeChild(li);
},
//Update the ActiveScriptsItems array
updateActiveScriptsItems: function() {
var total = 0;
for (var i = 0; i < workerScripts.length; ++i) {
total += Engine.updateActiveScriptsItemContent(i, workerScripts[i]);
}
document.getElementById("active-scripts-total-prod").innerHTML =
"Total online production rate: $" + formatNumber(total, 2) + " / second";
},
//Updates the content of the given item in the Active Scripts list
updateActiveScriptsItemContent: function(i, workerscript) {
var list = Engine.ActiveScriptsList.getElementsByTagName("li");
if (i >= list.length) {
throw new Error("Trying to update an out-of-range Active Scripts Item");
}
var item = list[i];
//Clear the item
while (item.firstChild) {
item.removeChild(item.firstChild);
}
//Add the updated text back. Returns the total online production rate
return Engine.createActiveScriptsText(workerscript, item);
},
createActiveScriptsText: function(workerscript, item) {
//Script name
var scriptName = document.createElement("h2");
scriptName.appendChild(document.createTextNode(workerscript.name));
item.appendChild(scriptName);
var itemText = document.createElement("p");
//Server ip/hostname
var hostname = workerscript.getServer().hostname;
var serverIpHostname = "Server: " + hostname + "(" + workerscript.serverIp + ")";
//Online
var onlineTotalMoneyMade = "Total online production: $" + formatNumber(workerscript.scriptRef.onlineMoneyMade, 2);
var onlineTotalExpEarned = (Array(26).join(" ") + formatNumber(workerscript.scriptRef.onlineExpGained, 2) + " hacking exp").replace( / /g, "&nbsp;");
var onlineMps = workerscript.scriptRef.onlineMoneyMade / workerscript.scriptRef.onlineRunningTime;
var onlineMpsText = "Online production rate: $" + formatNumber(onlineMps, 2) + "/second";
var onlineEps = workerscript.scriptRef.onlineExpGained / workerscript.scriptRef.onlineRunningTime;
var onlineEpsText = (Array(25).join(" ") + formatNumber(onlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;");
//Offline
var offlineTotalMoneyMade = "Total offline production: $" + formatNumber(workerscript.scriptRef.offlineMoneyMade, 2);
var offlineTotalExpEarned = (Array(27).join(" ") + formatNumber(workerscript.scriptRef.offlineExpGained, 2) + " hacking exp").replace( / /g, "&nbsp;");
var offlineMps = workerscript.scriptRef.offlineMoneyMade / workerscript.scriptRef.offlineRunningTime;
var offlineMpsText = "Offline production rate: $" + formatNumber(offlineMps, 2) + "/second";
var offlineEps = workerscript.scriptRef.offlineExpGained / workerscript.scriptRef.offlineRunningTime;
var offlineEpsText = (Array(26).join(" ") + formatNumber(offlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;");
itemText.innerHTML = serverIpHostname + "<br>" + onlineTotalMoneyMade + "<br>" + onlineTotalExpEarned + "<br>" +
onlineMpsText + "<br>" + onlineEpsText + "<br>" + offlineTotalMoneyMade + "<br>" + offlineTotalExpEarned + "<br>" +
offlineMpsText + "<br>" + offlineEpsText + "<br>";
item.appendChild(itemText);
//Return total online production rate
return onlineMps;
},
displayFactionsInfo: function() {
var factionsList = document.getElementById("factions-list");
@ -599,8 +507,7 @@ var Engine = {
updateSkillLevelsCounter: 10, //Only update skill levels every 2 seconds. Might improve performance
updateDisplays: 3, //Update displays such as Active Scripts display and character display
createProgramNotifications: 10, //Checks whether any programs can be created and notifies
serverGrowth: 450, //Process server growth every minute and a half
checkFactionInvitations: 250, //Check whether you qualify for any faction invitations every 5 minutes
checkFactionInvitations: 250, //Check whether you qualify for any faction invitations every 5 minutes
passiveFactionGrowth: 600,
messages: 300,
},
@ -629,7 +536,7 @@ var Engine = {
if (Engine.Counters.updateDisplays <= 0) {
Engine.displayCharacterOverviewInfo();
if (Engine.currentPage == Engine.Page.ActiveScripts) {
Engine.updateActiveScriptsItems();
updateActiveScriptsItems();
} else if (Engine.currentPage == Engine.Page.CharacterInfo) {
Engine.displayCharacterInfo();
} else if (Engine.currentPage == Engine.Page.HacknetNodes) {
@ -654,12 +561,6 @@ var Engine = {
Engine.Counters.createProgramNotifications = 10;
}
if (Engine.Counters.serverGrowth <= 0) {
var numCycles = Math.floor((450 - Engine.Counters.serverGrowth));
processServerGrowth(numCycles);
Engine.Counters.serverGrowth = 450;
}
if (Engine.Counters.checkFactionInvitations <= 0) {
var invitedFactions = Player.checkForFactionInvitations();
if (invitedFactions.length > 0) {
@ -747,7 +648,6 @@ var Engine = {
var numCyclesOffline = Math.floor((Engine._lastUpdate - lastUpdate) / Engine._idleSpeed);
/* Process offline progress */
processServerGrowth(numCyclesOffline); //Should be done before offline production for scripts
var offlineProductionFromScripts = loadAllRunningScripts(); //This also takes care of offline production for those scripts
if (Player.isWorking) {
console.log("work() called in load() for " + numCyclesOffline * Engine._idleSpeed + " milliseconds");
@ -799,7 +699,7 @@ var Engine = {
initAugmentations();
//Start interactive tutorial
iTutorialStart();
iTutorialStart();
}
},
@ -1042,7 +942,7 @@ var Engine = {
return false;
});
relaySmtpALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.RelaySMTPProgram. CONSTANTS.MillisecondsPer2Hours, 250);
Player.startCreateProgramWork(Programs.RelaySMTPProgram, CONSTANTS.MillisecondsPer2Hours, 250);
return false;
});
httpWormALink.addEventListener("click", function() {

@ -1,32 +1,64 @@
/* Pop up Dialog Box */
dialogBoxes = [];
//Close dialog box when clicking outside
/*
$(document).click(function(event) {
if (dialogBoxOpened) {
if (!$(event.target).closest('.dialog-box-container').length){
--dialogBoxCount;
dialogBoxes.splice(0, 1);
$(".dialog-box-container").remove();
if (dialogBoxCount == 0) {
if (dialogBoxes.length == 0) {
dialogBoxOpened = false;
} else {
dialogBoxes[0].style.display +
}
}
}
});*/
$(document).click(function(event) {
if (dialogBoxOpened && dialogBoxes.length >= 1) {
if (!$(event.target).closest(dialogBoxes[0]).length){
dialogBoxes[0].remove();
dialogBoxes.splice(0, 1);
if (dialogBoxes.length == 0) {
dialogBoxOpened = false;
} else {
dialogBoxes[0].style.visibility = "visible";
}
}
}
});
//Dialog box close buttons
/*
$(document).on('click', '.dialog-box-close-button', function( event ) {
console.log("clicked close button");
if (dialogBoxOpened) {
$(this).closest('.dialog-box-container').remove();
--dialogBoxCount;
if (dialogBoxCount == 0) {
if (dialogBoxes.length == 0) {
dialogBoxOpened = false;
}
}
});
*/
$(document).on('click', '.dialog-box-close-button', function( event ) {
if (dialogBoxOpened && dialogBoxes.length >= 1) {
dialogBoxes[0].remove();
dialogBoxes.splice(0, 1);
if (dialogBoxes.length == 0) {
dialogBoxOpened = false;
} else {
dialogBoxes[0].style.visibility = "visible";
}
}
});
var dialogBoxOpened = false;
var dialogBoxCount = 0;
dialogBoxCreate = function(txt) {
var container = document.createElement("div");
@ -47,9 +79,12 @@ dialogBoxCreate = function(txt) {
container.appendChild(content);
document.body.appendChild(container);
if (dialogBoxes.length >= 1) {
container.style.visibility = "hidden";
}
dialogBoxes.push(container);
setTimeout(function() {
dialogBoxOpened = true;
++dialogBoxCount;
}, 500);
}, 400);
}

@ -36,7 +36,7 @@ purchaseRamForHomeBoxCreate = function() {
//Calculate cost
//Have cost increase by some percentage each time RAM has been upgraded
var cost = currentRam * CONSTANTS.BaseCostFor1GBOfRamHome;
var mult = Math.pow(1.36, numUpgrades);
var mult = Math.pow(1.40, numUpgrades);
cost = cost * mult;
purchaseRamForHomeBoxSetText("Would you like to purchase additional RAM for your home computer? <br><br>" +