diff --git a/css/popupboxes.css b/css/popupboxes.css
index b15750591..0c10a2d50 100644
--- a/css/popupboxes.css
+++ b/css/popupboxes.css
@@ -82,7 +82,7 @@
float: right;
font-size: 16px;
font-weight: bold;
- padding: 6px;
+ padding: 2px;
margin: 6px;
border: 1px solid white;
}
@@ -133,7 +133,7 @@
float: right;
font-size: 16px;
font-weight: bold;
- padding: 6px;
+ padding: 2px;
margin: 6px;
border: 1px solid white;
}
@@ -184,7 +184,7 @@
float: right;
font-size: 16px;
font-weight: bold;
- padding: 6px;
+ padding: 2px;
margin: 6px;
border: 1px solid white;
}
@@ -229,12 +229,16 @@
color: #66ff33;
}
+#faction-invitation-box-warning {
+ margin: 4px;
+}
+
#faction-invitation-box-yes,
#faction-invitation-box-no {
color: #aaa;
font-size: 20px;
font-weight: bold;
- padding: 6px;
+ padding: 2px;
margin: 6px;
border: 1px solid white;
}
@@ -285,7 +289,7 @@
color: #aaa;
font-size: 20px;
font-weight: bold;
- padding: 6px;
+ padding: 2px;
margin: 6px;
border: 1px solid white;
}
diff --git a/index.html b/index.html
index cf712e751..07b05a8c6 100644
--- a/index.html
+++ b/index.html
@@ -112,7 +112,10 @@
diff --git a/src/Constants.js b/src/Constants.js
index a91a62702..265543cd6 100644
--- a/src/Constants.js
+++ b/src/Constants.js
@@ -28,6 +28,9 @@ CONSTANTS = {
//Time (seconds) it takes to run one operation in Netscript OFFLINE
CodeOfflineExecutionTime: 10,
+ //Server growth rate
+ ServerGrowthRate: 1.00075,
+
//Maximum number of log entries for a script
MaxLogCapacity: 20,
diff --git a/src/Faction.js b/src/Faction.js
index 74b654746..9736b3453 100644
--- a/src/Faction.js
+++ b/src/Faction.js
@@ -136,6 +136,9 @@ initFactions = function() {
//Earlygame factions - factions the player will prestige with early on that don't
//belong in other categories
+ var Netburners = new Faction("Netburners");
+ Netburners.setInfo(FactionInfo.NetburnersInfo);
+ AddToFactions(Netburners);
var TianDiHui = new Faction("Tian Di Hui"); //Society of the Heaven and Earth
TianDiHui.setInfo(FactionInfo.TianDiHuiInfo);
AddToFactions(TianDiHui);
@@ -378,7 +381,24 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
this.companyPosition.positionName == CompanyPositions.CEO.positionName) &&
this.money >= 15000000) {
invitedFactions.push(silhouetteFac);
- }
+ }
+
+ //Netburners
+ /*
+ var netburnersFac = Factions["Netburners"];
+ var totalHacknetRam = 0;
+ var totalHacknetCores = 0;
+ var totalHacknetLevels = 0;
+ for (var i = 0; i < Player.hacknetNodes.length; ++i) {
+ totalHacknetLevels += Player.hacknetNodes[i].level;
+ totalHacknetRam += Player.hacknetNodes[i].ram;
+ totalHacknetCores += Player.hacknetNodes[i].numCores;
+ }
+ if (netburnersFac.isBanned == false && netburnersFac.isMember == false &&
+ this.hacking_skill >= 100 && totalHacknetRam >= 10 &&
+ totalHacknetCores >= 5 && totalHacknetLevels >= 100) {
+ invitedFactions.push(netburnersFac);
+ }*/
//Tian Di Hui
var tiandihuiFac = Factions["Tian Di Hui"];
diff --git a/src/FactionInfo.js b/src/FactionInfo.js
index 4f6c5b2e7..1974931b7 100644
--- a/src/FactionInfo.js
+++ b/src/FactionInfo.js
@@ -115,6 +115,7 @@ FactionInfo = {
//Earlygame factions - factions the player will prestige with early on that don't
//belong in other categories
+ NetburnersInfo: "~~HACKNET BURNERS~~",
TianDiHuiInfo: "Obey Heaven and Work Righteousness",
CyberSecInfo: "The Internet is the first thing that humanity has built that humanity doesn’t understand,\n" +
diff --git a/src/Netscript/Evaluator.js b/src/Netscript/Evaluator.js
index b8e4abdaf..e6c47bbbe 100644
--- a/src/Netscript/Evaluator.js
+++ b/src/Netscript/Evaluator.js
@@ -281,7 +281,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.");
+ reject("|" + workerScript.serverIp + "|" + workerScript.name + "|sleep() call has incorrect number of arguments. Takes 1 argument.");
return;
}
@@ -302,11 +302,9 @@ function evaluate(exp, workerScript) {
}, function(e) {
reject(e)
});
-
-
} 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");
+ reject("|" + workerScript.serverIp + "|" + workerScript.name + "|print() call has incorrect number of arguments. Takes 1 argument");
}
var p = new Promise(function(resolve, reject) {
@@ -321,18 +319,67 @@ function evaluate(exp, workerScript) {
});
p.then(function(res) {
- post(res.toString());
+ workerScript.scriptRef.log(res.toString());
resolve("printExecuted");
}, function(e) {
reject(e);
});
- }
+ } 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");
+ }
+
+ //IP/hostname of server to hack
+ var ipPromise = evaluate(exp.args[0], workerScript);
+
+ ipPromise.then(function(ip) {
+ //Check if its a valid IP address. If it's not, assume its a hostname and
+ //try to get the server. If its not a server, there is an error
+ var server = null;
+ if (!isValidIPAddress(ip)) {
+ //It's not an IP address, so see if its a hostanme
+ server = GetServerByHostname(ip);
+ } else {
+ server = AllServers[ip];
+ }
+ if (server == null) {
+ reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into grow() command");
+ workerScript.scriptRef.log("Cannot grow(). Invalid IP or hostname passed in: " + ip);
+ return;
+ }
+
+ //No root access or skill level too low
+ if (server.hasAdminRights == false) {
+ workerScript.scriptRef.log("Cannot grow this server (" + server.hostname + ") because user does not have root access");
+ reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Script crashed because it did not have root access to " + server.hostname);
+ return;
+ }
+
+ var p = new Promise(function(resolve, reject) {
+ if (env.stopFlag) {reject(workerScript);}
+ console.log("Executing grow on " + server.hostname + " in 2 minutes ");
+ setTimeout(function() {
+ var growthPercentage = processSingleServerGrowth(server, 450);
+ resolve(growthPercentage);
+ }, 120 * 1000); //grow() takes flat 2 minutes right now
+ });
+
+ p.then(function(growthPercentage) {
+ resolve("hackExecuted");
+ workerScript.scriptRef.log("Using grow(), the money available on " + server.hostname + " was grown by " + growthPercentage + "%");
+ }, function(e) {
+ reject(e);
+ });
+ }, function(e) {
+ reject(e);
+ });
+ }
}, CONSTANTS.CodeInstructionRunTime);
});
break;
default:
- reject("|" + workerScript.serverIp + "|" + workerScript.name + "| Can't evaluate type " + exp.type);
+ reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Can't evaluate type " + exp.type);
}
}
diff --git a/src/Player.js b/src/Player.js
index 4c799d4b5..4cf75aa7b 100644
--- a/src/Player.js
+++ b/src/Player.js
@@ -191,12 +191,12 @@ PlayerObject.prototype.calculateHackingChance = function() {
//Calculate the time it takes to hack a server in seconds. Returns the time
//The formula is:
-// (requiredLevel * difficulty)
-// ------------------------------- * hacking_speed_multiplier
-// hacking_skill
+// (requiredLevel * difficulty + 500)
+// ----------------------------------- * hacking_speed_multiplier
+// hacking_skill + 100
PlayerObject.prototype.calculateHackingTime = function() {
var difficultyMult = this.getCurrentServer().requiredHackingSkill * this.getCurrentServer().hackDifficulty;
- var skillFactor = (difficultyMult + 500) / (this.hacking_skill + 100);
+ var skillFactor = (2 * difficultyMult + 300) / (this.hacking_skill + 100);
return skillFactor * this.hacking_speed_mult;
}
diff --git a/src/Server.js b/src/Server.js
index c7da7cbbd..3708ba628 100644
--- a/src/Server.js
+++ b/src/Server.js
@@ -626,11 +626,12 @@ initForeignServers = function() {
Player.getHomeComputer().serversOnNetwork.push(NetworkGroup1[i].ip);
NetworkGroup1[i].serversOnNetwork.push(Player.homeComputer);
}
-},
+}
//Server growth
processServerGrowth = function(numCycles) {
+ //Server growth processed once every 450 game cycles
var numServerGrowthCycles = Math.max(Math.floor(numCycles / 450), 0);
for (var ip in AllServers) {
@@ -643,13 +644,30 @@ processServerGrowth = function(numCycles) {
var numServerGrowthCyclesAdjusted = numServerGrowthCycles * serverGrowthPercentage;
//Apply serverGrowth for the calculated number of growth cycles
- var serverGrowth = Math.pow(1.00075, numServerGrowthCyclesAdjusted);
+ var serverGrowth = Math.pow(CONSTANTS.ServerGrowthRate, numServerGrowthCyclesAdjusted);
//console.log("serverGrowth ratio: " + serverGrowth);
server.moneyAvailable *= serverGrowth;
}
}
console.log("Server growth processed for " + numServerGrowthCycles + " cycles");
-},
+}
+
+//Applied server growth for a single server. Returns the percentage growth
+processSingleServerGrowth = function(server, numCycles) {
+ //Server growth processed once every 450 game cycles
+ var numServerGrowthCycles = Math.max(Math.floor(numCycles / 450), 0);
+
+ //Get the number of server growth cycles that will be applied based on the
+ //server's serverGrowth property
+ var serverGrowthPercentage = server.serverGrowth / 100;
+ var numServerGrowthCyclesAdjusted = numServerGrowthCycles * serverGrowthPercentage;
+
+ //Apply serverGrowth for the calculated number of growth cycles
+ var serverGrowth = Math.pow(CONSTANTS.ServerGrowthRate, numServerGrowthCyclesAdjusted);
+ server.moneyAvailable *= serverGrowth;
+
+ return serverGrowth;
+}
//List of all servers that exist in the game, indexed by their ip
AllServers = {};
diff --git a/src/Terminal.js b/src/Terminal.js
index 8c9a20fc3..4b6efaa5b 100644
--- a/src/Terminal.js
+++ b/src/Terminal.js
@@ -31,6 +31,12 @@ var postNetburnerText = function() {
$(document).keydown(function(event) {
//Terminal
if (Engine.currentPage == Engine.Page.Terminal) {
+ var terminalInput = document.getElementById("terminal-input-text-box");
+ if (terminalInput == null) {return;}
+
+ //Keep terminal input in focus
+ terminalInput.focus();
+
//Enter
if (event.keyCode == 13) {
var command = $('input[class=terminal-input]').val();
@@ -64,9 +70,8 @@ $(document).keydown(function(event) {
--Terminal.commandHistoryIndex;
}
var prevCommand = Terminal.commandHistory[Terminal.commandHistoryIndex];
- document.getElementById("terminal-input-text-box").value = prevCommand;
-
-
+ terminalInput.value = prevCommand;
+ setTimeout(function(){terminalInput.selectionStart = terminalInput.selectionEnd = 10000; }, 0);
}
//Down key
@@ -82,17 +87,17 @@ $(document).keydown(function(event) {
//Latest command, put nothing
if (i == len || i == len-1) {
Terminal.commandHistoryIndex = len;
- document.getElementById("terminal-input-text-box").value = "";
+ terminalInput.value = "";
} else {
++Terminal.commandHistoryIndex;
var prevCommand = Terminal.commandHistory[Terminal.commandHistoryIndex];
- document.getElementById("terminal-input-text-box").value = prevCommand;
+ terminalInput.value = prevCommand;
}
}
//Tab (autocomplete)
if (event.keyCode == 9) {
- var input = document.getElementById("terminal-input-text-box").value;
+ var input = terminalInput.value;
if (input == "") {return;}
input = input.trim();
input = input.replace(/\s\s+/g, ' ');
@@ -158,7 +163,9 @@ function tabCompletion(command, arg, allPossibilities) {
}
}
- if (allPossibilities.length == 1) {
+ if (allPossibilities.length == 0) {
+ return;
+ } else if (allPossibilities.length == 1) {
document.getElementById("terminal-input-text-box").value = command + " " + allPossibilities[0];
document.getElementById("terminal-input-text-box").focus();
} else {
diff --git a/utils/StringHelperFunctions.js b/utils/StringHelperFunctions.js
index e3399f777..a61a78687 100644
--- a/utils/StringHelperFunctions.js
+++ b/utils/StringHelperFunctions.js
@@ -46,6 +46,7 @@ function convertTimeMsToTimeElapsedString(time) {
//Finds the longest common starting substring in a set of strings
function longestCommonStart(strings) {
if (!containsAllStrings(strings)) {return;}
+ if (strings.length == 0) {return;}
var A = strings.concat().sort(),
a1= A[0], a2= A[A.length-1], L= a1.length, i= 0;