Lowered hacking exp gain. Added deleteServer(). Maximum of 25 purchaseable servers. Added autocompletion for ./ command. Oustanding faction invitations. Suppress Faction invites and messages

This commit is contained in:
danielyxie 2017-07-26 21:56:14 -05:00
parent 118118db83
commit 0e64359814
16 changed files with 644 additions and 575 deletions

@ -502,6 +502,11 @@
<h1> Factions </h1> <h1> Factions </h1>
<p> Lists all factions you have joined </p> <p> Lists all factions you have joined </p>
<ul class="factions-list" id="factions-list"></ul> <ul class="factions-list" id="factions-list"></ul>
<br><br>
<h1> Outstanding Faction Invitations </h1>
<p style="width:70%;"> Lists factions you have been invited to, as well as factions you have previously rejected.
You can accept these faction invitations at any times </p>
<ul class="factions-list" id="outstanding-faction-invitations-list"></ul>
</div> </div>
<!-- Single Faction info (when you select a faction from the Factions menu) --> <!-- Single Faction info (when you select a faction from the Factions menu) -->
@ -928,7 +933,7 @@
</span> </span>
</label> </label>
<input type ="range" max="100" min="20" <input type="range" max="100" min="20"
oninput="document.getElementById('settingsNSLogRangeValLabel').innerHTML = this.value; oninput="document.getElementById('settingsNSLogRangeValLabel').innerHTML = this.value;
Settings.MaxLogCapacity=this.value;" Settings.MaxLogCapacity=this.value;"
step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50"> step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50">
@ -946,7 +951,7 @@
</span> </span>
</label> </label>
<input type ="range" max="100" min="20" <input type="range" max="100" min="20"
oninput="document.getElementById('settingsNSPortRangeValLabel').innerHTML = this.value; oninput="document.getElementById('settingsNSPortRangeValLabel').innerHTML = this.value;
Settings.MaxPortCapacity=this.value;" Settings.MaxPortCapacity=this.value;"
step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50"> step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50">
@ -954,6 +959,31 @@
<em id="settingsNSPortRangeValLabel" style="font-style: normal;"></em> <em id="settingsNSPortRangeValLabel" style="font-style: normal;"></em>
</fieldset> </fieldset>
<!-- Suppress messages -->
<fieldset>
<label for="settingsSuppressMessages" class="tooltip">Suppress Messages:
<span class="tooltiptext">
If this is set, then any messages you receive will not appear as popups
on the screen. They will still get sent to your home computer as '.msg' files
and can be viewed with the 'cat' Terminal command.
</span>
</label>
<input type="checkbox" name="settingsSuppressMessages" id="settingsSuppressMessages"
onclick="Settings.SuppressMessages = this.checked;">
</fieldset>
<!-- Suppress faction invites -->
<fieldset>
<label for="settingsSuppressFactionInvites" class="tooltip">Suppress Faction Invites:
<span class="tooltiptext">
If this is set, then any faction invites you receive will not appear as popups
on the screen. Your outstanding faction invites can be viewed in the 'Factions' page.
</span>
</label>
<input type="checkbox" name="settingsSuppressFactionInvites" id="settingsSuppressFactionInvites"
onclick="Settings.SuppressFactionInvites = this.checked;">
</fieldset>
<!-- Donate button --> <!-- Donate button -->
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank"> <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
<input type="hidden" name="cmd" value="_s-xclick"> <input type="hidden" name="cmd" value="_s-xclick">

@ -61,9 +61,7 @@ CONSTANTS = {
ScriptHasRootAccessRamCost: 0.05, ScriptHasRootAccessRamCost: 0.05,
ScriptGetHostnameRamCost: 0.05, ScriptGetHostnameRamCost: 0.05,
ScriptGetHackingLevelRamCost: 0.05, ScriptGetHackingLevelRamCost: 0.05,
ScriptGetServerMoneyRamCost: 0.1, ScriptGetServerCost: 0.1,
ScriptGetServerSecurityRamCost: 0.1,
ScriptGetServerReqdHackRamCost: 0.1,
ScriptFileExistsRamCost: 0.1, ScriptFileExistsRamCost: 0.1,
ScriptIsRunningRamCost: 0.1, ScriptIsRunningRamCost: 0.1,
ScriptOperatorRamCost: 0.01, ScriptOperatorRamCost: 0.01,
@ -86,6 +84,8 @@ CONSTANTS = {
ServerFortifyAmount: 0.002, //Amount by which server's security increases when its hacked/grown ServerFortifyAmount: 0.002, //Amount by which server's security increases when its hacked/grown
ServerWeakenAmount: 0.05, //Amount by which server's security decreases when weakened ServerWeakenAmount: 0.05, //Amount by which server's security decreases when weakened
PurchasedServerLimit: 25,
//Augmentation Constants //Augmentation Constants
AugmentationCostMultiplier: 5, //Used for balancing costs without having to readjust every Augmentation cost AugmentationCostMultiplier: 5, //Used for balancing costs without having to readjust every Augmentation cost
AugmentationRepMultiplier: 2.5, //Used for balancing rep cost without having to readjust every value AugmentationRepMultiplier: 2.5, //Used for balancing rep cost without having to readjust every value
@ -678,7 +678,18 @@ CONSTANTS = {
"World Stock Exchange account and TIX API Access<br>", "World Stock Exchange account and TIX API Access<br>",
LatestUpdate: LatestUpdate:
"V0.26.1<br>" + "v0.26.2<br>" +
"-Significantly lowered hacking exp gain from hacking servers. The exp gain for higher-level servers was lowered more than " +
"that of low level servers. (~16% for lower level servers, up to ~25% for higher-level servers)<br>" +
"-Added deleteServer() Netscript function<br>" +
"-You can now purchase a maximum of 25 servers each run (Deleting a server will allow you to purchase a new one)<br>" +
"-Added autocompletion for './' Terminal command<br>" +
"-Darkweb prices now displayed properly using toLocaleString()<br>" +
"-Added NOT operator (!) and negation operator(-), so negative numbers should be functional now<br>" +
"-Rejected faction invitations will now show up as 'Outstanding Faction Invites' in the Factions page. These " +
"can be accepted at any point in the future<br>" +
"-Added a few more configurable game settings for suppressing messages and faction invitations<br>" +
"v0.26.1<br>" +
"-Added autocompletion for aliases<br>" + "-Added autocompletion for aliases<br>" +
"-Added getServerRam() Netscript function()<br>" + "-Added getServerRam() Netscript function()<br>" +
"-Added getLevelUpgradeCost(n), getRamUpgradeCost(), getCoreUpgradeCost() functions for Netscript Hacknet Node API<br>" + "-Added getLevelUpgradeCost(n), getRamUpgradeCost(), getCoreUpgradeCost() functions for Netscript Hacknet Node API<br>" +

@ -41,9 +41,39 @@ executeDarkwebTerminalCommand = function(commandArray) {
listAllDarkwebItems = function() { listAllDarkwebItems = function() {
for (var item in DarkWebItems) { for (var item in DarkWebItems) {
if (DarkWebItems.hasOwnProperty(item)) { if (DarkWebItems.hasOwnProperty(item)) {
post(DarkWebItems[item]); var item = DarkWebItems[item];
//Convert string using toLocaleString
var split = item.split(" - ");
if (split.length == 3 && split[1].charAt(0) == '$') {
split[1] = split[1].slice(1);
split[1] = split[1].replace(/,/g, '');
var price = parseFloat(split[1]);
if (isNaN(price)) {
post(item);
return;
}
price = formatNumber(price, 0);
split[1] = "$" + price.toString();
post(split.join(" - "));
} else {
post(item);
}
} }
} }
var priceString = split[1];
//Check for errors
if (priceString.length == 0 || priceString.charAt(0) != '$') {
return -1;
}
//Remove dollar sign and commas
priceString = priceString.slice(1);
priceString = priceString.replace(/,/g, '');
//Convert string to numeric
var price = parseFloat(priceString);
if (isNaN(price)) {return -1;}
else {return price;}
} }
buyDarkwebItem = function(itemName) { buyDarkwebItem = function(itemName) {

@ -630,7 +630,12 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
} }
inviteToFaction = function(faction) { inviteToFaction = function(faction) {
factionInvitationBoxCreate(faction); if (Settings.SuppressFactionInvites) {
faction.alreadyInvited = true;
Player.factionInvitations.push(faction.name);
} else {
factionInvitationBoxCreate(faction);
}
} }
joinFaction = function(faction) { joinFaction = function(faction) {

@ -20,7 +20,9 @@ Reviver.constructors.Message = Message;
function sendMessage(msg) { function sendMessage(msg) {
console.log("sending message: " + msg.filename); console.log("sending message: " + msg.filename);
msg.recvd = true; msg.recvd = true;
showMessage(msg); if (!Settings.SuppressMessages) {
showMessage(msg);
}
addMessageToServer(msg, "home"); addMessageToServer(msg, "home");
} }

@ -131,6 +131,14 @@ function evaluate(exp, workerScript) {
reject(e); reject(e);
}); });
break; break;
case "UnaryExpression":
var p = evalUnary(exp, workerScript, resolve, reject);
p.then(function(res) {
resolve(res);
}).catch(function(e) {
reject(e);
});
break;
case "AssignmentExpression": case "AssignmentExpression":
var p = evalAssignment(exp, workerScript); var p = evalAssignment(exp, workerScript);
p.then(function(res) { p.then(function(res) {
@ -210,58 +218,6 @@ function evaluate(exp, workerScript) {
}); // End Promise }); // End Promise
} }
/*
function evalFunction(exp, workerScript){
return new Promise(function(resolve, reject) {
if (exp.callee.type!="Identifier"){
reject(makeRuntimeRejectMsg(workerScript, "callee must be an Identifier"));
return;
}
switch(exp.callee.name){
case "print":
if (exp.arguments.length != 1) {
return reject(makeRuntimeRejectMsg(workerScript, "print() call has incorrect number of arguments. Takes 1 argument"));
}
var evaluatePromise = evaluate(exp.arguments[0], workerScript);
evaluatePromise.then(function(res) {
workerScript.scriptRef.log(res.toString());
resolve(true);
}).catch(function(e) {
reject(e);
});
break;
case "scan":
if (exp.arguments.length != 1) {
exp.arguments = [{value:Player.getCurrentServer().hostname,type:"Literal"}];
}
var ipPromise = evaluate(exp.arguments[0], workerScript);
ipPromise.then(function (ip) {
var server = getServer(ip);
if (server == null) {
workerScript.scriptRef.log('getServerOpenPortsCount() failed. Invalid IP or hostname passed in: ' + ip);
return reject(makeRuntimeRejectMsg(workerScript, 'Invalid IP or hostname passed into getServerOpenPortsCount() command'));
}
var out = [];
for (var i = 0; i < server.serversOnNetwork.length; i++) {
var entry = server.getServerOnNetwork(i).hostname;
if (entry == null) {
continue;
}
out.push(entry);
}
workerScript.scriptRef.log('scan() returned ' + server.serversOnNetwork.length + ' connections for ' + server.hostname);
resolve(out);
}).catch(function(e) {
reject(e);
});
break;
default:
reject(makeRuntimeRejectMsg(workerScript, "Invalid function: " + exp.callee));
}
});
}
*/
function evalBinary(exp, workerScript){ function evalBinary(exp, workerScript){
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
var expLeftPromise = evaluate(exp.left, workerScript); var expLeftPromise = evaluate(exp.left, workerScript);
@ -329,17 +285,24 @@ function evalBinary(exp, workerScript){
} }
function evalUnary(exp, workerScript){ function evalUnary(exp, workerScript){
var env = workerScript.env;
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
var expLeftPromise = evaluate(exp.left, workerScript); if (env.stopFlag) {return reject(workerScript);}
expLeftPromise.then(function(expLeft) { var p = evaluate(exp.argument, workerScript);
switch(exp.operator){ p.then(function(res) {
case "++": if (exp.operator == "!") {
break resolve(!res);
case "--": } else if (exp.operator == "-") {
break; if (isNaN(res)) {
resolve(res);
} else {
resolve(-1 * res);
}
} else {
reject(makeRuntimeRejectMsg(workerScript, "Unimplemented unary operator: " + exp.operator));
} }
}, function(e) { }).catch(function(e) {
reject(e); reject(e);
}); });
}); });
} }
@ -534,113 +497,6 @@ function evaluateWhile(exp, workerScript) {
}); });
} }
/*
function evaluateHacknetNode(exp, workerScript) {
console.log("here");
var env = workerScript.env;
return new Promise(function(resolve, reject) {
setTimeout(function() {
if (exp.index == null) {
if ((exp.op.type == "call" && exp.op.func.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) || arg < 0) {
reject(makeRuntimeRejectMsg(workerScript, "Invalid argument passed into upgradeLevel()"));
return;
}
arg = Math.round(arg);
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) { function evaluateProg(exp, workerScript, index) {
var env = workerScript.env; var env = workerScript.env;
@ -791,7 +647,7 @@ function scriptCalculateExpGain(server) {
if (server.baseDifficulty == null) { if (server.baseDifficulty == null) {
server.baseDifficulty = server.hackDifficulty; server.baseDifficulty = server.hackDifficulty;
} }
return (server.baseDifficulty * Player.hacking_exp_mult * 0.4 + 2); return (server.baseDifficulty * Player.hacking_exp_mult * 0.3 + 2);
} }
//The same as Player's calculatePercentMoneyHacked() function but takes in the server as an argument //The same as Player's calculatePercentMoneyHacked() function but takes in the server as an argument

@ -654,6 +654,12 @@ function NetscriptFunctions(workerScript) {
return ""; return "";
} }
if (Player.purchasedServers.length >= CONSTANTS.PurchasedServerLimit) {
workerScript.scriptRef.log("Error: You have reached the maximum limit of " + CONSTANTS.PurchasedServerLimit +
" servers. You cannot purchase any more.");
return "";
}
ram = Math.round(ram); ram = Math.round(ram);
if (isNaN(ram) || !powerOfTwo(ram)) { if (isNaN(ram) || !powerOfTwo(ram)) {
workerScript.scriptRef.log("Error: Invalid ram argument passed to purchaseServer(). Must be numeric and a power of 2"); workerScript.scriptRef.log("Error: Invalid ram argument passed to purchaseServer(). Must be numeric and a power of 2");
@ -677,6 +683,56 @@ function NetscriptFunctions(workerScript) {
workerScript.scriptRef.log("Purchased new server with hostname " + newServ.hostname + " for $" + formatNumber(cost, 2)); workerScript.scriptRef.log("Purchased new server with hostname " + newServ.hostname + " for $" + formatNumber(cost, 2));
return newServ.hostname; return newServ.hostname;
}, },
deleteServer : function(hostname) {
var hostnameStr = String(hostname);
hostnameStr = hostnameStr.replace(/\s\s+/g, '');
var server = GetServerByHostname(hostnameStr);
if (server == null) {
workerScript.scriptRef.log("Error: Could not find server with hostname " + hostnameStr + ". deleteServer() failed");
return false;
}
if (!server.purchasedByPlayer) {
workerScript.scriptRef.log("Error: Server " + server.hostname + " is not a purchased server. " +
"Cannot be deleted. deleteSErver failed");
return false;
}
var ip = server.ip;
//Delete from all servers
delete AllServers[ip];
//Delete from player's purchasedServers array
var found = false;
for (var i = 0; i < Player.purchasedServers.length; ++i) {
if (ip == Player.purchasedServers[i]) {
found = true;
Player.purchasedServers.splice(i, 1);
break;
}
}
if (!found) {
workerScript.scriptRef.log("Error: Could not identify server " + server.hostname +
"as a purchased server. This is likely a bug please contact game dev");
return false;
}
//Delete from home computer
found = false;
var homeComputer = Player.getHomeComputer();
for (var i = 0; i < homeComputer.serversOnNetwork.length; ++i) {
if (ip == homeComputer.serversOnNetwork[i]) {
homeComputer.serversOnNetwork.splice(i, 1);
workerScript.scriptRef.log("Deleted server " + hostnameStr);
return true;
}
}
//Wasn't found on home computer
workerScript.scriptRef.log("Error: Could not find server " + server.hostname +
"as a purchased server. This is likely a bug please contact game dev");
return false;
},
round : function(n) { round : function(n) {
if (isNaN(n)) {return 0;} if (isNaN(n)) {return 0;}
return Math.round(n); return Math.round(n);

@ -85,7 +85,8 @@ function PlayerObject() {
this.totalHacknetNodeProduction = 0; this.totalHacknetNodeProduction = 0;
//Factions //Factions
this.factions = []; //Names of all factions player has joined this.factions = []; //Names of all factions player has joined
this.factionInvitations = []; //Outstanding faction invitations
//Augmentations //Augmentations
this.queuedAugmentations = []; //Purchased but not installed, names only this.queuedAugmentations = []; //Purchased but not installed, names only
@ -268,7 +269,7 @@ PlayerObject.prototype.calculateExpGain = function() {
if (s.baseDifficulty == null) { if (s.baseDifficulty == null) {
s.baseDifficulty = s.hackDifficulty; s.baseDifficulty = s.hackDifficulty;
} }
return (s.baseDifficulty * this.hacking_exp_mult * 0.4 + 2); return (s.baseDifficulty * this.hacking_exp_mult * 0.3 + 2);
} }
//Hack/Analyze a server. Return the amount of time the hack will take. This lets the Terminal object know how long to disable itself for //Hack/Analyze a server. Return the amount of time the hack will take. This lets the Terminal object know how long to disable itself for
@ -1243,6 +1244,3 @@ PlayerObject.fromJSON = function(value) {
Reviver.constructors.PlayerObject = PlayerObject; Reviver.constructors.PlayerObject = PlayerObject;
Player = new PlayerObject(); Player = new PlayerObject();

@ -74,6 +74,7 @@ function prestigeAugmentation() {
Player.purchasedServers = []; Player.purchasedServers = [];
Player.factions = []; Player.factions = [];
Player.factionInvitations = [];
Player.queuedAugmentations = []; Player.queuedAugmentations = [];

@ -173,6 +173,8 @@ function calculateRamUsage(codeCopy) {
var getServerSecurityCount = numOccurrences(codeCopy, "getServerSecurityLevel("); var getServerSecurityCount = numOccurrences(codeCopy, "getServerSecurityLevel(");
var getServerBaseSecurityCount = numOccurrences(codeCopy, "getServerBaseSecurityLevel("); var getServerBaseSecurityCount = numOccurrences(codeCopy, "getServerBaseSecurityLevel(");
var getServerReqdHackingCount = numOccurrences(codeCopy, "getServerRequiredHackingLevel("); var getServerReqdHackingCount = numOccurrences(codeCopy, "getServerRequiredHackingLevel(");
var getServerNumPortsReqdCount = numOccurrences(codeCopy, "getServerNumPortsRequired(");
var getServerRamCount = numOccurrences(codeCopy, "getServerRam(");
var fileExistsCount = numOccurrences(codeCopy, "fileExists("); var fileExistsCount = numOccurrences(codeCopy, "fileExists(");
var isRunningCount = numOccurrences(codeCopy, "isRunning("); var isRunningCount = numOccurrences(codeCopy, "isRunning(");
var numOperators = numNetscriptOperators(codeCopy); var numOperators = numNetscriptOperators(codeCopy);
@ -185,7 +187,8 @@ function calculateRamUsage(codeCopy) {
numOccurrences(codeCopy, "getStockPosition("); numOccurrences(codeCopy, "getStockPosition(");
var scriptBuySellStockCount = numOccurrences(codeCopy, "buyStock(") + var scriptBuySellStockCount = numOccurrences(codeCopy, "buyStock(") +
numOccurrences(codeCopy, "sellStock("); numOccurrences(codeCopy, "sellStock(");
var scriptPurchaseServerCount = numOccurrences(codeCopy, "purchaseServer("); var scriptPurchaseServerCount = numOccurrences(codeCopy, "purchaseServer(") +
numOccurrences(codeCopy, "deleteServer(");
var scriptRoundCount = numOccurrences(codeCopy, "round("); var scriptRoundCount = numOccurrences(codeCopy, "round(");
var scriptWriteCount = numOccurrences(codeCopy, "write("); var scriptWriteCount = numOccurrences(codeCopy, "write(");
var scriptReadCount = numOccurrences(codeCopy, "read("); var scriptReadCount = numOccurrences(codeCopy, "read(");
@ -210,11 +213,13 @@ function calculateRamUsage(codeCopy) {
(hasRootAccessCount * CONSTANTS.ScriptHasRootAccessRamCost) + (hasRootAccessCount * CONSTANTS.ScriptHasRootAccessRamCost) +
(getHostnameCount * CONSTANTS.ScriptGetHostnameRamCost) + (getHostnameCount * CONSTANTS.ScriptGetHostnameRamCost) +
(getHackingLevelCount * CONSTANTS.ScriptGetHackingLevelRamCost) + (getHackingLevelCount * CONSTANTS.ScriptGetHackingLevelRamCost) +
(getServerMoneyAvailableCount * CONSTANTS.ScriptGetServerMoneyRamCost) + (getServerMoneyAvailableCount * CONSTANTS.ScriptGetServerCost) +
(getServerMaxMoneyCount * CONSTANTS.ScriptGetServerMoneyRamCost) + (getServerMaxMoneyCount * CONSTANTS.ScriptGetServerCost) +
(getServerSecurityCount * CONSTANTS.ScriptGetServerSecurityRamCost) + (getServerSecurityCount * CONSTANTS.ScriptGetServerCost) +
(getServerBaseSecurityCount * CONSTANTS.ScriptGetServerSecurityRamCost) + (getServerBaseSecurityCount * CONSTANTS.ScriptGetServerCost) +
(getServerReqdHackingCount * CONSTANTS.ScriptGetServerReqdHackRamCost) + (getServerReqdHackingCount * CONSTANTS.ScriptGetServerCost) +
(getServerNumPortsReqdCount * CONSTANTS.ScriptGetServerCost) +
(getServerRamCount * CONSTANTS.ScriptGetServerCost) +
(fileExistsCount * CONSTANTS.ScriptFileExistsRamCost) + (fileExistsCount * CONSTANTS.ScriptFileExistsRamCost) +
(isRunningCount * CONSTANTS.ScriptIsRunningRamCost) + (isRunningCount * CONSTANTS.ScriptIsRunningRamCost) +
(numOperators * CONSTANTS.ScriptOperatorRamCost) + (numOperators * CONSTANTS.ScriptOperatorRamCost) +

@ -9,6 +9,14 @@ purchaseServer = function(ram, cost) {
return; return;
} }
//Maximum of 30 servers
if (Player.purchasedServers.length >= CONSTANTS.PurchasedServerLimit) {
dialogBoxCreate("You have reached the maximum limit of " + CONSTANTS.PurchasedServerLimit + " servers. " +
"You cannot purchase any more. You can " +
"delete some of your purchased servers using the deleteServer() Netscript function in a script");
return;
}
var newServ = new Server(); var newServ = new Server();
var hostname = document.getElementById("purchase-server-box-input").value; var hostname = document.getElementById("purchase-server-box-input").value;
hostname = hostname.replace(/\s\s+/g, ''); hostname = hostname.replace(/\s\s+/g, '');

@ -1,16 +1,18 @@
/* Settings.js */ /* Settings.js */
Settings = { Settings = {
CodeInstructionRunTime: 100, CodeInstructionRunTime: 100,
suppressMessages: false,
MaxLogCapacity: 50, MaxLogCapacity: 50,
MaxPortCapacity: 50, MaxPortCapacity: 50,
SuppressMessages: false,
SuppressFactionInvites: false,
} }
function initSettings() { function initSettings() {
Settings.CodeInstructionRunTime = 100; Settings.CodeInstructionRunTime = 100;
Settings.suppressMessages = false;
Settings.MaxLogCapacity = 50; Settings.MaxLogCapacity = 50;
Settings.MaxPortCapacity = 50; Settings.MaxPortCapacity = 50;
Settings.SuppressMessages = false;
Settings.SuppressFactionInvites = false;
} }
function setSettingsLabels() { function setSettingsLabels() {
@ -20,4 +22,8 @@ function setSettingsLabels() {
= Settings.MaxLogCapacity; = Settings.MaxLogCapacity;
document.getElementById("settingsNSPortRangeValLabel").innerHTML document.getElementById("settingsNSPortRangeValLabel").innerHTML
= Settings.MaxPortCapacity; = Settings.MaxPortCapacity;
document.getElementById("settingsSuppressMessages").checked
= Settings.SuppressMessages;
document.getElementById("settingsSuppressFactionInvites").checked
= Settings.SuppressFactionInvites;
} }

@ -175,7 +175,9 @@ function tabCompletion(command, arg, allPossibilities, index=0) {
if (!(allPossibilities.constructor === Array)) {return;} if (!(allPossibilities.constructor === Array)) {return;}
if (!containsAllStrings(allPossibilities)) {return;} if (!containsAllStrings(allPossibilities)) {return;}
command = command.toLowerCase(); if (!command.startsWith("./")) {
command = command.toLowerCase();
}
//Remove all options in allPossibilities that do not match the current string //Remove all options in allPossibilities that do not match the current string
//that we are attempting to autocomplete //that we are attempting to autocomplete
@ -243,6 +245,23 @@ function determineAllPossibilitiesForTabCompletion(input, index=0) {
var currServ = Player.getCurrentServer(); var currServ = Player.getCurrentServer();
input = input.toLowerCase(); input = input.toLowerCase();
//If the command starts with './' and the index == -1, then the user
//has input ./partialexecutablename so autocomplete the script or program
//Put './' in front of each script/executable
if (input.startsWith("./") && index == -1) {
//All programs and scripts
for (var i = 0; i < currServ.scripts.length; ++i) {
allPos.push("./" + currServ.scripts[i].filename);
}
//Programs are on home computer
var homeComputer = Player.getHomeComputer();
for(var i = 0; i < homeComputer.programs.length; ++i) {
allPos.push("./" + homeComputer.programs[i]);
}
return allPos;
}
//Autocomplete the command //Autocomplete the command
if (index == -1) { if (index == -1) {
return ["alias", "analyze", "cat", "check", "clear", "cls", "connect", "free", return ["alias", "analyze", "cat", "check", "clear", "cls", "connect", "free",
@ -447,7 +466,7 @@ var Terminal = {
//Allow usage of ./ //Allow usage of ./
if (command.startsWith("./")) { if (command.startsWith("./")) {
command = command.slice(0, 2) + " " + command.slice(2); command = "run " + command.slice(2);
} }
//Only split the first space //Only split the first space
@ -895,7 +914,6 @@ var Terminal = {
post("No such file exists"); post("No such file exists");
break; break;
case "run": case "run":
case "./":
//Run a program or a script //Run a program or a script
if (commandArray.length != 2) { if (commandArray.length != 2) {
post("Incorrect number of arguments. Usage: run [program/script] [-t] [num threads] [arg1] [arg2]..."); post("Incorrect number of arguments. Usage: run [program/script] [-t] [num threads] [arg1] [arg2]...");

@ -485,9 +485,8 @@ var Engine = {
}, },
displayFactionsInfo: function() { displayFactionsInfo: function() {
//Clear the list of joined factions
var factionsList = document.getElementById("factions-list"); var factionsList = document.getElementById("factions-list");
//Clear the list
while (factionsList.firstChild) { while (factionsList.firstChild) {
factionsList.removeChild(factionsList.firstChild); factionsList.removeChild(factionsList.firstChild);
} }
@ -500,7 +499,6 @@ var Engine = {
//Add the faction to the Factions page content //Add the faction to the Factions page content
var item = document.createElement("li"); var item = document.createElement("li");
var aElem = document.createElement("a"); var aElem = document.createElement("a");
aElem.setAttribute("href", "#");
aElem.setAttribute("class", "a-link-button"); aElem.setAttribute("class", "a-link-button");
aElem.innerHTML = factionName; aElem.innerHTML = factionName;
aElem.addEventListener("click", function() { aElem.addEventListener("click", function() {
@ -509,10 +507,54 @@ var Engine = {
return false; return false;
}); });
item.appendChild(aElem); item.appendChild(aElem);
factionsList.appendChild(item); factionsList.appendChild(item);
}()); //Immediate invocation }()); //Immediate invocation
} }
//Clear the list of invitations
var invitationsList = document.getElementById("outstanding-faction-invitations-list");
while (invitationsList.firstChild) {
invitationsList.removeChild(invitationsList.firstChild);
}
//Add a link to accept for each faction you have invitiations for
for (var i = 0; i < Player.factionInvitations.length; ++i) {
(function () {
var factionName = Player.factionInvitations[i];
var item = document.createElement("li");
var pElem = document.createElement("p");
pElem.innerText = factionName;
pElem.style.display = "inline";
pElem.style.margin = "4px";
pElem.style.padding = "4px";
var aElem = document.createElement("a");
aElem.innerText = "Accept Faction Invitation";
aElem.setAttribute("class", "a-link-button");
aElem.style.display = "inline";
aElem.style.margin = "4px";
aElem.style.padding = "4px";
aElem.addEventListener("click", function() {
joinFaction(Factions[factionName]);
for (var i = 0; i < Player.factionInvitations.length; ++i) {
if (Player.factionInvitations[i] == factionName) {
Player.factionInvitations.splice(i, 1);
break;
}
}
Engine.displayFactionsInfo();
return false;
});
item.appendChild(pElem);
item.appendChild(aElem);
item.style.margin = "6px";
item.style.padding = "6px";
invitationsList.appendChild(item);
}());
}
}, },
displayAugmentationsContent: function() { displayAugmentationsContent: function() {
@ -693,7 +735,7 @@ var Engine = {
updateSkillLevelsCounter: 10, //Only update skill levels every 2 seconds. Might improve performance updateSkillLevelsCounter: 10, //Only update skill levels every 2 seconds. Might improve performance
updateDisplays: 3, //Update displays such as Active Scripts display and character display updateDisplays: 3, //Update displays such as Active Scripts display and character display
createProgramNotifications: 10, //Checks whether any programs can be created and notifies createProgramNotifications: 10, //Checks whether any programs can be created and notifies
checkFactionInvitations: 100, //Check whether you qualify for any faction invitations every 5 minutes checkFactionInvitations: 100, //Check whether you qualify for any faction invitations
passiveFactionGrowth: 600, passiveFactionGrowth: 600,
messages: 150, messages: 150,
stockTick: 30, //Update stock prices stockTick: 30, //Update stock prices

@ -35,6 +35,7 @@ factionInvitationBoxCreate = function(faction) {
noButton.addEventListener("click", function() { noButton.addEventListener("click", function() {
factionInvitationBoxClose(); factionInvitationBoxClose();
faction.alreadyInvited = true; faction.alreadyInvited = true;
Player.factionInvitations.push(faction.name);
return false; return false;
}); });