Merge pull request #12 from danielyxie/dev

Dev v0.7
This commit is contained in:
danielyxie 2017-05-15 12:56:07 -05:00 committed by GitHub
commit 870af53072
18 changed files with 327 additions and 103 deletions

@ -5,31 +5,12 @@ TESTING TODO:
If a server has no more money available it cannot be hacked anymore
Should work automatically...because your money gained percentage will be multiplied by 0
When the game is loaded re-load all of the scripts in runningScripts
- Seems to be working
Adjust leveling formula. Goes up way too high at first
http://gamedev.stackexchange.com/questions/55151/rpg-logarithmic-leveling-formula
- might be too slow now?
Change Company pages to display "apply for promotion" and other stuff when you are already employed there
rm command seems to work
+ Traveling
Script logging functionality? Logs to internal "log file" (property of script itself)
Can see log with tail.
Should add something where if you click it in the "Active Scripts" GUI you can see the logs too
Seems to work fine
Gyms - Later..don't need for MVP
Tasks TODO:
Adding augmentations for Silhouette fac
Factions Info page isn't formatted correctly
@ -58,12 +39,4 @@ Private beta feedback
Also not really a big deal, but I'm at 110% zoom on chrome and the tutorial window
covers some of the text
For the last thing of the tutorial, I would just have a button like "Finish Tutorial" rather than "Next"
I'd put a little popup or something when you click save, so you know
Netscript commands:
I just got two from the top of my head: a function to get the current cash on the server, and a function to know how much a hack would take
Like, if I want to grow each time I take 5000$ from the server, that would be practical
Now, only other suggestion before sleep would be to be able to buy multiple Hacknet upgrades in one click

@ -23,11 +23,11 @@
#script-editor-container {
position: fixed;
padding-top: 10px;
padding-left: 10px;
height: 100%;
margin-left: 10%;
width: 75%;
width: 99%;
color: #66ff33;
overflow-y: scroll;
}
#script-editor-filename-tag {
@ -36,14 +36,12 @@
float: left;
}
#script-editor-save-and-close-button {
float: right;
display: inline-block;
}
#script-editor-save-and-close-button,
#script-editor-netscript-doc-button {
float: right;
display: inline-block;
width: 50%;
margin-right: 25%;
}
#script-editor-netscript-doc-warning {
@ -58,9 +56,9 @@
float: left;
resize: none;
color: #66ff33;
width: 100%;
margin: 4px;
padding: 4px;
width: 75%;
margin: 10px;
padding: 5px;
border: 2px solid white;
-webkit-box-shadow:
@ -81,10 +79,10 @@
#script-editor-text {
color: #66ff33;
width: 100%;
width: 75%;
height: 100%;
margin: 4px;
padding: 4px;
margin: 10px;
padding: 5px;
border: 2px solid white;
-webkit-box-shadow:

@ -165,7 +165,7 @@ tr:focus {
visibility: visible;
}
/* Flashing button */
/* Flashing button (Red) */
@-webkit-keyframes glowing {
0% { background-color: #B20000; -webkit-box-shadow: 0 0 3px #B20000; }
50% { background-color: #FF0000; -webkit-box-shadow: 0 0 40px #FF0000; }
@ -195,4 +195,30 @@ tr:focus {
-moz-animation: glowing 1500ms infinite;
-o-animation: glowing 1500ms infinite;
animation: glowing 1500ms infinite;
}
}
/* Status text */
@-webkit-keyframes status-text{
from{
opacity:1;
top:0px;
}
to{
opacity:0;
top:0px;
}
}
.status-text{
display:inline;
position:fixed;
top:0px;
-webkit-animation:status-text 3s 1;
}
#status-text {
font-size: 20px;
color: #FFFFFF;
right: 0;
bottom: 0;
}

@ -112,6 +112,10 @@
<li class="delete-game-tab">
<a href="#" id="delete-game-link"> Delete Game </a>
</li>
<li class="debug-delete-scripts-tab">
<a href="#" id="debug-delete-scripts-link"> (DEBUG) Delete Active Scripts </a>
</li>
</ul>
</div>
@ -148,6 +152,7 @@
<br>
<br><br>
<textarea id="script-editor-text" tabindex="2" autofocus> </textarea>
<p> <br><br> </p>
</div>
<!-- Active scripts info page -->
@ -693,5 +698,10 @@
<span id="interactive-tutorial-back"> Back </span>
</div>
<!-- Status text -->
<div id="status-text-container">
<p id="status-text"> </p>
</div>
</body>
</html>

@ -760,7 +760,7 @@ initAugmentations = function() {
AddToAugmentations(HacknetNodeNICUpload);
var HacknetNodeKernelDNI = new Augmentation(AugmentationNames.HacknetNodeKernelDNI);
HacknetNodeKernelDNI.setRequirements(4000, 90000000);
HacknetNodeKernelDNI.setRequirements(4000, 12000000);
HacknetNodeKernelDNI.setInfo("Installs a Direct-Neural Interface jack into the arm that is capable of connecting to a " +
"Hacknet Node. This lets the user access and manipulate the Node's kernel using the mind's " +
"electrochemical signals.<br><br>" +

@ -1,5 +1,5 @@
CONSTANTS = {
Version: "0.6",
Version: "0.7",
//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
@ -10,9 +10,9 @@ CONSTANTS = {
CorpFactionRepRequirement: 250000,
/* Base costs */
BaseCostFor1GBOfRamHome: 50000,
BaseCostFor1GBOfRamServer: 40000, //1 GB of RAM
BaseCostFor1GBOfRamHacknetNode: 25000,
BaseCostFor1GBOfRamHome: 40000,
BaseCostFor1GBOfRamServer: 35000, //1 GB of RAM
BaseCostFor1GBOfRamHacknetNode: 30000,
BaseCostForHacknetNode: 1000,
BaseCostForHacknetNodeCore: 1000000,
@ -34,17 +34,21 @@ CONSTANTS = {
CodeInstructionRunTime: 1500,
//RAM Costs for differenc commands
ScriptWhileRamCost: 0.4,
ScriptForRamCost: 0.4,
ScriptIfRamCost: 0.1,
ScriptHackRamCost: 0.25,
ScriptGrowRamCost: 0.25,
ScriptNukeRamCost: 0.05,
ScriptBrutesshRamCost: 0.05,
ScriptFtpcrackRamCost: 0.05,
ScriptRelaysmtpRamCost: 0.05,
ScriptHttpwormRamCost: 0.05,
ScriptSqlinjectRamCost: 0.05,
ScriptWhileRamCost: 0.4,
ScriptForRamCost: 0.4,
ScriptIfRamCost: 0.1,
ScriptHackRamCost: 0.25,
ScriptGrowRamCost: 0.25,
ScriptNukeRamCost: 0.05,
ScriptBrutesshRamCost: 0.05,
ScriptFtpcrackRamCost: 0.05,
ScriptRelaysmtpRamCost: 0.05,
ScriptHttpwormRamCost: 0.05,
ScriptSqlinjectRamCost: 0.05,
ScriptRunRamCost: 0.75,
ScriptGetHackingLevelRamCost: 0.1,
ScriptGetServerMoneyRamCost: 0.1,
ScriptOperatorRamCost: 0.01,
//Server growth rate
ServerGrowthRate: 1.00075,
@ -195,13 +199,18 @@ CONSTANTS = {
"section of this 'Tutorial' page. <br><br>Running a script requires RAM. The more complex a script is, the more RAM " +
"it requires to run. Scripts can be run on any server you have root access to. <br><br>" +
"Here are some Terminal commands that are useful when working with scripts: <br>" +
"free - Shows the current server's RAM usage <br>" +
"free - Shows the current server's RAM usage and availability <br>" +
"kill [script] - Stops a script that is running <br>" +
"mem [script] - Check how much RAM a script requires to run<br>" +
"nano [script] - Create/Edit a script <br>" +
"ps - Displays all scripts that are actively running on the current server<br>" +
"run [script] - Run a script <br>" +
"tail [script] - Displays a script's logs<br>" +
"top - Displays all active scripts and their RAM usage <br><br>",
"top - Displays all active scripts and their RAM usage <br><br>" +
"<strong>Note that because of the way the Netscript interpreter is implemented, " +
"whenever you reload or re-open the game all of the scripts that you are running will " +
"start running from the BEGINNING of the code. The game does not keep track of where exactly " +
"the execution of a script is when it saves/loads. </strong><br><br>",
TutorialNetscriptText: "Netscript is a very simple programming language implemented for this game. The language has " +
"your basic programming constructs and several built-in commands that are used to hack. <br><br>" +
"<u><h1> Variables and data types </h1></u><br>" +
@ -247,6 +256,13 @@ CONSTANTS = {
"<i>relaysmtp(hostname/ip)</i><br>Run relaySMTP.exe on the target server. relaySMTP.exe must exist on your home computer <br> Example: relaysmtp('foodnstuff');<br><br>" +
"<i>httpworm(hostname/ip)</i><br>Run HTTPWorm.exe on the target server. HTTPWorm.exe must exist on your home computer <br> Example: httpworm('foodnstuff');<br><br>" +
"<i>sqlinject(hostname/ip)</i><br>Run SQLInject.exe on the target server. SQLInject.exe must exist on your home computer <br> Example: sqlinject('foodnstuff');<br><br>" +
"<i>run(script)</i> <br> Run a script as a separate process. The argument that is passed in is the name of the script as a string. This function can only " +
"be used to run scripts located on the same server. Returns true if the script is successfully started, and false otherwise. Requires a significant amount " +
"of RAM to run this command.<br>Example: run('hack-foodnstuff.script'); <br> The example above will try and launch the 'hack-foodnstuff.script' script on " +
"the current server, if it exists. <br><br>" +
"<i>getHackingLevel() </i><br> Returns the Player's current hacking level <br><br> " +
"<i>getServerMoneyAvailable(hostname/ip)</i><br> Returns the amount of money available on a server. The argument passed in must be a string with either the " +
"hostname or IP of the target server. <br> Example: getServerMoneyAvailable('foodnstuff');<br><br>" +
"<u><h1>While loops </h1></u><br>" +
"A while loop is a control flow statement that repeatedly executes code as long as a condition is met. <br><br> " +
"<i>while (<i>[cond]</i>) {<br>&nbsp;&nbsp;&nbsp;&nbsp;<i>[code]</i><br>}</i><br><br>" +
@ -257,14 +273,28 @@ CONSTANTS = {
"This while loop above is an infinite loop (continuously runs until the script is manually stopped) that repeatedly runs the 'hack('foodnstuff')' command. " +
"Note that a semicolon is needed at closing bracket of the while loop, UNLESS it is at the end of the code<br><br> " +
"<u><h1>For loops</h1></u><br>" +
"A for loop is another control flow statement that allows code to by repeated by iterations. The structure is: <br><br> " +
"A for loop is another control flow statement that allows code to be repeated by iterations. The structure is: <br><br> " +
"<i>for (<i>[init]</i>; <i>[cond]</i>; <i>[post]</i>) {<br>&nbsp;&nbsp;&nbsp;&nbsp;<i>code</i> <br> }; </i><br><br>" +
"The <i>[init]</i> expression evaluates before the for loop begins. The for loop will continue to execute " +
"as long as <i>[cond]</i> is met. The <i>[post]</i> expression will evaluate at the end of every iteration " +
"of the for loop. The following example shows code that will do the same thing as the while loop example above, " +
"except using a for loop instead: <br><br>" +
"of the for loop. The following example shows code that will run the 'hack('foodnstuff');' command 10 times " +
" using a for loop: <br><br>" +
"<i>for (i = 0; i < 10; i = i+1) { <br>&nbsp;&nbsp;&nbsp;&nbsp;hack('foodnstuff');<br>}; </i><br><br>" +
"<u><h1> If statements </h1></u>",
"<u><h1> If statements </h1></u><br>" +
"If/Elif/Else statements are conditional statements used to perform different actions based on different conditions: <br><br>" +
"<i>if (condition1) {<br>&nbsp;&nbsp;&nbsp;&nbsp;code1<br>} elif (condition2) {<br>&nbsp;&nbsp;&nbsp;&nbsp;code2<br>} else {<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;code3<br>}</i><br><br>" +
"In the code above, first <i>condition1</i> will be checked. If this condition is true, then <i>code1</i> will execute and the " +
"rest of the if/elif/else statement will be skipped. If <i>condition1</i> is NOT true, then the code will then go on to check " +
"<i>condition2</i>. If <i>condition2</i> is true, then <i>code2</i> will be executed, and the rest of the if/elif/else statement " +
"will be skipped. If none of the conditions are true, then the code within the else block (<i>code3</i>) will be executed. " +
"Note that a conditional statement can have any number of elif statements. <br><br>" +
"Example: <br><br>" +
"if(getServerMoneyAvailable('foodnstuff') > 200000) {<br>&nbsp;&nbsp;&nbsp;&nbsp;hack('foodnstuff');<br>" +
"} else {<br>&nbsp;&nbsp;&nbsp;&nbsp;grow('foodnstuff');<br>};<br><br>" +
"The code above will use the getServerMoneyAvailable() function to check how much money there is on the 'foodnstuff' server. " +
"If there is more than $200,000, then it will try to hack that server. If there is $200,000 or less on the server, " +
"then the code will call grow('foodnstuff') instead and add more money to the server.<br><br>",
TutorialTravelingText:"There are six major cities in the world that you are able to travel to: <br><br> " +
" Aevum<br>" +
@ -292,8 +322,10 @@ CONSTANTS = {
"your stats. Different positions value different stats. When you are working, you are unable to perform any " +
"other actions such as using your terminal or visiting other locations (However, note that any scripts you have " +
"running on servers will continue to run as you work!). It is possible to cancel your work shift before the " +
"8 hours is up, but doing so will result in you gaining only half of all of the money, experience, and reputation " +
"that you had earned up to that point. <br><br>" +
"8 hours is up. However, if you have a full-time job, then cancelling a shift early will result in you gaining " +
"only half of all of the money, experience, and reputation " +
"that you had earned up to that point. There are also part-time/consultant jobs available where you will not " +
" be penalized if you cancel a work shift early. However, these positions pay less than full-time positions.<br><br>" +
"As you continue to work at a company, you will gain more and more reputation at that company. When your stats " +
"and reputation are high enough, you can get a promotion. You can apply for a promotion on the company page, just like " +
"you applied for the job originally. Higher positions at a company provide better salaries and stat gains.",

@ -16,12 +16,13 @@ HacknetNode.prototype.updateMoneyGainRate = function() {
//How much extra $/s is gained per level
var gainPerLevel = CONSTANTS.HacknetNodeMoneyGainPerLevel;
//Each CPU core doubles the speed. Every 1GB of ram adds 20% increase
//Each CPU core doubles the speed. Every 1GB of ram adds 15% increase
this.moneyGainRatePerSecond = (this.level * gainPerLevel) *
Math.pow(1.2, this.ram-1) *
Math.pow(1.15, this.ram-1) *
this.numCores * Player.hacknet_node_money_mult;
if (isNaN(this.moneyGainRatePerSecond)) {
throw new Error("Money gain rate calculated for Hacknet Node is NaN");
this.moneyGainRatePerSecond = 0;
dialogBoxCreate("Error in calculating Hacknet Node production. Please report to game developer");
}
updateTotalHacknetProduction();
@ -175,7 +176,7 @@ updateHacknetNodesContent = function() {
//Update player's money
var moneyElem = document.getElementById("hacknet-nodes-money");
moneyElem.innerHTML = "Money: $" + formatNumber(Player.money, 2) + "<br>" +
"Total production from all Hacknet Nodes: $" + formatNumber(Player.totalHacknetNodeProduction, 2);
"Total production from all Hacknet Nodes: $" + formatNumber(Player.totalHacknetNodeProduction, 2) + " / second";
//Update information in each owned hacknet node
for (var i = 0; i < Player.hacknetNodes.length; ++i) {

@ -296,7 +296,7 @@ displayLocationContent = function() {
travelToVolhaven.style.display = "block";
break;
case Locations.AevumSummitUniveristy:
case Locations.AevumSummitUniversity:
var costMult = 4, expMult = 3;
displayUniversityLocationContent(costMult);
setUniversityLocationButtons(costMult, expMult);

@ -209,6 +209,8 @@ function evaluate(exp, workerScript) {
* relaysmtp(server)
* httpworm(server)
* sqlinject(server)
* getHackingLevel()
* run(script))
*/
case "call":
//Define only valid function calls here, like hack() and stuff
@ -223,6 +225,7 @@ function evaluate(exp, workerScript) {
if (exp.func.value == "hack") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Hack() call has incorrect number of arguments. Takes 1 argument");
return;
}
var ipPromise = evaluate(exp.args[0], workerScript);
@ -304,6 +307,7 @@ function evaluate(exp, workerScript) {
} else if (exp.func.value == "sleep") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|sleep() call has incorrect number of arguments. Takes 1 argument.");
return;
}
var sleepTimePromise = evaluate(exp.args[0], workerScript);
sleepTimePromise.then(function(sleepTime) {
@ -325,6 +329,7 @@ function evaluate(exp, workerScript) {
} else if (exp.func.value == "print") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|print() call has incorrect number of arguments. Takes 1 argument");
return;
}
var p = new Promise(function(resolve, reject) {
@ -347,10 +352,11 @@ function evaluate(exp, workerScript) {
} else if (exp.func.value == "grow") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|grow() call has incorrect number of arguments. Takes 1 argument");
return;
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
if (env.stopFlag) {reject(workerScript);}
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into grow() command");
@ -388,9 +394,11 @@ function evaluate(exp, workerScript) {
} else if (exp.func.value == "nuke") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|nuke() call has incorrect number of arguments. Takes 1 argument");
return;
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
if (env.stopFlag) {reject(workerScript);}
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into nuke() command");
@ -433,9 +441,11 @@ function evaluate(exp, workerScript) {
} else if (exp.func.value == "brutessh") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|brutessh() call has incorrect number of arguments. Takes 1 argument");
return;
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
if (env.stopFlag) {reject(workerScript);}
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into brutessh() command");
@ -474,9 +484,11 @@ function evaluate(exp, workerScript) {
} else if (exp.func.value == "ftpcrack") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|ftpcrack() call has incorrect number of arguments. Takes 1 argument");
return;
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
if (env.stopFlag) {reject(workerScript);}
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into ftpcrack() command");
@ -515,9 +527,11 @@ function evaluate(exp, workerScript) {
} else if (exp.func.value == "relaysmtp") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|relaysmtp() call has incorrect number of arguments. Takes 1 argument");
return;
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
if (env.stopFlag) {reject(workerScript);}
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into relaysmtp() command");
@ -556,9 +570,11 @@ function evaluate(exp, workerScript) {
} else if (exp.func.value == "httpworm") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|httpworm() call has incorrect number of arguments. Takes 1 argument");
return;
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
if (env.stopFlag) {reject(workerScript);}
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into relaysmtp() command");
@ -597,9 +613,11 @@ function evaluate(exp, workerScript) {
} else if (exp.func.value == "sqlinject") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|sqlinject() call has incorrect number of arguments. Takes 1 argument");
return;
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
if (env.stopFlag) {reject(workerScript);}
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into sqlinject() command");
@ -635,9 +653,63 @@ function evaluate(exp, workerScript) {
}, function(e) {
reject(e);
});
} else if (exp.func.value == "run") {
if (exp.args.length != 1) {
reject("|"+workerScript.serverIp+"|"+workerScript.name+"|run() call has incorrect number of arguments. Takes 1 argument");
return;
}
var scriptNamePromise = evaluate(exp.args[0], workerScript);
scriptNamePromise.then(function(scriptname) {
var serverIp = workerScript.serverIp;
var scriptServer = AllServers[serverIp];
if (scriptServer == null) {
reject("|"+workerScript.serverIp+"|"+workerScript.name+"|Could not find server. This is a bug in the game. Report to game dev");
return;
}
var runScriptPromise = runScriptFromScript(scriptServer, scriptname, workerScript);
runScriptPromise.then(function(res) {
resolve(res);
}, function(e) {
reject(e);
});
}, function(e) {
reject(e);
});
} else if (exp.func.value == "getHackingLevel") {
if (exp.args.length != 0) {
reject("|"+workerScript.serverIp+"|"+workerScript.name+"|getHackingLevel() call has incorrect number of arguments. Takes 0 arguments");
return;
}
setTimeout(function() {
Player.updateSkillLevels();
workerScript.scriptRef.log("getHackingLevel() returned " + Player.hacking_skill);
resolve(Player.hacking_skill);
}, CONSTANTS.CodeInstructionRunTime);
} else if (exp.func.value == "getServerMoneyAvailable") {
if (exp.args.length != 1) {
reject("|"+workerScript.serverIp+"|"+workerScript.name+"|getServerMoneyAvailable() call has incorrect number of arguments. Takes 1 arguments");
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
setTimeout(function() {
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into getServerMoneyAvailable() command");
workerScript.scriptRef.log("Cannot getServerMoneyAvailable(). Invalid IP or hostname passed in: " + ip);
return;
}
workerScript.scriptRef.log("getServerMoneyAvailable() returned " + server.moneyAvailable);
resolve(server.moneyAvailable);
}, CONSTANTS.CodeInstructionRunTime);
}, function(e) {
reject(e);
});
}
}, CONSTANTS.CodeInstructionRunTime);
});
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Unrecognized function call");
break;
default:
@ -868,7 +940,54 @@ function apply_op(op, a, b) {
case "!=": return a !== b;
}
throw new Error("Can't apply operator " + op);
}
}
//Run a script from inside a script using run() command
function runScriptFromScript(server, scriptname, workerScript) {
return new Promise(function(resolve, reject) {
var env = workerScript.env;
if (env.stopFlag) {reject(workerScript);}
setTimeout(function() {
//Check if the script is already running
for (var i = 0; i < server.runningScripts.length; ++i) {
if (server.runningScripts[i] == scriptname) {
workerScript.scriptRef.log(scriptname + " is already running on " + server.hostname);
resolve(false);
return;
}
}
//Check if the script exists and if it does run it
for (var i = 0; i < server.scripts.length; ++i) {
if (server.scripts[i].filename == scriptname) {
//Check for admin rights and that there is enough RAM availble to run
var ramUsage = server.scripts[i].ramUsage;
var ramAvailable = server.maxRam - server.ramUsed;
if (server.hasAdminRights == false) {
workerScript.scriptRef.log("Cannot run script " + scriptname + " because you do not have root access!");
resolve(false);
return;
} else if (ramUsage > ramAvailable){
workerScript.scriptRef.log("Cannot run script " + scriptname + " because there is not enough available RAM!");
resolve(false);
return;
} else {
//Able to run script
workerScript.scriptRef.log("Running script: " + scriptname + ". May take a few seconds to start up...");
var script = server.scripts[i];
server.runningScripts.push(script.filename); //Push onto runningScripts
addWorkerScript(script, server);
resolve(true);
return;
}
}
}
workerScript.scriptRef.log("Could not find script " + scriptname + " on " + server.hostname);
resolve(false);
}, CONSTANTS.CodeInstructionRunTime);
});
}
function isScriptErrorMessage(msg) {
splitMsg = msg.split("|");
@ -913,4 +1032,4 @@ function scriptCalculatePercentMoneyHacked(server) {
if (percentMoneyHacked < 0) {return 0;}
if (percentMoneyHacked > 1) {return 1;}
return percentMoneyHacked;
}
}

@ -109,16 +109,13 @@ function Parser(input) {
* else: {"type": "var", "value": "foo"}
*/
function parse_if() {
console.log("Parsing if token");
checkKeywordAndSkip("if");
//Conditional
var cond = parse_expression();
console.log("cond: " + cond);
//Body
var then = parse_expression();
console.log("then: " + then);
var ret = {
type: "if",
cond: [],

@ -31,6 +31,7 @@ function runScriptsLoop() {
if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) {
try {
var ast = Parser(Tokenizer(InputStream(workerScripts[i].code)));
//console.log(ast);
} catch (e) {
dialogBoxCreate("Syntax ERROR in " + workerScripts[i].name + ":", e, "", "");
workerScripts[i].env.stopFlag = true;

@ -168,6 +168,7 @@ function PlayerObject() {
//Used to store the last update time.
this.lastUpdate = new Date().getTime();
this.totalPlaytime = 0;
};
PlayerObject.prototype.init = function() {
@ -584,7 +585,7 @@ PlayerObject.prototype.finishWorkPartTime = function() {
formatNumber(this.workDexExpGained, 4) + " dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " agility exp <br>" +
formatNumber(this.workChaExpGained, 4) + " charisma exp<br>";
txt = "You worked for " + convertTimeMsToTimeElapsedString(this.timeWorked) + ".<br><br> " + txt;
txt = "You worked for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br> " + txt;
dialogBoxCreate(txt);
var mainMenu = document.getElementById("mainmenu-container");

@ -22,6 +22,9 @@ BitburnerSaveObject.prototype.saveGame = function() {
var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this))));
window.localStorage.setItem("bitburnerSave", saveString);
console.log("Game saved!");
Engine.createStatusText("Game saved!");
}
loadGame = function(saveObj) {
@ -45,6 +48,7 @@ BitburnerSaveObject.prototype.deleteGame = function() {
if (window.localStorage.getItem("bitburnerSave")) {
window.localStorage.removeItem("bitburnerSave");
}
Engine.createStatusText("Game deleted!");
}

@ -96,11 +96,6 @@ function Script() {
this.logs = []; //Script logging. Array of strings, with each element being a log entry
/* Properties to calculate offline progress. Only applies for infinitely looping scripts */
//Number of instructions ("lines") in the code. Any call ending in a ;
//is considered one instruction. Used to calculate ramUsage
this.numInstructions = 0;
//Stats to display on the Scripts menu, and used to determine offline progress
this.offlineRunningTime = 0.01; //Seconds
this.offlineMoneyMade = 0;
@ -125,8 +120,7 @@ Script.prototype.saveScript = function() {
//Server
this.server = Player.currentServer;
//Calculate/update number of instructions, ram usage, execution time, etc.
this.updateNumInstructions();
//Calculate/update ram usage, execution time, etc.
this.updateRamUsage();
//Clear the stats when the script is updated
@ -147,12 +141,7 @@ Script.prototype.reset = function() {
this.onlineRunningTime = 0.01; //Seconds
this.onlineMoneyMade = 0;
this.onlineExpGained = 0;
}
//Calculates the number of instructions, which is just determined by number of semicolons
Script.prototype.updateNumInstructions = function() {
var numSemicolons = this.code.split(";").length - 1;
this.numInstructions = numSemicolons;
this.logs = [];
}
//Updates how much RAM the script uses when it is running.
@ -172,6 +161,10 @@ Script.prototype.updateRamUsage = function() {
var relaysmtpCount = numOccurrences(codeCopy, "relaysmtp(");
var httpwormCount = numOccurrences(codeCopy, "httpworm(");
var sqlinjectCount = numOccurrences(codeCopy, "sqlinject(");
var runCount = numOccurrences(codeCopy, "run(");
var getHackingLevelCount = numOccurrences(codeCopy, "getHackingLevel(");
var getServerMoneyAvailableCount = numOccurrences(codeCopy, "getServerMoneyAvailable(");
var numOperators = numNetscriptOperators(codeCopy);
this.ramUsage = baseRam +
((whileCount * CONSTANTS.ScriptWhileRamCost) +
@ -184,8 +177,15 @@ Script.prototype.updateRamUsage = function() {
(ftpcrackCount * CONSTANTS.ScriptFtpcrackRamCost) +
(relaysmtpCount * CONSTANTS.ScriptRelaysmtpRamCost) +
(httpwormCount * CONSTANTS.ScriptHttpwormRamCost) +
(sqlinjectCount * CONSTANTS.ScriptSqlinjectRamCost));
(sqlinjectCount * CONSTANTS.ScriptSqlinjectRamCost) +
(runCount * CONSTANTS.ScriptRunRamCost) +
(getHackingLevelCount * CONSTANTS.ScriptGetHackingLevelRamCost) +
(getServerMoneyAvailableCount * CONSTANTS.ScriptGetServerMoneyRamCost) +
(numOperators * CONSTANTS.ScriptOperatorRamCost));
console.log("ram usage: " + this.ramUsage);
if (isNaN(this.ramUsage)) {
dialogBoxCreate("ERROR in calculating ram usage. This is a bug, please report to game develoepr");
}
}
Script.prototype.log = function(txt) {
@ -304,7 +304,6 @@ function AllServersToMoneyMap() {
}
AllServersToMoneyMap.prototype.printConsole = function() {
console.log("Printing AllServersToMoneyMap");
for (var ip in this) {
if (this.hasOwnProperty(ip)) {
var serv = AllServers[ip];
@ -312,7 +311,6 @@ AllServersToMoneyMap.prototype.printConsole = function() {
console.log("Warning null server encountered with ip: " + ip);
continue;
}
console.log(ip + "(" + serv.hostname + "): " + this[ip]);
}
}
}

@ -452,7 +452,7 @@ initForeignServers = function() {
var HaraKiriSushiBarServer = new Server();
HaraKiriSushiBarServer.setHackingParameters(40, 2000000, 15, 40);
HaraKiriSushiBarServer.init(createRandomIp(), "harakiri-sushi", "HaraKiri Sushi Bar Network", true, false, false, false, 4);
HaraKiriSushiBarServer.setPortProperties(1);
HaraKiriSushiBarServer.setPortProperties(0);
AddToAllServers(HaraKiriSushiBarServer);
var PhantasyServer = new Server();

@ -273,7 +273,8 @@ var Engine = {
'Crime money multiplier: ' + formatNumber(Player.crime_money_mult * 100, 2) + '%<br><br><br>' +
'<b>Misc</b><br><br>' +
'Servers owned: ' + Player.purchasedServers.length + '<br>' +
'Hacknet Nodes owned: ' + Player.hacknetNodes.length + '<br><br> ').replace( / /g, "&nbsp;" );
'Hacknet Nodes owned: ' + Player.hacknetNodes.length + '<br>' +
'Time played: ' + convertTimeMsToTimeElapsedString(Player.totalPlaytime) + '<br><br><br>').replace( / /g, "&nbsp;" );
},
@ -524,6 +525,11 @@ var Engine = {
},
updateGame: function(numCycles = 1) {
//Update total playtime
var time = numCycles * Engine._idleSpeed;
if (Player.totalPlaytime == null) {Player.totalPlaytime = 0;}
Player.totalPlaytime += time;
//Start Manual hack
if (Player.startAction == true) {
Engine._totalActionTime = Player.actionTime;
@ -685,6 +691,23 @@ var Engine = {
}
},
_prevTimeout: null,
createStatusText: function(txt) {
if (Engine._prevTimeout != null) {
clearTimeout(Engine._prevTimeout);
Engine._prevTimeout = null;
}
var statusText = document.getElementById("status-text")
statusText.style.display = "inline-block";
statusText.setAttribute("class", "status-text");
statusText.innerHTML = txt;
Engine._prevTimeout = setTimeout(function() {
statusText.style.display = "none";
statusText.removeAttribute("class");
statusText.innerHTML = "";
}, 3000);
},
load: function() {
//Load game from save or create new game
if (loadGame(saveObject)) {
@ -723,6 +746,11 @@ var Engine = {
//Passive faction rep gain offline
processPassiveFactionRepGain(numCyclesOffline);
//Update total playtime
var time = numCyclesOffline * Engine._idleSpeed;
if (Player.totalPlaytime == null) {Player.totalPlaytime = 0;}
Player.totalPlaytime += time;
} else {
//No save found, start new game
console.log("Initializing new game");
@ -987,7 +1015,7 @@ var Engine = {
if (Player.workType == CONSTANTS.WorkTypeFaction) {
var fac = Factions[Player.currentWorkFactionName];
Player.finishFactionWork(true, fac);
} else if (Player.WorkType == CONSTANTS.WorkTypeCreateProgram) {
} else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) {
Player.finishCreateProgramWork(true, Player.createProgramName);
} else if (Player.workType == CONSTANTS.WorkTypeStudyClass) {
Player.finishClass();
@ -1001,6 +1029,12 @@ var Engine = {
});
Engine.loadWorkInProgressContent();
}
//DEBUG
document.getElementById("debug-delete-scripts-link").addEventListener("click", function() {
Player.getHomeComputer().runningScripts = [];
return false;
});
},
start: function() {

@ -34,10 +34,9 @@ purchaseRamForHomeBoxCreate = function() {
var numUpgrades = Math.log2(currentRam);
//Calculate cost
//Base cost of RAM is 50k per 1GB...but lets have this increase by some percentage
//each time the ram has been upgraded
//Have cost increase by some percentage each time RAM has been upgraded
var cost = currentRam * CONSTANTS.BaseCostFor1GBOfRamHome;
var mult = Math.pow(1.32, numUpgrades);
var mult = Math.pow(1.33, numUpgrades);
cost = cost * mult;
purchaseRamForHomeBoxSetText("Would you like to purchase additional RAM for your home computer? <br><br>" +

@ -32,6 +32,9 @@ function convertTimeMsToTimeElapsedString(time) {
//Convert ms to seconds, since we only have second-level precision
time = Math.floor(time / 1000);
var days = Math.floor(time / 86400);
time %= 86400;
var hours = Math.floor(time / 3600);
time %= 3600;
@ -40,7 +43,12 @@ function convertTimeMsToTimeElapsedString(time) {
var seconds = time;
return hours + " hours " + minutes + " minutes " + seconds + " seconds";
var res = "";
if (days) {res += days + " days";}
if (hours) {res += hours + " hours ";}
if (minutes) {res += minutes + " minutes ";}
if (seconds) {res += seconds + " seconds ";}
return res;
}
//Finds the longest common starting substring in a set of strings
@ -73,7 +81,7 @@ function formatNumber(num, numFractionDigits) {
});
}
//Counters the number of times a substring occurs in a string
//Count the number of times a substring occurs in a string
function numOccurrences(string, subString) {
string += "";
subString += "";
@ -89,4 +97,27 @@ function numOccurrences(string, subString) {
} else break;
}
return n;
}
}
//Counters the number of Netscript operators in a string
function numNetscriptOperators(string) {
var total = 0;
total += numOccurrences(string, "+");
total += numOccurrences(string, "-");
total += numOccurrences(string, "*");
total += numOccurrences(string, "/");
total += numOccurrences(string, "%");
total += numOccurrences(string, "&&");
total += numOccurrences(string, "||");
total += numOccurrences(string, "<");
total += numOccurrences(string, ">");
total += numOccurrences(string, "<=");
total += numOccurrences(string, ">=");
total += numOccurrences(string, "==");
total += numOccurrences(string, "!=");
if (isNaN(total)) {
dialogBoxCreate("ERROR in counting number of operators in script. This is a bug, please report to game developer");
total = 0;
}
return total;
}