From 8eb0809d905771b6563393ea8bd5fbd367987fef Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Tue, 23 May 2017 15:20:28 -0500 Subject: [PATCH 01/16] Formatted number in TravelBox. Upgrading Core on Hacknet node even more expensive --- src/Constants.js | 2 +- utils/TravelBox.js | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Constants.js b/src/Constants.js index 738c3ae4d..f39488ae6 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -22,7 +22,7 @@ CONSTANTS = { HacknetNodePurchaseNextMult: 1.33, //Multiplier when purchasing an additional hacknet node HacknetNodeUpgradeLevelMult: 1.04, //Multiplier for cost when upgrading level HacknetNodeUpgradeRamMult: 1.22, //Multiplier for cost when upgrading RAM - HacknetNodeUpgradeCoreMult: 1.42, //Multiplier for cost when buying another core + HacknetNodeUpgradeCoreMult: 1.45, //Multiplier for cost when buying another core HacknetNodeMaxLevel: 200, HacknetNodeMaxRam: 64, diff --git a/utils/TravelBox.js b/utils/TravelBox.js index 89232d2f8..5fefbb2da 100644 --- a/utils/TravelBox.js +++ b/utils/TravelBox.js @@ -27,13 +27,10 @@ travelBoxSetText = function(txt) { } travelBoxCreate = function(destCityName, cost) { - travelBoxSetText("Would you like to travel to " + destCityName + "? The trip will cost $" + cost + "."); + travelBoxSetText("Would you like to travel to " + destCityName + "? The trip will cost $" + formatNumber(cost, 2) + "."); //Clear old event listeners from Confirm button var newConfirmButton = clearEventListeners("travel-box-confirm"); - //var confirmButton = document.getElementById("travel-box-confirm"); - //var newConfirmButton = confirmButton.cloneNode(true); - //confirmButton.parentNode.replaceChild(newConfirmButton, confirmButton); newConfirmButton.addEventListener("click", function() { travelBoxClose(); travelToCity(destCityName, cost); From 1a116c75ea182448a41b41b24034bd9e5407c0e3 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Tue, 23 May 2017 16:53:42 -0500 Subject: [PATCH 02/16] Adding .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..4147856a2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +Changelog.txt +Netburner.txt +README.md \ No newline at end of file From 5d415a1a601776044d2ddb595d10bc854ef4ef6b Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Tue, 23 May 2017 21:55:24 -0500 Subject: [PATCH 03/16] Fix bug with purchaseHacknetNode(). Improve nano interface --- css/menupages.css | 68 +++++++++++++++++++++++++++++---------- index.html | 20 ++++++------ src/NetscriptEvaluator.js | 1 + 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/css/menupages.css b/css/menupages.css index 79adcc1cb..3337b8e2b 100644 --- a/css/menupages.css +++ b/css/menupages.css @@ -30,18 +30,25 @@ overflow-y: scroll; } -#script-editor-filename-tag { - padding-top: 10px; - padding-bottom: 0px; - float: left; +#script-editor-buttons-wrapper { + width: 100%; + padding-right: 0xp; + margin-right: 0px; } #script-editor-save-and-close-button, +#script-editor-netscript-doc-button { + display: inline-block; +} + +#script-editor-save-and-close-button { + float:left; +} + #script-editor-netscript-doc-button { float: right; - display: block; - width: 50%; - margin-right: 25%; + padding-right: 0px; + margin-right: 2px; } #script-editor-netscript-doc-warning { @@ -52,13 +59,37 @@ background-color: #666; } +#script-editor-wrapper { + height:100%; + width: 70%; +} + +#script-editor-filename-wrapper { + background-color: #555; + margin-left: 6px; + margin-right: 0px; + padding-left: 6px; + width: 100%; + border: 2px solid white; +} + +#script-editor-filename-tag { + display: inline-block; + padding-top: 10px; + padding-bottom: 0px; + float:center; + background-color: #555; +} + #script-editor-filename { - float: left; +background-color: #555; + display: inline-block; + float: center; resize: none; - color: #66ff33; - width: 70%; - margin: 10px; - padding: 5px; + color: white; + margin: 4px; + + padding: 2px; border: 2px solid white; -webkit-box-shadow: @@ -79,11 +110,14 @@ #script-editor-text { color: #66ff33; - width: 70%; - height: 100%; - margin: 10px; - padding: 5px; - + height: 80%; + width: 100%; + margin-left: 6px; + + padding-left: 6px; + padding-top: 6px; + padding-bottom: 6px; + border: 2px solid white; -webkit-box-shadow: inset 0 0 8px rgba(0,0,0,0.1), diff --git a/index.html b/index.html index 8daf76b08..eb4297c24 100644 --- a/index.html +++ b/index.html @@ -143,17 +143,19 @@
-
-

Script name:

- Save & Close (Ctrl + b) - Netscript Documentation -

Warning: You will lose unsaved content!

+
+
+

Script name:

+
- - -
-

+
+ Save & Close (Ctrl + b) + Netscript Documentation +

Warning: You will lose unsaved content!

+
+
+



diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index dc7938737..2b2578591 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -755,6 +755,7 @@ function evaluate(exp, workerScript) { Player.loseMoney(cost); Player.hacknetNodes.push(node); + displayHacknetNodesContent(); workerScript.scriptRef.log("Purchased new Hacknet Node with name: " + name); resolve(name); }, CONSTANTS.CodeInstructionRunTime); From f756f09dbe3985751bce124c3470f74e99a42689 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Wed, 24 May 2017 00:05:31 -0500 Subject: [PATCH 04/16] Player starts with 8GB of RAM on home. scan-analyze displays RAM. Increased percentage money hacked --- src/Constants.js | 4 ++-- src/HacknetNode.js | 2 +- src/NetscriptEvaluator.js | 3 ++- src/Player.js | 4 ++-- src/Terminal.js | 3 ++- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Constants.js b/src/Constants.js index f39488ae6..27c12558d 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -15,10 +15,10 @@ CONSTANTS = { BaseCostFor1GBOfRamHacknetNode: 30000, BaseCostForHacknetNode: 1000, - BaseCostForHacknetNodeCore: 400000, + BaseCostForHacknetNodeCore: 500000, /* Hacknet Node constants */ - HacknetNodeMoneyGainPerLevel: 1.25, + HacknetNodeMoneyGainPerLevel: 1.5, HacknetNodePurchaseNextMult: 1.33, //Multiplier when purchasing an additional hacknet node HacknetNodeUpgradeLevelMult: 1.04, //Multiplier for cost when upgrading level HacknetNodeUpgradeRamMult: 1.22, //Multiplier for cost when upgrading RAM diff --git a/src/HacknetNode.js b/src/HacknetNode.js index 5224e5017..42f2fb507 100644 --- a/src/HacknetNode.js +++ b/src/HacknetNode.js @@ -50,7 +50,7 @@ HacknetNode.prototype.updateMoneyGainRate = function() { this.moneyGainRatePerSecond = (this.level * gainPerLevel) * Math.pow(1.04, this.ram-1) * - ((this.numCores + 1) / 2) * Player.hacknet_node_money_mult; + ((this.numCores + 3) / 4) * Player.hacknet_node_money_mult; if (isNaN(this.moneyGainRatePerSecond)) { this.moneyGainRatePerSecond = 0; dialogBoxCreate("Error in calculating Hacknet Node production. Please report to game developer"); diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index 2b2578591..d44cbc111 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -745,6 +745,7 @@ function evaluate(exp, workerScript) { if (cost > Player.money) { workerScript.scriptRef.log("Could not afford to purchase new Hacknet Node"); resolve(""); + return; } //Auto generate a name for the node for now...TODO @@ -1127,7 +1128,7 @@ function scriptCalculateExpGain(server) { function scriptCalculatePercentMoneyHacked(server) { var difficultyMult = (100 - server.hackDifficulty) / 100; var skillMult = (Player.hacking_skill - (server.requiredHackingSkill - 1)) / Player.hacking_skill; - var percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / 950; + var percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / 875; if (percentMoneyHacked < 0) {return 0;} if (percentMoneyHacked > 1) {return 1;} return percentMoneyHacked; diff --git a/src/Player.js b/src/Player.js index 886dda5a9..74e53b11d 100644 --- a/src/Player.js +++ b/src/Player.js @@ -176,7 +176,7 @@ function PlayerObject() { PlayerObject.prototype.init = function() { /* Initialize Player's home computer */ var t_homeComp = new Server(); - t_homeComp.init(createRandomIp(), "home", "Home PC", true, true, true, true, 2); + t_homeComp.init(createRandomIp(), "home", "Home PC", true, true, true, true, 8); this.homeComputer = t_homeComp.ip; this.currentServer = t_homeComp.ip; AddToAllServers(t_homeComp); @@ -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 / 950; + var percentMoneyHacked = difficultyMult * skillMult * this.hacking_money_mult / 875; console.log("Percent money hacked calculated to be: " + percentMoneyHacked); if (percentMoneyHacked < 0) {return 0;} if (percentMoneyHacked > 1) {return 1;} diff --git a/src/Terminal.js b/src/Terminal.js index 7c7d707e0..f6fdb3afe 100644 --- a/src/Terminal.js +++ b/src/Terminal.js @@ -851,7 +851,8 @@ var Terminal = { if (serv.hasAdminRights) {c = "Y";} post("--Root Access: " + c); post("--Required hacking skill: " + serv.requiredHackingSkill); - post("--Number open ports required to NUKE: " + serv.numOpenPortsRequired); + post("--Number of open ports required to NUKE: " + serv.numOpenPortsRequired); + post("--RAM: " + serv.maxRam); post(" "); } }, From 5c1675990864b8154afbdc348c868b0955a46cf8 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Wed, 24 May 2017 08:49:52 -0500 Subject: [PATCH 05/16] Clicking outisde popup dialog box closes it. Grow() time is now based on hacking level --- css/popupboxes.css | 3 ++- index.html | 2 +- src/NetscriptEvaluator.js | 19 +++++++++++++++---- src/Terminal.js | 9 --------- utils/DialogBox.js | 17 ++++++++++++++++- 5 files changed, 34 insertions(+), 16 deletions(-) diff --git a/css/popupboxes.css b/css/popupboxes.css index c6ced2ff6..75a8514d7 100644 --- a/css/popupboxes.css +++ b/css/popupboxes.css @@ -4,7 +4,7 @@ #dialog-box-container { display: none; /* Hidden by default */ position: fixed; /* Stay in place */ - z-index: 1; /* Sit on top */ + z-index: 2; /* Sit on top */ left: 0; top: 0; width: 100%; /* Full width */ @@ -15,6 +15,7 @@ } #dialog-box-content { + z-index: 2; background-color: black; margin: 20% auto; /* 20% from the top and centered */ padding: 10px; diff --git a/index.html b/index.html index eb4297c24..ad77e36cd 100644 --- a/index.html +++ b/index.html @@ -635,7 +635,7 @@
-
+
×


diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index d44cbc111..4f2d4108a 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -371,14 +371,17 @@ function evaluate(exp, workerScript) { return; } - workerScript.scriptRef.log("Calling grow() on server " + server.hostname + " in 120 seconds"); + 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"); + var p = new Promise(function(resolve, reject) { if (env.stopFlag) {reject(workerScript);} setTimeout(function() { server.moneyAvailable += 1; //It can be grown even if it has no money var growthPercentage = processSingleServerGrowth(server, 450); resolve(growthPercentage); - }, 120 * 1000); //grow() takes flat 2 minutes right now + }, growTime); }); p.then(function(growthPercentage) { @@ -1104,9 +1107,9 @@ function isScriptErrorMessage(msg) { //The same as Player's calculateHackingChance() function but takes in the server as an argument function scriptCalculateHackingChance(server) { var difficultyMult = (100 - server.hackDifficulty) / 100; - var skillMult = (2 * Player.hacking_chance_mult * Player.hacking_skill); + var skillMult = (2 * Player.hacking_skill); var skillChance = (skillMult - server.requiredHackingSkill) / skillMult; - var chance = skillChance * difficultyMult; + var chance = skillChance * difficultyMult * Player.hacking_chance_mult; if (chance < 0) {return 0;} else {return chance;} } @@ -1132,4 +1135,12 @@ function scriptCalculatePercentMoneyHacked(server) { if (percentMoneyHacked < 0) {return 0;} if (percentMoneyHacked > 1) {return 1;} return percentMoneyHacked; +} + +//Amount of time to execute grow() +function scriptCalculateGrowTime(server) { + var difficultyMult = server.requiredHackingSkill * server.hackDifficulty; + var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50); + var growTime = skillFactor * 20; //This is in seconds + return growTime * 1000; } \ No newline at end of file diff --git a/src/Terminal.js b/src/Terminal.js index f6fdb3afe..7606f439d 100644 --- a/src/Terminal.js +++ b/src/Terminal.js @@ -27,15 +27,6 @@ var postNetburnerText = function() { post("Bitburner v" + CONSTANTS.Version); } -/* -$(document).keyup(function(event) { - //Enter - if (event.keyCode == 13) { - - } -}); -*/ - //Defines key commands in terminal $(document).keydown(function(event) { //Terminal diff --git a/utils/DialogBox.js b/utils/DialogBox.js index ebb443a54..b483fc600 100644 --- a/utils/DialogBox.js +++ b/utils/DialogBox.js @@ -1,7 +1,17 @@ /* Pop up Dialog Box */ + +//Close dialog box when clicking outside +$(document).click(function(event) { + if (dialogBoxOpened) { + if ( $(event.target).closest(".dialog-box").get(0) == null ) { + dialogBoxClose(); + } + } +}); + +var dialogBoxOpened = false; function dialogBoxInit() { var closeButton = document.getElementById("dialog-box-close-button"); - var dialogBox = document.getElementById("dialog-box-container"); //Close Dialog box closeButton.addEventListener("click", function() { @@ -13,6 +23,7 @@ function dialogBoxInit() { document.addEventListener("DOMContentLoaded", dialogBoxInit, false); dialogBoxClose = function() { + dialogBoxOpened = false; var dialogBox = document.getElementById("dialog-box-container"); dialogBox.style.display = "none"; } @@ -20,6 +31,10 @@ dialogBoxClose = function() { dialogBoxOpen = function() { var dialogBox = document.getElementById("dialog-box-container"); dialogBox.style.display = "block"; + setTimeout(function() { + dialogBoxOpened = true; + }, 500); + } dialogBoxSetText = function(txt1, txt2="", txt3="", txt4="") { From d00211a4ff312855e0eecf42f2bd9289862b2f77 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Wed, 24 May 2017 10:32:45 -0500 Subject: [PATCH 06/16] Buffed base production of Hacknet Nodes. Re-calibrated hacker faction invites to account for starting with 8GB of RAM. BruteSSH only takes 10 minutes at most to complete now --- src/Constants.js | 5 ++++- src/Faction.js | 6 +++--- src/NetscriptEvaluator.js | 2 +- src/engine.js | 8 ++++---- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Constants.js b/src/Constants.js index 27c12558d..c95a12c58 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -18,7 +18,7 @@ CONSTANTS = { BaseCostForHacknetNodeCore: 500000, /* Hacknet Node constants */ - HacknetNodeMoneyGainPerLevel: 1.5, + HacknetNodeMoneyGainPerLevel: 1.75, HacknetNodePurchaseNextMult: 1.33, //Multiplier when purchasing an additional hacknet node HacknetNodeUpgradeLevelMult: 1.04, //Multiplier for cost when upgrading level HacknetNodeUpgradeRamMult: 1.22, //Multiplier for cost when upgrading RAM @@ -88,6 +88,9 @@ CONSTANTS = { MillisecondsPerQuarterHour: 900000, GameCyclesPerQuarterHour: 900000 / 200, + MillisecondsPerFiveMinutes: 300000, + GameCyclesPerFiveMinutes: 300000 / 200, + FactionWorkHacking: "Faction Hacking Work", FactionWorkField: "Faction Field Work", FactionWorkSecurity: "Faction Security Work", diff --git a/src/Faction.js b/src/Faction.js index 5a463d28f..5c7e998ec 100644 --- a/src/Faction.js +++ b/src/Faction.js @@ -305,7 +305,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() { var bitrunnersFac = Factions["BitRunners"]; var homeComp = Player.getHomeComputer(); if (bitrunnersFac.isBanned == false && bitrunnersFac.isMember == false && - this.hacking_skill >= 600 && homeComp.maxRam >= 32) { + this.hacking_skill >= 600 && homeComp.maxRam >= 128) { invitedFactions.push(bitrunnersFac); } @@ -313,14 +313,14 @@ PlayerObject.prototype.checkForFactionInvitations = function() { var theblackhandFac = Factions["The Black Hand"]; if (theblackhandFac.isBanned == false && theblackhandFac.isMember == false && this.hacking_skill >= 400 && this.strength >= 200 && this.defense >= 200 && - this.agility >= 200 && this.dexterity >= 200 && homeComp.maxRam >= 16) { + this.agility >= 200 && this.dexterity >= 200 && homeComp.maxRam >= 64) { invitedFactions.push(theblackhandFac); } //NiteSec var nitesecFac = Factions["NiteSec"]; if (nitesecFac.isBanned == false && nitesecFac.isMember == false && - this.hacking_skill >= 200 && homeComp.maxRam >= 8) { + this.hacking_skill >= 200 && homeComp.maxRam >= 32) { invitedFactions.push(nitesecFac); } diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index 4f2d4108a..bd881f0c6 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -1141,6 +1141,6 @@ function scriptCalculatePercentMoneyHacked(server) { function scriptCalculateGrowTime(server) { var difficultyMult = server.requiredHackingSkill * server.hackDifficulty; var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50); - var growTime = skillFactor * 20; //This is in seconds + var growTime = skillFactor * 16; //This is in seconds return growTime * 1000; } \ No newline at end of file diff --git a/src/engine.js b/src/engine.js index ada971d6c..8b3aa1e92 100644 --- a/src/engine.js +++ b/src/engine.js @@ -999,17 +999,17 @@ var Engine = { }); //Create Program buttons - var portHackALink = document.getElementById("create-program-nuke"); + var nukeALink = document.getElementById("create-program-nuke"); var bruteSshALink = document.getElementById("create-program-brutessh"); var ftpCrackALink = document.getElementById("create-program-ftpcrack"); var relaySmtpALink = document.getElementById("create-program-relaysmtp"); var httpWormALink = document.getElementById("create-program-httpworm"); var sqlInjectALink = document.getElementById("create-program-sqlinject"); - portHackALink.addEventListener("click", function() { - Player.startCreateProgramWork(Programs.NukeProgram, CONSTANTS.MillisecondsPerQuarterHour, 1); + nukeALink.addEventListener("click", function() { + Player.startCreateProgramWork(Programs.NukeProgram, CONSTANTS.MillisecondsPerFiveMinutes, 1); }); bruteSshALink.addEventListener("click", function() { - Player.startCreateProgramWork(Programs.BruteSSHProgram, CONSTANTS.MillisecondsPerQuarterHour, 50); + Player.startCreateProgramWork(Programs.BruteSSHProgram, CONSTANTS.MillisecondsPerFiveMinutes * 2, 50); }); ftpCrackALink.addEventListener("click", function() { Player.startCreateProgramWork(Programs.FTPCrackProgram, CONSTANTS.MillisecondsPerHalfHour, 100); From 3771e00d1f9748b276bf57cd4d965bbe33420325 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Wed, 24 May 2017 10:34:22 -0500 Subject: [PATCH 07/16] Iron-gym and Max-hardware servers now have 2GB of RAM --- src/Server.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Server.js b/src/Server.js index e7b523b02..83b875b05 100644 --- a/src/Server.js +++ b/src/Server.js @@ -462,7 +462,7 @@ initForeignServers = function() { AddToAllServers(PhantasyServer); var MaxHardwareServer = new Server(); - MaxHardwareServer.init(createRandomIp(), "max-hardware", "Max Hardware Store", true, false, false, false, 0); + MaxHardwareServer.init(createRandomIp(), "max-hardware", "Max Hardware Store", true, false, false, false, 2); MaxHardwareServer.setHackingParameters(80, 11000000, 15, 25); MaxHardwareServer.setPortProperties(1); AddToAllServers(MaxHardwareServer); @@ -481,7 +481,7 @@ initForeignServers = function() { AddToAllServers(CrushFitnessGymServer); var IronGymServer = new Server(); - IronGymServer.init(createRandomIp(), "iron-gym", "Iron Gym Network", true, false, false, false, 0); + IronGymServer.init(createRandomIp(), "iron-gym", "Iron Gym Network", true, false, false, false, 2); IronGymServer.setHackingParameters(100, 20000000, 30, 20); IronGymServer.setPortProperties(1); AddToAllServers(IronGymServer); From 60cfdd3aa1f364aec9ffa5bbbe71b3dc37ebb64c Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Wed, 24 May 2017 10:50:19 -0500 Subject: [PATCH 08/16] Buffed job salaries across the board --- src/Company.js | 62 +++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/Company.js b/src/Company.js index 2248dd3c9..58f76a256 100644 --- a/src/Company.js +++ b/src/Company.js @@ -223,58 +223,58 @@ CompanyPositions = { //Constructor: CompanyPosition(name, reqHack, reqStr, reqDef, reqDex, reqAgi, reqCha, reqRep, salary) //Software - SoftwareIntern: new CompanyPosition("Software Engineering Intern", 1, 0, 0, 0, 0, 0, 0, 8), - JuniorDev: new CompanyPosition("Junior Software Engineer", 51, 0, 0, 0, 0, 0, 8000, 20), - SeniorDev: new CompanyPosition("Senior Software Engineer", 251, 0, 0, 0, 0, 51, 32000, 40), - LeadDev: new CompanyPosition("Lead Software Developer", 401, 0, 0, 0, 0, 151, 144000, 120), + SoftwareIntern: new CompanyPosition("Software Engineering Intern", 1, 0, 0, 0, 0, 0, 0, 12), + JuniorDev: new CompanyPosition("Junior Software Engineer", 51, 0, 0, 0, 0, 0, 8000, 25), + SeniorDev: new CompanyPosition("Senior Software Engineer", 251, 0, 0, 0, 0, 51, 32000, 50), + LeadDev: new CompanyPosition("Lead Software Developer", 401, 0, 0, 0, 0, 151, 144000, 150), //TODO Through darkweb, maybe? FreelanceDeveloper: new CompanyPosition("Freelance Developer", 0, 0, 0, 0, 0, 0, 0, 0), - SoftwareConsultant: new CompanyPosition("Software Consultant", 51, 0, 0, 0, 0, 0, 0, 15), - SeniorSoftwareConsultant: new CompanyPosition("Senior Software Consultant", 251, 0, 0, 0, 0, 51, 0, 30), + SoftwareConsultant: new CompanyPosition("Software Consultant", 51, 0, 0, 0, 0, 0, 0, 16), + SeniorSoftwareConsultant: new CompanyPosition("Senior Software Consultant", 251, 0, 0, 0, 0, 51, 0, 32), //IT - ITIntern: new CompanyPosition("IT Intern", 1, 0, 0, 0, 0, 0, 0, 1.75), - ITAnalyst: new CompanyPosition("IT Analyst", 26, 0, 0, 0, 0, 0, 6000, 7.5), + ITIntern: new CompanyPosition("IT Intern", 1, 0, 0, 0, 0, 0, 0, 10), + ITAnalyst: new CompanyPosition("IT Analyst", 26, 0, 0, 0, 0, 0, 6000, 20), ITManager: new CompanyPosition("IT Manager", 151, 0, 0, 0, 0, 51, 24000, 35), SysAdmin: new CompanyPosition("Systems Administrator", 251, 0, 0, 0, 0, 76, 120000, 100), - SecurityEngineer: new CompanyPosition("Security Engineer", 151, 0, 0, 0, 0, 26, 28000, 35), - NetworkEngineer: new CompanyPosition("Network Engineer", 151, 0, 0, 0, 0, 26, 28000, 35), + SecurityEngineer: new CompanyPosition("Security Engineer", 151, 0, 0, 0, 0, 26, 28000, 38), + NetworkEngineer: new CompanyPosition("Network Engineer", 151, 0, 0, 0, 0, 26, 28000, 38), NetworkAdministrator: new CompanyPosition("Network Administrator", 251, 0, 0, 0, 0, 76, 120000, 100), //Technology management - HeadOfSoftware: new CompanyPosition("Head of Software", 501, 0, 0, 0, 0, 251, 288000, 250), - HeadOfEngineering: new CompanyPosition("Head of Engineering", 501, 0, 0, 0, 0, 251, 576000, 400), - VicePresident: new CompanyPosition("Vice President of Technology", 601, 0, 0, 0, 0, 401, 1152000, 600), - CTO: new CompanyPosition("Chief Technology Officer", 751, 0, 0, 0, 0, 501, 4608000, 750), + HeadOfSoftware: new CompanyPosition("Head of Software", 501, 0, 0, 0, 0, 251, 288000, 275), + HeadOfEngineering: new CompanyPosition("Head of Engineering", 501, 0, 0, 0, 0, 251, 576000, 500), + VicePresident: new CompanyPosition("Vice President of Technology", 601, 0, 0, 0, 0, 401, 1152000, 750), + CTO: new CompanyPosition("Chief Technology Officer", 751, 0, 0, 0, 0, 501, 4608000, 900), //Business - BusinessIntern: new CompanyPosition("Business Intern", 1, 0, 0, 0, 0, 1, 0, 10), - BusinessAnalyst: new CompanyPosition("Business Analyst", 6, 0, 0, 0, 0, 51, 8000, 25), - BusinessManager: new CompanyPosition("Business Manager", 51, 0, 0, 0, 0, 101, 32000, 60), - OperationsManager: new CompanyPosition("Operations Manager", 51, 0, 0, 0, 0, 226, 144000, 180), - CFO: new CompanyPosition("Chief Financial Officer", 76, 0, 0, 0, 0, 501, 576000, 600), - CEO: new CompanyPosition("Chief Executive Officer", 101, 0, 0, 0, 0, 751, 4608000, 1000), + BusinessIntern: new CompanyPosition("Business Intern", 1, 0, 0, 0, 0, 1, 0, 13), + BusinessAnalyst: new CompanyPosition("Business Analyst", 6, 0, 0, 0, 0, 51, 8000, 32), + BusinessManager: new CompanyPosition("Business Manager", 51, 0, 0, 0, 0, 101, 32000, 75), + OperationsManager: new CompanyPosition("Operations Manager", 51, 0, 0, 0, 0, 226, 144000, 220), + CFO: new CompanyPosition("Chief Financial Officer", 76, 0, 0, 0, 0, 501, 576000, 675), + CEO: new CompanyPosition("Chief Executive Officer", 101, 0, 0, 0, 0, 751, 4608000, 1100), - BusinessConsultant: new CompanyPosition("Business Consultant", 6, 0, 0, 0, 0, 51, 0, 18), - SeniorBusinessConsultant: new CompanyPosition("Senior Business Consultant", 51, 0, 0, 0, 0, 226, 0, 135), + BusinessConsultant: new CompanyPosition("Business Consultant", 6, 0, 0, 0, 0, 51, 0, 21), + SeniorBusinessConsultant: new CompanyPosition("Senior Business Consultant", 51, 0, 0, 0, 0, 226, 0, 150), //Non-tech/management jobs - PartTimeWaiter: new CompanyPosition("Part-time Waiter", 0, 0, 0, 0, 0, 0, 0, 6), - PartTimeEmployee: new CompanyPosition("Part-time Employee", 0, 0, 0, 0, 0, 0, 0, 6), + PartTimeWaiter: new CompanyPosition("Part-time Waiter", 0, 0, 0, 0, 0, 0, 0, 7), + PartTimeEmployee: new CompanyPosition("Part-time Employee", 0, 0, 0, 0, 0, 0, 0, 7), Waiter: new CompanyPosition("Waiter", 0, 0, 0, 0, 0, 0, 0, 9), Employee: new CompanyPosition("Employee", 0, 0, 0, 0, 0, 0, 0, 9), - PoliceOfficer: new CompanyPosition("Police Officer", 11, 101, 101, 101, 101, 51, 8000, 25), - PoliceChief: new CompanyPosition("Police Chief", 101, 301, 301, 301, 301, 151, 32000, 100), + PoliceOfficer: new CompanyPosition("Police Officer", 11, 101, 101, 101, 101, 51, 8000, 28), + PoliceChief: new CompanyPosition("Police Chief", 101, 301, 301, 301, 301, 151, 32000, 110), SecurityGuard: new CompanyPosition("Security Guard", 0, 51, 51, 51, 51, 1, 0, 16), - SecurityOfficer: new CompanyPosition("Security Officer", 26, 151, 151, 151, 151, 51, 8000, 40), - SecuritySupervisor: new CompanyPosition("Security Supervisor", 26, 251, 251, 251, 251, 101, 32000, 80), + SecurityOfficer: new CompanyPosition("Security Officer", 26, 151, 151, 151, 151, 51, 8000, 50), + SecuritySupervisor: new CompanyPosition("Security Supervisor", 26, 251, 251, 251, 251, 101, 32000, 100), HeadOfSecurity: new CompanyPosition("Head of Security", 51, 501, 501, 501, 501, 151, 144000, 250), - FieldAgent: new CompanyPosition("Field Agent", 101, 101, 101, 101, 101, 101, 8000, 30), - SecretAgent: new CompanyPosition("Secret Agent", 201, 251, 251, 251, 251, 32000, 120), - SpecialOperative: new CompanyPosition("Special Operative", 251, 501, 501, 501, 501, 144000, 300), + FieldAgent: new CompanyPosition("Field Agent", 101, 101, 101, 101, 101, 101, 8000, 40), + SecretAgent: new CompanyPosition("Secret Agent", 201, 251, 251, 251, 251, 32000, 150), + SpecialOperative: new CompanyPosition("Special Operative", 251, 501, 501, 501, 501, 144000, 375), init: function() { //Argument order: hack, str, def, dex, agi, cha From 0fcde41a873293e0c56a597fa1f800d5a528de3f Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Wed, 24 May 2017 12:07:33 -0500 Subject: [PATCH 09/16] scan-analyze now properly works with depth using DFS. The formatting of the otuput needs to be improved --- src/Terminal.js | 49 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/src/Terminal.js b/src/Terminal.js index 7606f439d..c4877b55f 100644 --- a/src/Terminal.js +++ b/src/Terminal.js @@ -724,7 +724,18 @@ var Terminal = { Terminal.executeScanCommand(commandArray); break; case "scan-analyze": - Terminal.executeScanAnalyzeCommand(commandArray); + if (commandArray.length == 1) { + Terminal.executeScanAnalyzeCommand(1); + } else if (commandArray.length == 2) { + var depth = Number(commandArray[1]); + if (isNaN(depth)) { + post("Incorrect usage of scan-analyze command. depth argument must be numeric"); + return; + } + Terminal.executeScanAnalyzeCommand(depth); + } else { + post("Incorrect usage of scan-analyze command. usage: scan-analyze [depth]"); + } break; case "scp": //TODO @@ -829,10 +840,39 @@ var Terminal = { } }, - executeScanAnalyzeCommand: function(commandArray) { - if (commandArray.length != 1) { - post("Incorrect usage of scan-analyze command. usage: scan-analyze"); return; + executeScanAnalyzeCommand: function(depth=1) { + //We'll use the AllServersToMoneyMap as a visited() array + //TODO Later refactor this to a generic name + //TODO Using array as stack for now, can make more efficient + var visited = new AllServersToMoneyMap(); + var stack = []; + var depthQueue = [0]; + var currServ = Player.getCurrentServer(); + stack.push(currServ); + while(stack.length != 0) { + var s = stack.pop(); + var d = depthQueue.pop(); + if (visited[s.ip] || d > depth) { + continue; + } else { + visited[s.ip] = 1; + } + for (var i = s.serversOnNetwork.length-1; i >= 0; --i) { + stack.push(s.getServerOnNetwork(i)); + depthQueue.push(d+1); + } + if (d == 0) {continue;} //Don't print current server + var titleNumDashes = Array((d-1) * 2 + 1).join("-"); + post("" + titleNumDashes + s.hostname + ""); + var numDashes = Array(d * 2 + 1).join("-"); + var c = "N"; + if (s.hasAdminRights) {c = "Y";} + post(numDashes + "Root Access: " + c); + post(numDashes + "Required hacking skill: " + s.requiredHackingSkill); + post(numDashes + "Number of open ports required to NUKE: " + s.numOpenPortsRequired); + post(numDashes + "RAM: " + s.maxRam); } + /* var currServ = Player.getCurrentServer(); for (var i = 0; i < currServ.serversOnNetwork.length; ++i) { var serv = currServ.getServerOnNetwork(i); @@ -846,6 +886,7 @@ var Terminal = { post("--RAM: " + serv.maxRam); post(" "); } + */ }, executeFreeCommand: function(commandArray) { From 84eb2955277634d1af01cdc0c1ca91f8f66b2c3e Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Wed, 24 May 2017 16:35:24 -0500 Subject: [PATCH 10/16] Added functionality to create Deepscan programs. Untested --- index.html | 10 +++++++++ src/CreateProgram.js | 37 ++++++++++++++++++++++++++------ src/Terminal.js | 50 ++++++++++++++++++++++---------------------- src/engine.js | 17 +++++++++++++++ 4 files changed, 83 insertions(+), 31 deletions(-) diff --git a/index.html b/index.html index ad77e36cd..21705c4fa 100644 --- a/index.html +++ b/index.html @@ -430,6 +430,16 @@ SQLInject.exe This virus opens SQL ports + + + DeepscanV1.exe + This program allows you to use the scan-analyze command with a depth up to 5 + + + + DeepscanV2.exe + This program allows you to use the scan-analyze command with a depth up to 10 +
diff --git a/src/CreateProgram.js b/src/CreateProgram.js index c00012040..141cc5317 100644 --- a/src/CreateProgram.js +++ b/src/CreateProgram.js @@ -1,11 +1,13 @@ /* Create programs */ Programs = { - NukeProgram: "NUKE.exe", - BruteSSHProgram: "BruteSSH.exe", - FTPCrackProgram: "FTPCrack.exe", - RelaySMTPProgram: "relaySMTP.exe", - HTTPWormProgram: "HTTPWorm.exe", - SQLInjectProgram: "SQLInject.exe", + NukeProgram: "NUKE.exe", + BruteSSHProgram: "BruteSSH.exe", + FTPCrackProgram: "FTPCrack.exe", + RelaySMTPProgram: "relaySMTP.exe", + HTTPWormProgram: "HTTPWorm.exe", + SQLInjectProgram: "SQLInject.exe", + DeepscanV1: "DeepscanV1.exe", + DeepscanV2: "DeepscanV2.exe", } //TODO Right now the times needed to complete work are hard-coded... @@ -17,6 +19,8 @@ function displayCreateProgramContent() { var relaySmtpALink = document.getElementById("create-program-relaysmtp"); var httpWormALink = document.getElementById("create-program-httpworm"); var sqlInjectALink = document.getElementById("create-program-sqlinject"); + var deepscanv1ALink = document.getElementById("create-program-deepscanv1"); + var deepscanv2ALink = document.getElementById("create-program-deepscanv2"); nukeALink.style.display = "none"; bruteSshALink.style.display = "none"; @@ -24,6 +28,8 @@ function displayCreateProgramContent() { relaySmtpALink.style.display = "none"; httpWormALink.style.display = "none"; sqlInjectALink.style.display = "none"; + deepscanv1ALink.style.display = "none"; + deepscanv2ALink.style.display = "none"; //NUKE.exe (in case you delete it lol) if (Player.getHomeComputer().programs.indexOf(Programs.NukeProgram) == -1) { @@ -59,6 +65,15 @@ function displayCreateProgramContent() { Player.hacking_skill >= 750) { sqlInjectALink.style.display = "inline-block"; } + + //Deepscan V1 and V2 + if (!Player.hasProgram(Programs.DeepscanV1) && Player.hacking_skill >= 75) { + deepscanv1ALink.style.display = "inline-block"; + } + + if (!Player.hasProgram(Programs.DeepscanV2) && Player.hacking_skill >= 400) { + deepscanv2ALink.style.display = "inline-block"; + } } //Returns the number of programs that are currently available to be created @@ -99,5 +114,15 @@ function getNumAvailableCreateProgram() { Player.hacking_skill >= 750) { ++count; } + + //Deepscan V1 and V2 + if (!Player.hasProgram(Programs.DeepscanV1) && Player.hacking_skill >= 75) { + ++count; + } + + if (!Player.hasProgram(Programs.DeepscanV2) && Player.hacking_skill >= 400) { + ++count; + } + return count; } \ No newline at end of file diff --git a/src/Terminal.js b/src/Terminal.js index c4877b55f..5fca816a2 100644 --- a/src/Terminal.js +++ b/src/Terminal.js @@ -728,8 +728,19 @@ var Terminal = { Terminal.executeScanAnalyzeCommand(1); } else if (commandArray.length == 2) { var depth = Number(commandArray[1]); - if (isNaN(depth)) { - post("Incorrect usage of scan-analyze command. depth argument must be numeric"); + if (isNaN(depth) || depth < 0) { + post("Incorrect usage of scan-analyze command. depth argument must be positive numeric"); + return; + } + if (depth > 3 && !Player.hasProgram(Programs.DeepscanV1) && + !Player.hasProgram(Programs.DeepscanV2)) { + post("You cannot scan-analyze with that high of a depth. Maximum depth is 3"); + return; + } else if (depth > 5 && !Player.hasProgram(Programs.DeepscanV2)) { + post("You cannot scan-analyze with that high of a depth. Maximum depth is 5"); + return; + } else if (depth > 10) { + post("You cannot scan-analyze with that high of a depth. Maximum depth is 10"); return; } Terminal.executeScanAnalyzeCommand(depth); @@ -844,6 +855,9 @@ var Terminal = { //We'll use the AllServersToMoneyMap as a visited() array //TODO Later refactor this to a generic name //TODO Using array as stack for now, can make more efficient + post("~~~~~~~~~~ Beginning scan-analyze ~~~~~~~~~~"); + post(" "); + post(" "); var visited = new AllServersToMoneyMap(); var stack = []; var depthQueue = [0]; @@ -862,31 +876,17 @@ var Terminal = { depthQueue.push(d+1); } if (d == 0) {continue;} //Don't print current server - var titleNumDashes = Array((d-1) * 2 + 1).join("-"); - post("" + titleNumDashes + s.hostname + ""); - var numDashes = Array(d * 2 + 1).join("-"); - var c = "N"; - if (s.hasAdminRights) {c = "Y";} - post(numDashes + "Root Access: " + c); - post(numDashes + "Required hacking skill: " + s.requiredHackingSkill); - post(numDashes + "Number of open ports required to NUKE: " + s.numOpenPortsRequired); - post(numDashes + "RAM: " + s.maxRam); - } - /* - var currServ = Player.getCurrentServer(); - for (var i = 0; i < currServ.serversOnNetwork.length; ++i) { - var serv = currServ.getServerOnNetwork(i); - if (serv == null) {continue;} - post("" + serv.hostname + ""); - var c = "N"; - if (serv.hasAdminRights) {c = "Y";} - post("--Root Access: " + c); - post("--Required hacking skill: " + serv.requiredHackingSkill); - post("--Number of open ports required to NUKE: " + serv.numOpenPortsRequired); - post("--RAM: " + serv.maxRam); + var titleDashes = Array((d-1) * 4 + 1).join("-"); + post("" + titleDashes + ">" + s.hostname + ""); + var dashes = titleDashes + "--"; + //var dashes = Array(d * 2 + 1).join("-"); + var c = "NO"; + if (s.hasAdminRights) {c = "YES";} + post(dashes + "Root Access: " + c + ", Required hacking skill: " + s.requiredHackingSkill); + post(dashes + "Number of open ports required to NUKE: " + s.numOpenPortsRequired); + post(dashes + "RAM: " + s.maxRam); post(" "); } - */ }, executeFreeCommand: function(commandArray) { diff --git a/src/engine.js b/src/engine.js index 8b3aa1e92..bb9289b6b 100644 --- a/src/engine.js +++ b/src/engine.js @@ -1005,23 +1005,40 @@ var Engine = { var relaySmtpALink = document.getElementById("create-program-relaysmtp"); var httpWormALink = document.getElementById("create-program-httpworm"); var sqlInjectALink = document.getElementById("create-program-sqlinject"); + var deepscanv1ALink = document.getElementById("create-program-deepscanv1"); + var deepscanv2ALink = document.getElementById("create-program-deepscanv2"); + nukeALink.addEventListener("click", function() { Player.startCreateProgramWork(Programs.NukeProgram, CONSTANTS.MillisecondsPerFiveMinutes, 1); + return false; }); bruteSshALink.addEventListener("click", function() { Player.startCreateProgramWork(Programs.BruteSSHProgram, CONSTANTS.MillisecondsPerFiveMinutes * 2, 50); + return false; }); ftpCrackALink.addEventListener("click", function() { Player.startCreateProgramWork(Programs.FTPCrackProgram, CONSTANTS.MillisecondsPerHalfHour, 100); + return false; }); relaySmtpALink.addEventListener("click", function() { Player.startCreateProgramWork(Programs.RelaySMTPProgram. CONSTANTS.MillisecondsPer2Hours, 250); + return false; }); httpWormALink.addEventListener("click", function() { Player.startCreateProgramWork(Programs.HTTPWormProgram, CONSTANTS.MillisecondsPer4Hours, 500); + return false; }); sqlInjectALink.addEventListener("click", function() { Player.startCreateProgramWork(Programs.SQLInjectProgram, CONSTANTS.MillisecondsPer8Hours, 750); + return false; + }); + deepscanv1ALink.addEventListener("click", function() { + Player.startCreateProgramWork(Programs.DeepscanV1, CONSTANTS.MillisecondsPerQuarterHour, 75); + return false; + }); + deepscanv2ALink.addEventListener("click", function() { + Player.startCreateProgramWork(Programs.DeepscanV2, CONSTANTS.MillisecondsPer2Hours, 400); + return false; }); //Message at the top of terminal From 0fd5323d52e70449bc2a89ea103901a12931de55 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Wed, 24 May 2017 18:23:28 -0500 Subject: [PATCH 11/16] Added scan-analyze to Interactive Tutorial --- css/workinprogress.css | 2 ++ src/Constants.js | 2 +- src/InteractiveTutorial.js | 36 +++++++++++++++++++++++++++++++----- src/Terminal.js | 17 +++++++++++++++-- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/css/workinprogress.css b/css/workinprogress.css index 2ce130425..416c8aa35 100644 --- a/css/workinprogress.css +++ b/css/workinprogress.css @@ -4,10 +4,12 @@ padding-top: 10px; padding-left: 10px; height: 100%; + width: 99%; } #work-in-progress-text { color: #66ff33; + width: 70%; } #work-in-progress-cancel-button { diff --git a/src/Constants.js b/src/Constants.js index c95a12c58..975c337ca 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -150,7 +150,7 @@ CONSTANTS = { "rm Delete a script/program from the machine. (WARNING: Permanent)
" + "run [script/program] Execute a program or a script
" + "scan Displays all available network connections
" + - "scan-analyze Displays hacking-related information for all available network connections
" + + "scan-analyze [depth] Displays hacking-related information for all servers up to depth nodes away
" + "sudov Shows whether or not you have root access on this computer
" + "tail [script] Display script logs (logs contain details about active scripts)
" + "top Display all running scripts and their RAM usage
", diff --git a/src/InteractiveTutorial.js b/src/InteractiveTutorial.js index 1de7f1e08..9fb4701f9 100644 --- a/src/InteractiveTutorial.js +++ b/src/InteractiveTutorial.js @@ -8,6 +8,8 @@ iTutorialSteps = { TerminalHelp: "Using the help command to display all options in terminal", TerminalLs: "Use the ls command to show all programs/scripts. Right now we have NUKE.exe", TerminalScan: "Using the scan command to display all available connections", + TerminalScanAnalyze1: "Use the scan-analyze command to show hacking related information", + TerminalScanAnalyze2: "Use the scan-analyze command with a depth of 3", TerminalConnect: "Using the telnet/connect command to connect to another server", TerminalAnalyze: "Use the analyze command to display details about this server", TerminalNuke: "Use the NUKE Program to gain root access to a server", @@ -155,13 +157,29 @@ function iTutorialEvaluateStep() { "the 'scan' command. "); //next step triggered by terminal command break; - case iTutorialSteps.TerminalConnect: + case iTutorialSteps.TerminalScanAnalyze1: iTutorialSetText("The 'scan' command shows all available network connections. In other words, " + "it displays a list of all servers that can be connected to from your " + - "current machine. A server is identified by either its IP or its hostname.

" + - "To connect to a machine, use the 'connect [ip/hostname]' command. You can type in " + + "current machine. A server is identified by either its IP or its hostname.

" + + "That's great and all, but there's so many servers. Which one should you go to? " + + "The 'scan-analyze' command gives some more detailed information about servers on the " + + "network. Try it now"); + //next step triggered by terminal command + break; + case iTutorialSteps.TerminalScanAnalyze2: + iTutorialSetText("You just ran 'scan-analyze' with a depth of one. This command shows more detailed " + + "information about each server that you can connect to (servers that are a distance of " + + "one node away).

It is also possible to run 'scan-analyze' with " + + "a higher depth. Let's try a depth of two with the following command: 'scan-analyze 2'.") + //next step triggered by terminal command + break; + case iTutorialSteps.TerminalConnect: + iTutorialSetText("Now you can see information about all servers that are up to two nodes away, as well " + + "as figure out how to connect to those servers through the network. You can only connect to " + + "a server that is one node away. To connect to a machine, use the 'connect [ip/hostname]' command. You can type in " + "the ip or the hostname, but dont use both.

" + - "Let's try this now by connecting to the 'foodnstuff' server (connect foodnstuff)"); + "From the results of the 'scan-analyze' command, we can see that the 'foodnstuff' server is " + + "only one node away. Let's connect so it now using: 'connect foodnstuff'"); //next step triggered by terminal command break; case iTutorialSteps.TerminalAnalyze: @@ -228,7 +246,7 @@ function iTutorialEvaluateStep() { "}

" + "For anyone with basic programming experience, this code should be straightforward. " + "This script will continuously hack the 'foodnstuff' server.

" + - "To save and close the script editor, press the button in the top right, or press ctrl + b."); + "To save and close the script editor, press the button in the bottom left, or press ctrl + b."); //next step triggered in saveAndCloseScriptEditor() (Script.js) break; case iTutorialSteps.TerminalFree: @@ -406,6 +424,14 @@ function iTutorialNextStep() { iTutorialEvaluateStep(); break; case iTutorialSteps.TerminalScan: + currITutorialStep = iTutorialSteps.TerminalScanAnalyze1; + iTutorialEvaluateStep(); + break; + case iTutorialSteps.TerminalScanAnalyze1: + currITutorialStep = iTutorialSteps.TerminalScanAnalyze2; + iTutorialEvaluateStep(); + break; + case iTutorialSteps.TerminalScanAnalyze2: currITutorialStep = iTutorialSteps.TerminalConnect; iTutorialEvaluateStep(); break; diff --git a/src/Terminal.js b/src/Terminal.js index 5fca816a2..3ec8065c7 100644 --- a/src/Terminal.js +++ b/src/Terminal.js @@ -387,10 +387,23 @@ var Terminal = { iTutorialNextStep(); } else {post("Bad command. Please follow the tutorial");} break; + case iTutorialSteps.TerminalScanAnalyze1: + if (commandArray.length == 1 && commandArray[0] == "scan-analyze") { + Terminal.executeScanAnalyzeCommand(1); + iTutorialNextStep(); + } else {post("Bad command. Please follow the tutorial");} + break; + case iTutorialSteps.TerminalScanAnalyze2: + if (commandArray.length == 2 && commandArray[0] == "scan-analyze" && + commandArray[1] == "2") { + Terminal.executeScanAnalyzeCommand(2); + iTutorialNextStep(); + } else {post("Bad command. Please follow the tutorial");} + break; + break; case iTutorialSteps.TerminalConnect: - if (commandArray.length == 2) { - if ((commandArray[0] == "connect" || commandArray[0] == "telnet") && + if ((commandArray[0] == "connect") && (commandArray[1] == "foodnstuff" || commandArray[1] == foodnstuffServ.ip)) { Player.getCurrentServer().isConnectedTo = false; Player.currentServer = foodnstuffServ.ip; From 6316cbae2388c1a8b8dc276479e2d22d7c4dae94 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Thu, 25 May 2017 03:09:51 -0500 Subject: [PATCH 12/16] Minor UI changes --- css/menupages.css | 4 ++++ index.html | 4 ---- src/CreateProgram.js | 7 ------- src/Terminal.js | 1 - 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/css/menupages.css b/css/menupages.css index 3337b8e2b..2d50a9b2c 100644 --- a/css/menupages.css +++ b/css/menupages.css @@ -262,6 +262,10 @@ background-color: #555; width: 70%; } +#create-program-list { + width: 70%; +} + .create-program-a-link-button { text-decoration: none; background-color: #555; diff --git a/index.html b/index.html index 21705c4fa..6100a8e21 100644 --- a/index.html +++ b/index.html @@ -420,22 +420,18 @@ relaySMTP.exe This program opens SMTP ports by redirecting data - HTTPWorm.exe This virus opens up HTTP ports - SQLInject.exe This virus opens SQL ports - DeepscanV1.exe This program allows you to use the scan-analyze command with a depth up to 5 - DeepscanV2.exe This program allows you to use the scan-analyze command with a depth up to 10 diff --git a/src/CreateProgram.js b/src/CreateProgram.js index 141cc5317..e8026f0c6 100644 --- a/src/CreateProgram.js +++ b/src/CreateProgram.js @@ -35,42 +35,35 @@ function displayCreateProgramContent() { if (Player.getHomeComputer().programs.indexOf(Programs.NukeProgram) == -1) { nukeALink.style.display = "inline-block"; } - //BruteSSH if (Player.getHomeComputer().programs.indexOf(Programs.BruteSSHProgram) == -1 && Player.hacking_skill >= 50) { bruteSshALink.style.display = "inline-block"; } - //FTPCrack if (Player.getHomeComputer().programs.indexOf(Programs.FTPCrackProgram) == -1 && Player.hacking_skill >= 100) { ftpCrackALink.style.display = "inline-block"; } - //relaySMTP if (Player.getHomeComputer().programs.indexOf(Programs.RelaySMTPProgram) == -1 && Player.hacking_skill >= 250) { relaySmtpALink.style.display = "inline-block"; } - //HTTPWorm if (Player.getHomeComputer().programs.indexOf(Programs.HTTPWormProgram) == -1 && Player.hacking_skill >= 500) { httpWormALink.style.display = "inline-block"; } - //SQLInject if (Player.getHomeComputer().programs.indexOf(Programs.SQLInjectProgram) == -1 && Player.hacking_skill >= 750) { sqlInjectALink.style.display = "inline-block"; } - //Deepscan V1 and V2 if (!Player.hasProgram(Programs.DeepscanV1) && Player.hacking_skill >= 75) { deepscanv1ALink.style.display = "inline-block"; } - if (!Player.hasProgram(Programs.DeepscanV2) && Player.hacking_skill >= 400) { deepscanv2ALink.style.display = "inline-block"; } diff --git a/src/Terminal.js b/src/Terminal.js index 3ec8065c7..971e58f13 100644 --- a/src/Terminal.js +++ b/src/Terminal.js @@ -870,7 +870,6 @@ var Terminal = { //TODO Using array as stack for now, can make more efficient post("~~~~~~~~~~ Beginning scan-analyze ~~~~~~~~~~"); post(" "); - post(" "); var visited = new AllServersToMoneyMap(); var stack = []; var depthQueue = [0]; From 8cd9e8954df0918d2a069b24b361dfa57fc3b682 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Thu, 25 May 2017 07:18:34 -0500 Subject: [PATCH 13/16] Refactored Netscript Hacknet Node library. Now an array called hacknetnodes[i] can be used to access hacknet nodes, and they can be upgraded with functions --- src/Constants.js | 7 +- src/HacknetNode.js | 21 +++-- src/NetscriptEvaluator.js | 173 +++++++++++++++++++++++++++----------- src/NetscriptParser.js | 47 ++++++++++- src/NetscriptTokenizer.js | 4 +- src/NetscriptWorker.js | 2 +- src/Script.js | 10 ++- src/engine.js | 1 + 8 files changed, 196 insertions(+), 69 deletions(-) diff --git a/src/Constants.js b/src/Constants.js index 975c337ca..cb13fb0db 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -52,8 +52,11 @@ CONSTANTS = { ScriptGetHackingLevelRamCost: 0.1, ScriptGetServerMoneyRamCost: 0.1, ScriptOperatorRamCost: 0.01, - ScriptPurchaseHacknetRamCost: 1.0, - ScriptUpgradeHacknetRamCost: 1.0, + ScriptPurchaseHacknetRamCost: 1.5, + ScriptHacknetNodesRamCost: 1.0, //Base cost for accessing hacknet nodes array + ScriptHNUpgLevelRamCost: 0.4, + ScriptHNUpgRamRamCost: 0.6, + ScriptHNUpgCoreRamCost: 0.8, //Server growth rate ServerGrowthRate: 1.00075, diff --git a/src/HacknetNode.js b/src/HacknetNode.js index 42f2fb507..18143696e 100644 --- a/src/HacknetNode.js +++ b/src/HacknetNode.js @@ -73,15 +73,16 @@ HacknetNode.prototype.calculateLevelUpgradeCost = function(levels=1) { HacknetNode.prototype.purchaseLevelUpgrade = function(levels=1) { var cost = this.calculateLevelUpgradeCost(levels); - if (isNaN(cost)) {throw new Error("Cost is NaN"); return;} - if (cost > Player.money) {return;} + if (isNaN(cost)) {return false;} + if (cost > Player.money) {return false;} Player.loseMoney(cost); if (this.level + levels >= CONSTANTS.HacknetNodeMaxLevel) { this.level = CONSTANTS.HacknetNodeMaxLevel; - return; + return false; } this.level += levels; this.updateMoneyGainRate(); + return true; } HacknetNode.prototype.calculateRamUpgradeCost = function() { @@ -96,12 +97,13 @@ HacknetNode.prototype.calculateRamUpgradeCost = function() { HacknetNode.prototype.purchaseRamUpgrade = function() { var cost = this.calculateRamUpgradeCost(); - if (isNaN(cost)) {throw new Error("Cost is NaN"); return;} - if (cost > Player.money) {return;} + if (isNaN(cost)) {return false;} + if (cost > Player.money) {return false;} Player.loseMoney(cost); - if (this.ram >= CONSTANTS.HacknetNodeMaxRam) {return;} + if (this.ram >= CONSTANTS.HacknetNodeMaxRam) {return false;} this.ram *= 2; //Ram is always doubled this.updateMoneyGainRate(); + return true; } HacknetNode.prototype.calculateCoreUpgradeCost = function() { @@ -112,12 +114,13 @@ HacknetNode.prototype.calculateCoreUpgradeCost = function() { HacknetNode.prototype.purchaseCoreUpgrade = function() { var cost = this.calculateCoreUpgradeCost(); - if (isNaN(cost)) {throw new Error("Cost is NaN"); return;} - if (cost > Player.money) {return;} + if (isNaN(cost)) {return false;} + if (cost > Player.money) {return false;} Player.loseMoney(cost); - if (this.numCores >= CONSTANTS.HacknetNodeMaxCores) {return;} + if (this.numCores >= CONSTANTS.HacknetNodeMaxCores) {return false;} ++this.numCores; this.updateMoneyGainRate(); + return true; } /* Saving and loading HackNets */ diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index bd881f0c6..b0ed43598 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -23,6 +23,17 @@ function evaluate(exp, workerScript) { case "var": return new Promise(function(resolve, reject) { if (env.stopFlag) {reject(workerScript);} + if (exp.value == "hacknetnodes") { + setTimeout(function() { + var pEvaluateHacknetNode = evaluateHacknetNode(exp, workerScript); + pEvaluateHacknetNode.then(function(res) { + resolve(res); + }, function(e) { + reject(e); + }); + }, CONSTANTS.CodeInstructionRunTime); + return; + } try { resolve(env.get(exp.value)); } catch (e) { @@ -747,7 +758,7 @@ function evaluate(exp, workerScript) { } if (cost > Player.money) { workerScript.scriptRef.log("Could not afford to purchase new Hacknet Node"); - resolve(""); + resolve(false); return; } @@ -761,62 +772,15 @@ function evaluate(exp, workerScript) { Player.hacknetNodes.push(node); displayHacknetNodesContent(); workerScript.scriptRef.log("Purchased new Hacknet Node with name: " + name); - resolve(name); + resolve(numOwned); }, CONSTANTS.CodeInstructionRunTime); - } else if (exp.func.value == "upgradeHacknetNode") { - if (exp.args.length != 1) { - reject("|"+workerScript.serverIp+"|"+workerScript.name+"|upgradeHacknetNode() call has incorrect number of arguments. Takes 1 argument"); - return; - } - var namePromise = evaluate(exp.args[0], workerScript); - namePromise.then(function(name) { - var node = getHacknetNode(name); - if (node == null) { - reject("|"+workerScript.serverIp+"|"+workerScript.name+"|Invalid Hacknet Node name passed into upgradeHacknetNode()"); - return; - } - var cost = node.calculateLevelUpgradeCost(1); - if (isNaN(cost)) { - reject("|"+workerScript.serverIp+"|"+workerScript.name+"|Could not calculate cost in upgradeHacknetNode(). This is a bug please report to game dev"); - return; - } - if (cost > Player.money) { - workerScript.scriptRef.log("Could not afford to upgrade Hacknet Node: " + name); - resolve(false); - return; - } - if (node.level >= CONSTANTS.HacknetNodeMaxLevel) { - workerScript.scriptRef.log("Hacknet Node " + name + " already at max level"); - node.level = CONSTANTS.HacknetNodeMaxLevel; - resolve(false); - return; - } - Player.loseMoney(cost); - node.level += 1; - node.updateMoneyGainRate(); - workerScript.scriptRef.log("Hacknet node " + name + " upgraded to level " + node.level + "!"); - resolve(true); - }, function(e) { - reject(e); - }); - } else if (exp.func.value == "getNumHacknetNodes") { - if (exp.args.length != 0) { - reject("|"+workerScript.serverIp+"|"+workerScript.name+"|getNumHacknetNodes() call has incorrect number of arguments. Takes 0 arguments"); - return; - } - setTimeout(function() { - if (env.stopFlag) {reject(workerScript);} - workerScript.scriptRef.log("getNumHacknetNodes() returned " + Player.hacknetNodes.length); - resolve(Player.hacknetNodes.length); - }, CONSTANTS.CodeInstructionRunTime); - } + } }, CONSTANTS.CodeInstructionRunTime); }); reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Unrecognized function call"); break; - default: - reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Can't evaluate type " + exp.type); + break; } } @@ -980,6 +944,109 @@ function evaluateWhile(exp, workerScript) { }); } +function evaluateHacknetNode(exp, workerScript) { + var env = workerScript.env; + return new Promise(function(resolve, reject) { + setTimeout(function() { + if (exp.index == null) { + if ((exp.op.type == "call" && exp.op.value == "length") || + (exp.op.type == "var" && exp.op.value == "length")) { + resolve(Player.hacknetNodes.length); + workerScript.scriptRef.log("hacknetnodes.length returned " + Player.hacknetNodes.length); + return; + } else { + workerScript.scriptRef.log("Invalid/null index for hacknetnodes"); + reject(makeRuntimeRejectMsg(workerScript, "Invalid/null index. hacknetnodes array must be accessed with an index")); + return; + } + + } + var indexPromise = evaluate(exp.index.value, workerScript); + indexPromise.then(function(index) { + if (isNaN(index) || index >= Player.hacknetNodes.length || index < 0) { + workerScript.scriptRef.log("Invalid index value for hacknetnodes[]"); + reject(makeRuntimeRejectMsg(workerScript, "Invalid index value for hacknetnodes[].")); + return; + } + var nodeObj = Player.hacknetNodes[index]; + if (exp.op == null) { + reject(makeRuntimeRejectMsg(workerScript, "No operator or property called for hacknetnodes. Usage: hacknetnodes[i].property/operator")); + return; + } else if (exp.op.type == "var") { + //Get properties: level, ram, cores + switch(exp.op.value) { + case "level": + resolve(nodeObj.level); + break; + case "ram": + resolve(nodeObj.ram); + break; + case "cores": + resolve(nodeObj.numCores); + break; + default: + reject(makeRuntimeRejectMsg(workerScript, "Unrecognized property for Hacknet Node. Valid properties: ram, cores, level")); + break; + } + + } else if (exp.op.type == "call") { + switch(exp.op.func.value) { + case "upgradeLevel": + if (exp.op.args.length == 1) { + var argPromise = evaluate(exp.op.args[0], workerScript); + argPromise.then(function(arg) { + if (isNaN(arg)) { + reject(makeRuntimeRejectMsg(workerScript, "Argument passed into upgradeLevel() is not numeric")); + return; + } + var res = nodeObj.purchaseLevelUpgrade(arg); + if (res) { + workerScript.scriptRef.log("Upgraded " + nodeObj.name + arg + " times to level " + nodeObj.level); + } + resolve(res); + }, function(e) { + reject(e); + }); + } else { + var res = nodeObj.purchaseLevelUpgrade(1); + if (res) { + workerScript.scriptRef.log("Upgraded " + nodeObj.name + " once to level " + nodeObj.level); + } + resolve(res); + } + break; + case "upgradeRam": + var res = nodeObj.purchaseRamUpgrade(); + if (res) { + workerScript.scriptRef.log("Upgraded " + nodeObj.name + "'s RAM to " + nodeObj.ram + "GB"); + } + resolve(res); + break; + case "upgradeCore": + var res = nodeObj.purchaseCoreUpgrade(); + if (res) { + workerScript.scriptRef.log("Upgraded " + nodeObj.name + "'s number of cores to " + nodeObj.numCores); + } + resolve(res); + break; + default: + reject(makeRuntimeRejectMsg(workerScript, "Unrecognized function/operator for hacknet node. Valid functions: upgradeLevel(n), upgradeRam(), upgradeCore()")); + break; + } + } else { + reject(makeRuntimeRejectMsg(workerScript, "Unrecognized operation for hacknet node")); + return; + } + }, function(e) { + reject(e); + }); + + }, CONSTANTS.CodeInstructionRunTime); + }, function(e) { + reject(e); + }); +} + function evaluateProg(exp, workerScript, index) { var env = workerScript.env; @@ -1016,6 +1083,10 @@ function evaluateProg(exp, workerScript, index) { }); } +function makeRuntimeRejectMsg(workerScript, msg) { + return "|"+workerScript.serverIp+"|"+workerScript.name+"|" + msg; +} + function apply_op(op, a, b) { function num(x) { if (typeof x != "number") diff --git a/src/NetscriptParser.js b/src/NetscriptParser.js index 95f4fad71..9f57b12fc 100644 --- a/src/NetscriptParser.js +++ b/src/NetscriptParser.js @@ -187,8 +187,48 @@ function Parser(input) { cond: cond, code: code } - } + + /* hacknetnodes[i].operator + */ + function parse_hacknetnodes() { + var index = null; + if (is_punc("[")) { + index = parse_expression(); + if (index.type != "index") { + console.log("Failed here"); + unexpected(); + } + } + + if (is_punc(".")) { + checkPuncAndSkip("."); + var op = maybe_call(function() { + var tok = input.next(); + return tok; + }); + return { + type: "var", + value: "hacknetnodes", + index: index, + op: op, + } + } + console.log("Failed here"); + unexpected(); + } + + function parse_arrayindex() { + var index = delimited("[", "]", ";", parse_expression); + var val = 0; + if (index.length == 1 && (index[0].type == "num" || index[0].type == "var")) { + val = index[0]; + } else { + console.log("WARNING: Extra indices passed in") + } + + return { type: "index", value: val }; + } function parse_bool() { return { @@ -211,13 +251,16 @@ function Parser(input) { return exp; } if (is_punc("{")) return parse_prog(); + if (is_punc("[")) return parse_arrayindex(); if (is_kw("if")) return parse_if(); if (is_kw("for")) return parse_for(); if (is_kw("while")) return parse_while(); + //if (is_kw("hacknetnodes")) return parse_hacknetnodes(); //Note, let for loops be function calls (call node types) if (is_kw("true") || is_kw("false")) return parse_bool(); - + var tok = input.next(); + if (tok.type == "var" && tok.value == "hacknetnodes") return parse_hacknetnodes(); if (tok.type == "var" || tok.type == "num" || tok.type == "str") return tok; unexpected(); diff --git a/src/NetscriptTokenizer.js b/src/NetscriptTokenizer.js index d7307e775..38d591ed0 100644 --- a/src/NetscriptTokenizer.js +++ b/src/NetscriptTokenizer.js @@ -6,7 +6,7 @@ * {type: "punc", value: "(" } // punctuation: parens, comma, semicolon etc. * {type: "num", value: 5 } // numbers (including floats) * {type: "str", value: "Hello World!" } // strings - * {type: "kw", value: "for/if/" } // keywords, see defs below + * {type: "kw", value: "for/if/..." } // keywords, see defs below * {type: "var", value: "a" } // identifiers/variables * {type: "op", value: "!=" } // operator characters * {type: "bool", value: "true" } // Booleans @@ -46,7 +46,7 @@ function Tokenizer(input) { } function is_punc(ch) { - return ",;(){}[]".indexOf(ch) >= 0; + return ",;(){}[].".indexOf(ch) >= 0; } function is_whitespace(ch) { diff --git a/src/NetscriptWorker.js b/src/NetscriptWorker.js index 1076ced86..4f57bb201 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; diff --git a/src/Script.js b/src/Script.js index 4619ea862..2624489bc 100644 --- a/src/Script.js +++ b/src/Script.js @@ -185,7 +185,10 @@ Script.prototype.updateRamUsage = function() { var getServerMoneyAvailableCount = numOccurrences(codeCopy, "getServerMoneyAvailable("); var numOperators = numNetscriptOperators(codeCopy); var purchaseHacknetCount = numOccurrences(codeCopy, "purchaseHacknetNode("); - var upgradeHacknetCount = numOccurrences(codeCopy, "upgradeHacknetNode("); + var hacknetnodesArrayCount = numOccurrences(codeCopy, "hacknetnodes["); + var hnUpgLevelCount = numOccurrences(codeCopy, ".upgradeLevel("); + var hnUpgRamCount = numOccurrences(codeCopy, ".upgradeRam()"); + var hnUpgCoreCount = numOccurrences(codeCopy, ".upgradeCore()"); this.ramUsage = baseRam + ((whileCount * CONSTANTS.ScriptWhileRamCost) + @@ -204,7 +207,10 @@ Script.prototype.updateRamUsage = function() { (getServerMoneyAvailableCount * CONSTANTS.ScriptGetServerMoneyRamCost) + (numOperators * CONSTANTS.ScriptOperatorRamCost) + (purchaseHacknetCount * CONSTANTS.ScriptPurchaseHacknetRamCost) + - (upgradeHacknetCount * CONSTANTS.ScriptUpgradeHacknetRamCost)); + (hacknetnodesArrayCount * CONSTANTS.ScriptHacknetNodesRamCost) + + (hnUpgLevelCount * CONSTANTS.ScriptHNUpgLevelRamCost) + + (hnUpgRamCount * CONSTANTS.ScriptHNUpgRamRamCost) + + (hnUpgCoreCount * CONSTANTS.ScriptHNUpgCoreRamCost)); 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"); diff --git a/src/engine.js b/src/engine.js index bb9289b6b..8733b7f97 100644 --- a/src/engine.js +++ b/src/engine.js @@ -1080,6 +1080,7 @@ var Engine = { //DEBUG document.getElementById("debug-delete-scripts-link").addEventListener("click", function() { + console.log("Deleting running scripts on home computer"); Player.getHomeComputer().runningScripts = []; return false; }); From bfba6a3d5bca860537f60e20f76f3a9c330d7563 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Thu, 25 May 2017 09:50:58 -0500 Subject: [PATCH 14/16] Updated Netscript documentation for new Hacknet Node 'API'. Adde game options --- css/popupboxes.css | 50 ++++++++++++++++++++++++++++++++++- css/styles.css | 21 ++++++++++++++- index.html | 27 +++++++++++-------- src/Constants.js | 55 ++++++++++++++++++++++++++++++--------- src/NetscriptEvaluator.js | 6 ++--- src/NetscriptWorker.js | 2 +- src/engine.js | 6 +++++ utils/GameOptions.js | 43 ++++++++++++++++++++++++++++++ 8 files changed, 180 insertions(+), 30 deletions(-) create mode 100644 utils/GameOptions.js diff --git a/css/popupboxes.css b/css/popupboxes.css index 75a8514d7..dfb9d85bb 100644 --- a/css/popupboxes.css +++ b/css/popupboxes.css @@ -286,7 +286,7 @@ color: #66ff33; } -#trave-l-box-text { +#travel-box-text { margin: 8px; } @@ -313,4 +313,52 @@ color: white; text-decoration: none; cursor: pointer; +} + +/* Game Options */ +#game-options-container { + display: none; /* Hidden by default */ + position: fixed; /* Stay in place */ + z-index: 1; /* Sit on top */ + left: 0; + right: 0; + bottom: 0; + top: 0; + width: 100%; /* Full width */ + height: 100%; /* Full height */ + overflow: auto; /* Enable scroll if needed */ + background-color: black; /* Fallback color */ + background-color: rgba(0,0,0,0.4); /* Black w/ opacity */ + transition: opacity 400ms ease-in; +} + +#game-options-content { + background-color: black; + margin: 15% auto; /* 15% from the top and centered */ + padding: 10px; + border: 5px solid #FFFFFF; + width: 50%; /* Could be more or less, depending on screen size */ + color: #66ff33; +} + +#game-options-close-button { + color: #aaa; + float: right; + margin: 4px; + padding: 4px; + font-size: 20px; + font-weight: bold; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; + border-radius: 12px white; + -moz-box-shadow: 1px 1px 3px #000; + -webkit-box-shadow: 1px 1px 3px #000; + box-shadow: 1px 1px 3px #000; +} + +#game-options-close-button:hover, +#game-options-close-button:focus { + color: white; + text-decoration: none; + cursor: pointer; } \ No newline at end of file diff --git a/css/styles.css b/css/styles.css index 7cbf5a14c..c273084e4 100644 --- a/css/styles.css +++ b/css/styles.css @@ -241,7 +241,7 @@ tr:focus { position: absolute; /* Stay in place */ right: 0; top: 0; - height: 150px; /* Full height */ + height: 175px; /* Full height */ /*margin: 50% auto;*/ padding: 5px; border: 2px solid #66ff33; @@ -257,3 +257,22 @@ tr:focus { color: white; background-color: #444; } + +#character-overview-save-button { + color: #aaa; + font-size: 16px; + font-weight: bold; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; + border-radius: 12px; + -moz-box-shadow: 1px 1px 3px #000; + -webkit-box-shadow: 1px 1px 3px #000; + box-shadow: 1px 1px 3px #000; +} + +#character-overview-save-button:hover, +#character-overview-save-button:focus { + color: white; + text-decoration: none; + cursor: pointer; +} diff --git a/index.html b/index.html index 6100a8e21..a3a570432 100644 --- a/index.html +++ b/index.html @@ -24,6 +24,7 @@ + @@ -105,19 +106,10 @@
  • Tutorial
  • - -
  • - Save Game -
  • - -
  • - Delete Game -
  • -
  • - (DEBUG) Delete Active Scripts +
  • + Options
  • -
    @@ -739,6 +731,7 @@

    + Save Game
    @@ -747,5 +740,17 @@

    Test

    + + + \ No newline at end of file diff --git a/src/Constants.js b/src/Constants.js index cb13fb0db..cc6f7d2c8 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -286,20 +286,49 @@ CONSTANTS = { "getHackingLevel()
    Returns the Player's current hacking level. Does NOT work while offline

    " + "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. Does NOT work while offline
    Example: getServerMoneyAvailable('foodnstuff');

    " + - "purchaseHacknetNode()
    Purchases a new Hacknet Node. Returns a string with the name of the new Hacknet Node. If the player cannot afford to purchase " + - "a new hacknet node then the function will return an empty string. Does NOT work offline

    " + - "upgradeHacknetNode(name)
    Upgrades the level of a Hacknet Node. The argument passed in must be a string with the name of the Hacknet Node to upgrade. " + - "If the Hacknet Node is successfully upgraded the function will return true. It will return false otherwise. Does NOT work offline. Example:
    " + - "node = purchaseHacknetNode();
    " + - "if (node != '') {
    " + - "    i = 0;
    " + - "    while(i < 10) {
    " + - "         if (upgradeHacknetNode(node)) {i = i + 1;}
    " + - "    };
    " + + "purchaseHacknetNode()
    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

    " + + "

    Hacknet Nodes API


    " + + "Netscript provides the following API for accessing and upgrading your Hacknet Nodes through scripts. This API does NOT work offline.

    " + + "hacknetnodes
    A special variable. This is an array that maps to the Player's Hacknet Nodes. The Hacknet Nodes are accessed through " + + "indexes. These indexes correspond to the number at the end of the name of the Hacknet Node. For example, the first Hacknet Node you purchase " + + "will have the same 'hacknet-node-0' and can be accessed with hacknetnodes[0]. The fourth Hacknet Node you purchase will have the name " + + "'hacknet-node-3' and can be accessed with hacknetnodes[3].

    " + + "hacknetnodes.length
    Returns the number of Hacknet Nodes that the player owns

    " + + "hacknetnodes[i].level
    Returns the level of the corresponding Hacknet Node

    " + + "hacknetnodes[i].ram
    Returns the amount of RAM on the corresponding Hacknet Node

    " + + "hacknetnodes[i].cores
    Returns the number of cores on the corresponding Hacknet Node

    " + + "hacknetnodes[i].upgradeLevel(n)
    Tries to upgrade the level of the corresponding Hacknet Node n times. The argument n must be a " + + "positive integer. Returns true if the Hacknet Node's level is successfully upgraded n times, and false otherwise.

    " + + "hacknetnodes[i].upgradeRam()
    Tries to upgrade the amount of RAM on the corresponding Hacknet Node. Returns true if the " + + "RAM is successfully upgraded, and false otherwise.

    " + + "hacknetnodes[i].upgradeCore()
    Attempts to purchase an additional core for the corresponding Hacknet Node. Returns true if the " + + "additional core is successfully purchase, and false otherwise.

    " + + "Example: The following is an example of one way a script can be used to automate the purchasing and upgrading of Hacknet Nodes. " + + "This script purchases new Hacknet Nodes until the player has four. Then, it iteratively upgrades each of those four Hacknet Nodes " + + "to a level of at least 75, RAM to at least 8GB, and number of cores to at least 2.

    " + + "while(hacknetnodes.length < 4) {
    " + + "    purchaseHacknetNode();
    " + + "};
    " + + "for (i = 0; i < 4; i = i+1) {
    " + + "    while (hacknetnodes[i].level <= 75) {
    " + + "        hacknetnodes[i].upgradeLevel(5);
    " + + "        sleep(10000);
    " + + "    };
    " + + "};
    " + + "for (i = 0; i < 4; i = i+1) {
    " + + "    while (hacknetnodes[i].ram < 8) {
    " + + "        hacknetnodes[i].upgradeRam();
    " + + "        sleep(10000);
    " + + "    };
    " + + "};
    " + + "for (i = 0; i < 4; i = i+1) {
    " + + "    while (hacknetnodes[i].cores < 2) {
    " + + "        hacknetnodes[i].upgradeCore();
    " + + "        sleep(10000);
    " + + "    };
    " + "};

    " + - "The example code above will attempt to purchase a new Hacknet Node. If the Hacknet Node is purchased, then it will " + - "continuously try to level it up until it is leveled up 10 times.

    " + - "getNumHacknetNodes()
    returns the number of Hacknet Nodes that the Player owns. Does NOT work while offline

    " + "

    While loops


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

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


    " + diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index b0ed43598..c3298cea1 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -995,13 +995,13 @@ function evaluateHacknetNode(exp, workerScript) { if (exp.op.args.length == 1) { var argPromise = evaluate(exp.op.args[0], workerScript); argPromise.then(function(arg) { - if (isNaN(arg)) { - reject(makeRuntimeRejectMsg(workerScript, "Argument passed into upgradeLevel() is not numeric")); + if (isNaN(arg) || arg < 0) { + reject(makeRuntimeRejectMsg(workerScript, "Invalid argument passed into upgradeLevel()")); return; } var res = nodeObj.purchaseLevelUpgrade(arg); if (res) { - workerScript.scriptRef.log("Upgraded " + nodeObj.name + arg + " times to level " + nodeObj.level); + workerScript.scriptRef.log("Upgraded " + nodeObj.name + " " + arg + " times to level " + nodeObj.level); } resolve(res); }, function(e) { 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; diff --git a/src/engine.js b/src/engine.js index 8733b7f97..03fb348a7 100644 --- a/src/engine.js +++ b/src/engine.js @@ -988,6 +988,12 @@ var Engine = { return false; }); + //Character Overview Save button + var charOverviewSaveButton = document.getElementById("character-overview-save-button"); + charOverviewSaveButton.addEventListener("click", function() { + saveObject.saveGame(); + return false; + }); //Script Editor Netscript documentation button var netscriptDocButton = document.getElementById("script-editor-netscript-doc-button"); diff --git a/utils/GameOptions.js b/utils/GameOptions.js new file mode 100644 index 000000000..019e9e0fc --- /dev/null +++ b/utils/GameOptions.js @@ -0,0 +1,43 @@ +/* GameOptions.js */ + +//Close box when clicking outside +$(document).click(function(event) { + if (gameOptionsOpened) { + if ( $(event.target).closest(".game-options-box").get(0) == null ) { + gameOptionsBoxClose(); + } + } +}); + +var gameOptionsOpened = false; +function gameOptionsBoxInit() { + //Menu link button + document.getElementById("options-menu-link").addEventListener("click", function() { + gameOptionsBoxOpen(); + return false; + }); + + //Close button + var closeButton = document.getElementById("game-options-close-button"); + closeButton.addEventListener("click", function() { + gameOptionsBoxClose(); + return false; + }); +}; + +document.addEventListener("DOMContentLoaded", gameOptionsBoxInit, false); + +gameOptionsBoxClose = function() { + gameOptionsOpened = false; + var box = document.getElementById("game-options-container"); + box.style.display = "none"; +} + +gameOptionsBoxOpen = function() { + var box = document.getElementById("game-options-container"); + box.style.display = "block"; + setTimeout(function() { + gameOptionsOpened = true; + }, 500); + +} \ No newline at end of file From f836596b8e921c8e66277d5f47a1ea9516a5b812 Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Thu, 25 May 2017 10:12:35 -0500 Subject: [PATCH 15/16] Updated version to 0.16 --- src/Constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Constants.js b/src/Constants.js index cc6f7d2c8..8c693ef1b 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -1,5 +1,5 @@ CONSTANTS = { - Version: "0.15", + Version: "0.16", //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 From a453d96d50280c2651724474ec937b7c8654928c Mon Sep 17 00:00:00 2001 From: Daniel Xie Date: Thu, 25 May 2017 10:55:25 -0500 Subject: [PATCH 16/16] Fixed text in Interactive Tutorial --- src/InteractiveTutorial.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/InteractiveTutorial.js b/src/InteractiveTutorial.js index 9fb4701f9..c67a19aef 100644 --- a/src/InteractiveTutorial.js +++ b/src/InteractiveTutorial.js @@ -175,7 +175,7 @@ function iTutorialEvaluateStep() { break; case iTutorialSteps.TerminalConnect: iTutorialSetText("Now you can see information about all servers that are up to two nodes away, as well " + - "as figure out how to connect to those servers through the network. You can only connect to " + + "as figure out how to navigate to those servers through the network. You can only connect to " + "a server that is one node away. To connect to a machine, use the 'connect [ip/hostname]' command. You can type in " + "the ip or the hostname, but dont use both.

    " + "From the results of the 'scan-analyze' command, we can see that the 'foodnstuff' server is " +