From f32ec4f9a78fa3ef6978a011c646ba0a9a5eadf5 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Mon, 15 May 2017 01:35:09 -0500 Subject: [PATCH 01/10] Added getServerMoneyAvailable(), run(), and getHackingSkill() commands, and some small bug fixes + UI improvements --- src/HacknetNode.js | 2 +- src/Location.js | 2 +- src/NetscriptEvaluator.js | 96 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 96 insertions(+), 4 deletions(-) diff --git a/src/HacknetNode.js b/src/HacknetNode.js index 89e38c991..e9b926c11 100644 --- a/src/HacknetNode.js +++ b/src/HacknetNode.js @@ -175,7 +175,7 @@ updateHacknetNodesContent = function() { //Update player's money var moneyElem = document.getElementById("hacknet-nodes-money"); moneyElem.innerHTML = "Money: $" + formatNumber(Player.money, 2) + "
" + - "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) { diff --git a/src/Location.js b/src/Location.js index 5174ffd81..e3a3328bb 100644 --- a/src/Location.js +++ b/src/Location.js @@ -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); diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index b3d91683e..876e7dee5 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -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 @@ -635,6 +637,53 @@ 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"); + } + 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"); + } + + 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"); + } + setTimeout(function() { + 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; + } + resolve(server.moneyAvailable); + }, CONSTANTS.CodeInstructionRunTime); + }, function(e) { + reject(e); + }); } }, CONSTANTS.CodeInstructionRunTime); }); @@ -868,7 +917,50 @@ 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) { + 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); + } + } + + //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); + } + } + } + workerScript.scriptRef.log("Could not find script " + scriptname + " on " + server.hostname); + resolve(false); + }, CONSTANTS.CodeInstructionRunTime); + }); +} function isScriptErrorMessage(msg) { splitMsg = msg.split("|"); @@ -913,4 +1005,4 @@ function scriptCalculatePercentMoneyHacked(server) { if (percentMoneyHacked < 0) {return 0;} if (percentMoneyHacked > 1) {return 1;} return percentMoneyHacked; -} \ No newline at end of file +} \ No newline at end of file From 3919d3e97ae5b1a761b3f7b31b01ed50151e820b Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Mon, 15 May 2017 09:15:59 -0500 Subject: [PATCH 02/10] Bug fixes for new Netscript commands. Added total Playtime statistics. Minor UI improvements --- README.md | 4 +--- index.html | 4 ++++ src/Augmentations.js | 2 +- src/Constants.js | 25 ++++++++++++++----------- src/NetscriptEvaluator.js | 4 ++++ src/NetscriptParser.js | 3 --- src/NetscriptWorker.js | 1 + src/Player.js | 1 + src/Script.js | 25 +++++++++---------------- src/engine.js | 14 +++++++++++++- utils/StringHelperFunctions.js | 10 +++++++++- 11 files changed, 57 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 9c3317aaa..ba370f007 100644 --- a/README.md +++ b/README.md @@ -57,9 +57,7 @@ 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: diff --git a/index.html b/index.html index f045e7fbb..ee64dfb49 100644 --- a/index.html +++ b/index.html @@ -112,6 +112,10 @@
  • Delete Game
  • + +
  • + Delete Active Scripts +
  • diff --git a/src/Augmentations.js b/src/Augmentations.js index 930a85daf..3ca5c1d03 100644 --- a/src/Augmentations.js +++ b/src/Augmentations.js @@ -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.

    " + diff --git a/src/Constants.js b/src/Constants.js index 44eb55917..317838987 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -34,17 +34,20 @@ 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.5, + ScriptGetHackingLevelRamCost: 0.1, + ScriptGetServerMoneyRamCost: 0.1, //Server growth rate ServerGrowthRate: 1.00075, diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index 876e7dee5..ee18b1ee8 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -638,6 +638,7 @@ function evaluate(exp, workerScript) { reject(e); }); } else if (exp.func.value == "run") { + console.log("run() called"); if (exp.args.length != 1) { reject("|"+workerScript.serverIp+"|"+workerScript.name+"|run() call has incorrect number of arguments. Takes 1 argument"); } @@ -660,10 +661,12 @@ function evaluate(exp, workerScript) { reject(e); }); } else if (exp.func.value == "getHackingLevel") { + console.log("getHackingLevel called"); if (exp.args.length != 0) { reject("|"+workerScript.serverIp+"|"+workerScript.name+"|getHackingLevel() call has incorrect number of arguments. Takes 0 arguments"); } setTimeout(function() { + console.log("About to resolve getHackingLevel"); resolve(Player.hacking_skill); }, CONSTANTS.CodeInstructionRunTime); } else if (exp.func.value == "getServerMoneyAvailable") { @@ -687,6 +690,7 @@ function evaluate(exp, workerScript) { } }, CONSTANTS.CodeInstructionRunTime); }); + reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Unrecognized function call"); break; default: diff --git a/src/NetscriptParser.js b/src/NetscriptParser.js index 09b366d31..95f4fad71 100644 --- a/src/NetscriptParser.js +++ b/src/NetscriptParser.js @@ -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: [], diff --git a/src/NetscriptWorker.js b/src/NetscriptWorker.js index 6667d2608..4f57bb201 100644 --- a/src/NetscriptWorker.js +++ b/src/NetscriptWorker.js @@ -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; diff --git a/src/Player.js b/src/Player.js index 68256bf60..cbcda55ef 100644 --- a/src/Player.js +++ b/src/Player.js @@ -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() { diff --git a/src/Script.js b/src/Script.js index d9429618a..e86913312 100644 --- a/src/Script.js +++ b/src/Script.js @@ -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,9 @@ 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("); this.ramUsage = baseRam + ((whileCount * CONSTANTS.ScriptWhileRamCost) + @@ -184,7 +176,10 @@ 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)); console.log("ram usage: " + this.ramUsage); } @@ -304,7 +299,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 +306,6 @@ AllServersToMoneyMap.prototype.printConsole = function() { console.log("Warning null server encountered with ip: " + ip); continue; } - console.log(ip + "(" + serv.hostname + "): " + this[ip]); } } } \ No newline at end of file diff --git a/src/engine.js b/src/engine.js index 57d580bce..5d7a4b400 100644 --- a/src/engine.js +++ b/src/engine.js @@ -273,7 +273,8 @@ var Engine = { 'Crime money multiplier: ' + formatNumber(Player.crime_money_mult * 100, 2) + '%


    ' + 'Misc

    ' + 'Servers owned: ' + Player.purchasedServers.length + '
    ' + - 'Hacknet Nodes owned: ' + Player.hacknetNodes.length + '

    ').replace( / /g, " " ); + 'Hacknet Nodes owned: ' + Player.hacknetNodes.length + '
    ' + + 'Time played: ' + convertTimeMsToTimeElapsedString(Player.totalPlaytime) + '


    ').replace( / /g, " " ); }, @@ -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; @@ -1001,6 +1007,12 @@ var Engine = { }); Engine.loadWorkInProgressContent(); } + + //DEBUG + document.getElementById("debug-delete-scripts-link").addEventListener("click", function() { + Player.getHomeComputer().runningScripts = []; + return false; + }); }, start: function() { diff --git a/utils/StringHelperFunctions.js b/utils/StringHelperFunctions.js index b518b5a0f..d030e5d3e 100644 --- a/utils/StringHelperFunctions.js +++ b/utils/StringHelperFunctions.js @@ -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 From 5039a03732d93fcdd4329dd609d7f109aded3fcc Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Mon, 15 May 2017 10:13:21 -0500 Subject: [PATCH 03/10] UI Improvement to script editor. FIxed some bugs in new Netscript commands --- css/menupages.css | 24 +++++++++++------------- index.html | 1 + src/Constants.js | 32 +++++++++++++++++++++++++++++--- src/HacknetNode.js | 7 ++++--- src/NetscriptEvaluator.js | 18 ++++++++++++++---- src/NetscriptWorker.js | 2 +- 6 files changed, 60 insertions(+), 24 deletions(-) diff --git a/css/menupages.css b/css/menupages.css index 0ec027941..79a3c49dc 100644 --- a/css/menupages.css +++ b/css/menupages.css @@ -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: diff --git a/index.html b/index.html index ee64dfb49..3b30df5e3 100644 --- a/index.html +++ b/index.html @@ -152,6 +152,7 @@


    +



    diff --git a/src/Constants.js b/src/Constants.js index 317838987..20e15606c 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -198,13 +198,18 @@ CONSTANTS = { "section of this 'Tutorial' page.

    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.

    " + "Here are some Terminal commands that are useful when working with scripts:
    " + - "free - Shows the current server's RAM usage
    " + + "free - Shows the current server's RAM usage and availability
    " + "kill [script] - Stops a script that is running
    " + + "mem [script] - Check how much RAM a script requires to run
    " + "nano [script] - Create/Edit a script
    " + "ps - Displays all scripts that are actively running on the current server
    " + "run [script] - Run a script
    " + "tail [script] - Displays a script's logs
    " + - "top - Displays all active scripts and their RAM usage

    ", + "top - Displays all active scripts and their RAM usage

    " + + "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.

    ", 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.

    " + "

    Variables and data types


    " + @@ -250,6 +255,13 @@ CONSTANTS = { "relaysmtp(hostname/ip)
    Run relaySMTP.exe on the target server. relaySMTP.exe must exist on your home computer
    Example: relaysmtp('foodnstuff');

    " + "httpworm(hostname/ip)
    Run HTTPWorm.exe on the target server. HTTPWorm.exe must exist on your home computer
    Example: httpworm('foodnstuff');

    " + "sqlinject(hostname/ip)
    Run SQLInject.exe on the target server. SQLInject.exe must exist on your home computer
    Example: sqlinject('foodnstuff');

    " + + "run(script)
    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.
    Example: run('hack-foodnstuff.script');
    The example above will try and launch the 'hack-foodnstuff.script' script on " + + "the current server, if it exists.

    " + + "getHackingLevel()
    Returns the Player's current hacking level

    " + + "getServerMoneyAvailable(hostname/ip)
    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.
    Example: getServerMoneyAvailable('foodnstuff');

    " + "

    While loops


    " + "A while loop is a control flow statement that repeatedly executes code as long as a condition is met.

    " + "while ([cond]) {
        [code]
    }


    " + @@ -267,7 +279,21 @@ CONSTANTS = { "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:

    " + "for (i = 0; i < 10; i = i+1) {
        hack('foodnstuff');
    };


    " + - "

    If statements

    ", + "

    If statements


    " + + "If/Elif/Else statements are conditional statements used to perform different actions based on different conditions:

    " + + "if (condition1) {
        code1
    } elif (condition2) {
        code2
    } else {
    " + + "    code3
    }


    " + + "In the code above, first condition1 will be checked. If this condition is true, then code1 will execute and the " + + "rest of the if/elif/else statement will be skipped. If condition1 is NOT true, then the code will then go on to check " + + "condition2. If condition2 is true, then code2 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 (code3) will be executed. " + + "Note that a conditional statement can have any number of elif statements.

    " + + "Example:

    " + + "if(getServerMoneyAvailable('foodnstuff') > 200000) {
        hack('foodnstuff');
    " + + "} else {
        grow('foodnstuff');
    };

    " + + "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.

    ", TutorialTravelingText:"There are six major cities in the world that you are able to travel to:

    " + " Aevum
    " + diff --git a/src/HacknetNode.js b/src/HacknetNode.js index e9b926c11..0d0f42a9a 100644 --- a/src/HacknetNode.js +++ b/src/HacknetNode.js @@ -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(); diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index ee18b1ee8..0edc62139 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -351,8 +351,8 @@ function evaluate(exp, workerScript) { reject("|" + workerScript.serverIp + "|" + workerScript.name + "|grow() call has incorrect number of arguments. Takes 1 argument"); } 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"); @@ -393,6 +393,7 @@ function evaluate(exp, workerScript) { } 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"); @@ -438,6 +439,7 @@ function evaluate(exp, workerScript) { } 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"); @@ -479,6 +481,7 @@ function evaluate(exp, workerScript) { } 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"); @@ -520,6 +523,7 @@ function evaluate(exp, workerScript) { } 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"); @@ -561,6 +565,7 @@ function evaluate(exp, workerScript) { } 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"); @@ -602,6 +607,7 @@ function evaluate(exp, workerScript) { } 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"); @@ -638,7 +644,6 @@ function evaluate(exp, workerScript) { reject(e); }); } else if (exp.func.value == "run") { - console.log("run() called"); if (exp.args.length != 1) { reject("|"+workerScript.serverIp+"|"+workerScript.name+"|run() call has incorrect number of arguments. Takes 1 argument"); } @@ -661,12 +666,12 @@ function evaluate(exp, workerScript) { reject(e); }); } else if (exp.func.value == "getHackingLevel") { - console.log("getHackingLevel called"); if (exp.args.length != 0) { reject("|"+workerScript.serverIp+"|"+workerScript.name+"|getHackingLevel() call has incorrect number of arguments. Takes 0 arguments"); } setTimeout(function() { - console.log("About to resolve getHackingLevel"); + Player.updateSkillLevels(); + workerScript.scriptRef.log("getHackingLevel() returned " + Player.hacking_skill); resolve(Player.hacking_skill); }, CONSTANTS.CodeInstructionRunTime); } else if (exp.func.value == "getServerMoneyAvailable") { @@ -682,6 +687,7 @@ function evaluate(exp, workerScript) { 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) { @@ -926,12 +932,15 @@ function apply_op(op, a, b) { //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; } } @@ -957,6 +966,7 @@ function runScriptFromScript(server, scriptname, workerScript) { server.runningScripts.push(script.filename); //Push onto runningScripts addWorkerScript(script, server); resolve(true); + return; } } } diff --git a/src/NetscriptWorker.js b/src/NetscriptWorker.js index 4f57bb201..1076ced86 100644 --- a/src/NetscriptWorker.js +++ b/src/NetscriptWorker.js @@ -31,7 +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); + //console.log(ast); } catch (e) { dialogBoxCreate("Syntax ERROR in " + workerScripts[i].name + ":", e, "", ""); workerScripts[i].env.stopFlag = true; From 51c8e7a6c61ea9837d9fa658bdd3a025f0b5c335 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Mon, 15 May 2017 10:28:59 -0500 Subject: [PATCH 04/10] Fixed bug with loading game when working on creating program --- src/Constants.js | 2 +- src/NetscriptEvaluator.js | 13 +++++++++++++ src/Script.js | 1 + src/engine.js | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Constants.js b/src/Constants.js index 20e15606c..fd4c0c6ad 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -45,7 +45,7 @@ CONSTANTS = { ScriptRelaysmtpRamCost: 0.05, ScriptHttpwormRamCost: 0.05, ScriptSqlinjectRamCost: 0.05, - ScriptRunRamCost: 0.5, + ScriptRunRamCost: 0.75, ScriptGetHackingLevelRamCost: 0.1, ScriptGetServerMoneyRamCost: 0.1, diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index 0edc62139..12c11e081 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -225,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); @@ -306,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) { @@ -327,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) { @@ -349,6 +352,7 @@ 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) { @@ -390,6 +394,7 @@ 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) { @@ -436,6 +441,7 @@ 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) { @@ -478,6 +484,7 @@ 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) { @@ -520,6 +527,7 @@ 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) { @@ -562,6 +570,7 @@ 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) { @@ -604,6 +613,7 @@ 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) { @@ -646,6 +656,7 @@ function evaluate(exp, workerScript) { } 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) { @@ -653,6 +664,7 @@ function evaluate(exp, workerScript) { 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); @@ -668,6 +680,7 @@ function evaluate(exp, workerScript) { } 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(); diff --git a/src/Script.js b/src/Script.js index e86913312..4dc814dd1 100644 --- a/src/Script.js +++ b/src/Script.js @@ -164,6 +164,7 @@ Script.prototype.updateRamUsage = function() { 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) + diff --git a/src/engine.js b/src/engine.js index 5d7a4b400..087bc88d3 100644 --- a/src/engine.js +++ b/src/engine.js @@ -993,7 +993,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(); From bb73fe1101fc3e22b7ff28686b271957757d2967 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Mon, 15 May 2017 10:38:17 -0500 Subject: [PATCH 05/10] Operators now have RAM cost --- src/Constants.js | 1 + src/Script.js | 6 +++++- utils/StringHelperFunctions.js | 27 +++++++++++++++++++++++++-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/Constants.js b/src/Constants.js index fd4c0c6ad..346994bf3 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -48,6 +48,7 @@ CONSTANTS = { ScriptRunRamCost: 0.75, ScriptGetHackingLevelRamCost: 0.1, ScriptGetServerMoneyRamCost: 0.1, + ScriptOperatorRamCost: 0.01, //Server growth rate ServerGrowthRate: 1.00075, diff --git a/src/Script.js b/src/Script.js index 4dc814dd1..1654ec64b 100644 --- a/src/Script.js +++ b/src/Script.js @@ -180,8 +180,12 @@ Script.prototype.updateRamUsage = function() { (sqlinjectCount * CONSTANTS.ScriptSqlinjectRamCost) + (runCount * CONSTANTS.ScriptRunRamCost) + (getHackingLevelCount * CONSTANTS.ScriptGetHackingLevelRamCost) + - (getServerMoneyAvailableCount * CONSTANTS.ScriptGetServerMoneyRamCost)); + (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) { diff --git a/utils/StringHelperFunctions.js b/utils/StringHelperFunctions.js index d030e5d3e..873557bb0 100644 --- a/utils/StringHelperFunctions.js +++ b/utils/StringHelperFunctions.js @@ -81,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 += ""; @@ -97,4 +97,27 @@ function numOccurrences(string, subString) { } else break; } return n; -} \ No newline at end of file +} + +//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; +} From 56a7ed66a52946b0ab2f6229061abf7770e75de9 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Mon, 15 May 2017 11:54:23 -0500 Subject: [PATCH 06/10] Added status text for saving. Minor rebalancing for Hacknet Node RAM Cost --- css/styles.css | 30 ++++++++++++++++++++++++++++-- index.html | 5 +++++ src/Constants.js | 2 +- src/SaveObject.js | 3 +++ src/engine.js | 20 ++++++++++++++++++++ 5 files changed, 57 insertions(+), 3 deletions(-) diff --git a/css/styles.css b/css/styles.css index 64d8b63e3..53a3e59a6 100644 --- a/css/styles.css +++ b/css/styles.css @@ -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; -} \ No newline at end of file +} + +/* 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; +} diff --git a/index.html b/index.html index 3b30df5e3..6552f4cab 100644 --- a/index.html +++ b/index.html @@ -698,5 +698,10 @@ Back + +
    +

    +
    + \ No newline at end of file diff --git a/src/Constants.js b/src/Constants.js index 346994bf3..939af58e8 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -12,7 +12,7 @@ CONSTANTS = { /* Base costs */ BaseCostFor1GBOfRamHome: 50000, BaseCostFor1GBOfRamServer: 40000, //1 GB of RAM - BaseCostFor1GBOfRamHacknetNode: 25000, + BaseCostFor1GBOfRamHacknetNode: 30000, BaseCostForHacknetNode: 1000, BaseCostForHacknetNodeCore: 1000000, diff --git a/src/SaveObject.js b/src/SaveObject.js index d2c3ba532..f6cc92867 100644 --- a/src/SaveObject.js +++ b/src/SaveObject.js @@ -22,6 +22,8 @@ BitburnerSaveObject.prototype.saveGame = function() { var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this)))); window.localStorage.setItem("bitburnerSave", saveString); + + Engine.createStatusText("Game saved!"); } loadGame = function(saveObj) { @@ -45,6 +47,7 @@ BitburnerSaveObject.prototype.deleteGame = function() { if (window.localStorage.getItem("bitburnerSave")) { window.localStorage.removeItem("bitburnerSave"); } + Engine.createStatusText("Game deleted!"); } diff --git a/src/engine.js b/src/engine.js index 087bc88d3..1fc033daf 100644 --- a/src/engine.js +++ b/src/engine.js @@ -691,6 +691,21 @@ var Engine = { } }, + _prevTimeout: null, + createStatusText: function(txt) { + if (Engine._prevTimeout != null) { + clearTimeout(Engine._prevTimeout); + Engine._prevTimeout = null; + } + var statusText = document.getElementById("status-text") + statusText.setAttribute("class", "status-text"); + statusText.innerHTML = txt; + Engine._prevTimeout = setTimeout(function() { + statusText.removeAttribute("class"); + statusText.innerHTML = ""; + }, 3000); + }, + load: function() { //Load game from save or create new game if (loadGame(saveObject)) { @@ -729,6 +744,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"); From 7dfb102ba79011755e290b98d48ed7d5194ae123 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Mon, 15 May 2017 12:09:11 -0500 Subject: [PATCH 07/10] Rebalancing on RAM costs --- README.md | 25 ------------------------- src/Constants.js | 4 ++-- utils/PurchaseRamForHomeBox.js | 5 ++--- 3 files changed, 4 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index ba370f007..dcc18dfe2 100644 --- a/README.md +++ b/README.md @@ -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 @@ -57,11 +38,5 @@ 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 - - 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 \ No newline at end of file diff --git a/src/Constants.js b/src/Constants.js index 939af58e8..d38c004a7 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -10,8 +10,8 @@ CONSTANTS = { CorpFactionRepRequirement: 250000, /* Base costs */ - BaseCostFor1GBOfRamHome: 50000, - BaseCostFor1GBOfRamServer: 40000, //1 GB of RAM + BaseCostFor1GBOfRamHome: 40000, + BaseCostFor1GBOfRamServer: 35000, //1 GB of RAM BaseCostFor1GBOfRamHacknetNode: 30000, BaseCostForHacknetNode: 1000, diff --git a/utils/PurchaseRamForHomeBox.js b/utils/PurchaseRamForHomeBox.js index 898e2fc99..a382e3d44 100644 --- a/utils/PurchaseRamForHomeBox.js +++ b/utils/PurchaseRamForHomeBox.js @@ -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?

    " + From bf1469ce151fa4be8273041119be05bb5074782c Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Mon, 15 May 2017 12:23:20 -0500 Subject: [PATCH 08/10] Updated version --- src/Constants.js | 2 +- src/SaveObject.js | 1 + src/engine.js | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Constants.js b/src/Constants.js index d38c004a7..81bf25d23 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -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 diff --git a/src/SaveObject.js b/src/SaveObject.js index f6cc92867..06470ff97 100644 --- a/src/SaveObject.js +++ b/src/SaveObject.js @@ -23,6 +23,7 @@ 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!"); } diff --git a/src/engine.js b/src/engine.js index 1fc033daf..ddfaac31e 100644 --- a/src/engine.js +++ b/src/engine.js @@ -698,9 +698,11 @@ var Engine = { 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); From bf0d5589e50b3dcaba4014e52d31fd88e3f6874e Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Mon, 15 May 2017 12:28:25 -0500 Subject: [PATCH 09/10] Showing that Delete Active Scripts button is for debugging --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 6552f4cab..4c59c12bb 100644 --- a/index.html +++ b/index.html @@ -114,7 +114,7 @@
  • - Delete Active Scripts + (DEBUG) Delete Active Scripts
  • From 238cd893764bec28ba4c4c8bfa9b43ccb2b121c0 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Mon, 15 May 2017 12:49:49 -0500 Subject: [PATCH 10/10] Harakiri sushi no longer needs ports opened. Updated tutorial doc --- src/Constants.js | 12 +++++++----- src/Player.js | 2 +- src/Server.js | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Constants.js b/src/Constants.js index 81bf25d23..8ee2175db 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -273,12 +273,12 @@ 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

    " + "

    For loops


    " + - "A for loop is another control flow statement that allows code to by repeated by iterations. The structure is:

    " + + "A for loop is another control flow statement that allows code to be repeated by iterations. The structure is:

    " + "for ([init]; [cond]; [post]) {
        code
    };


    " + "The [init] expression evaluates before the for loop begins. The for loop will continue to execute " + "as long as [cond] is met. The [post] 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:

    " + + "of the for loop. The following example shows code that will run the 'hack('foodnstuff');' command 10 times " + + " using a for loop:

    " + "for (i = 0; i < 10; i = i+1) {
        hack('foodnstuff');
    };


    " + "

    If statements


    " + "If/Elif/Else statements are conditional statements used to perform different actions based on different conditions:

    " + @@ -322,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.

    " + + "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.

    " + "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.", diff --git a/src/Player.js b/src/Player.js index cbcda55ef..c8c734a0d 100644 --- a/src/Player.js +++ b/src/Player.js @@ -585,7 +585,7 @@ PlayerObject.prototype.finishWorkPartTime = function() { formatNumber(this.workDexExpGained, 4) + " dexterity exp
    " + formatNumber(this.workAgiExpGained, 4) + " agility exp
    " + formatNumber(this.workChaExpGained, 4) + " charisma exp
    "; - txt = "You worked for " + convertTimeMsToTimeElapsedString(this.timeWorked) + ".

    " + txt; + txt = "You worked for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "

    " + txt; dialogBoxCreate(txt); var mainMenu = document.getElementById("mainmenu-container"); diff --git a/src/Server.js b/src/Server.js index 165765dee..c1ed2b985 100644 --- a/src/Server.js +++ b/src/Server.js @@ -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();