mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-20 05:05:47 +01:00
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
This commit is contained in:
parent
6316cbae23
commit
8cd9e8954d
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}, 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);
|
||||
resolve(numOwned);
|
||||
}, 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")
|
||||
|
@ -187,9 +187,49 @@ 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 {
|
||||
type : "bool",
|
||||
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user