mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-18 12:15:44 +01:00
Added Callback function to installAugmentations(). Implemented Source-File 5. Added player-defined functions to Netscript (not thoroughly tested). Began working on Hacking Mission Enemy 'AI'
This commit is contained in:
parent
1233d487d9
commit
26fe9eb519
@ -1,16 +1,26 @@
|
||||
/* css for Missions */
|
||||
|
||||
/* Hacking missions */
|
||||
#mission-container {
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
.hack-mission-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 10% 10% 10% 10% 10% 10% 10% 10%;
|
||||
grid-template-rows: 8% 8% 8% 8% 8% 8% 8% 8%;
|
||||
/*grid-template-columns: 11% 11% 11% 11% 11% 11% 11% 11%;*/
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||
/*grid-template-rows: 10% 10% 10% 10% 10% 10% 10% 10%;*/
|
||||
grid-template-rows: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||
grid-gap: 2.5%;
|
||||
height: 100%;
|
||||
position:fixed;
|
||||
position:absolute;
|
||||
width: 100%;
|
||||
overflow-y:auto;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.hack-mission-grid::-webkit-scrollbar {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.hack-mission-node {
|
||||
|
@ -2,6 +2,7 @@
|
||||
.generic-fullscreen-container {
|
||||
color: var(--my-font-color);
|
||||
width: 99%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#work-in-progress-container {
|
||||
|
9906
dist/bundle.js
vendored
9906
dist/bundle.js
vendored
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,11 @@
|
||||
import {BitNodeMultipliers} from "./BitNode.js";
|
||||
import {CONSTANTS} from "./Constants.js";
|
||||
import {Factions, getNextNeurofluxLevel} from "./Faction.js";
|
||||
import {addWorkerScript} from "./NetscriptWorker.js";
|
||||
import {Player} from "./Player.js";
|
||||
import {prestigeAugmentation} from "./Prestige.js";
|
||||
import {Factions, getNextNeurofluxLevel} from "./Faction.js";
|
||||
import {Script, RunningScript} from "./Script.js";
|
||||
import {Server} from "./Server.js";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox.js";
|
||||
import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver.js";
|
||||
@ -1910,7 +1913,7 @@ function PlayerOwnedAugmentation(name) {
|
||||
this.level = 1;
|
||||
}
|
||||
|
||||
function installAugmentations() {
|
||||
function installAugmentations(cbScript=null) {
|
||||
if (Player.queuedAugmentations.length == 0) {
|
||||
dialogBoxCreate("You have not purchased any Augmentations to install!");
|
||||
return false;
|
||||
@ -1930,6 +1933,25 @@ function installAugmentations() {
|
||||
"to install the following Augmentations:<br>" + augmentationList +
|
||||
"<br>You wake up in your home...you feel different...");
|
||||
prestigeAugmentation();
|
||||
|
||||
//Run a script after prestiging
|
||||
if (cbScript) {
|
||||
var home = Player.getHomeComputer();
|
||||
for (var i = 0; i < home.scripts.length; ++i) {
|
||||
if (home.scripts[i].filename === cbScript) {
|
||||
var script = home.scripts[i];
|
||||
var ramUsage = script.ramUsage;
|
||||
var ramAvailable = home.maxRam - home.ramUsed;
|
||||
if (ramUsage > ramAvailable) {
|
||||
return; //Not enough RAM
|
||||
}
|
||||
var runningScriptObj = new RunningScript(script, []); //No args
|
||||
runningScriptObj.threads = 1; //Only 1 thread
|
||||
home.runningScripts.push(runningScriptObj);
|
||||
addWorkerScript(runningScriptObj, home);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function augmentationExists(name) {
|
||||
|
@ -34,7 +34,6 @@ let CONSTANTS = {
|
||||
CompanyReputationToFavorBase: 500,
|
||||
CompanyReputationToFavorMult: 1.02,
|
||||
|
||||
|
||||
/* Augmentation */
|
||||
//NeuroFlux Governor cost multiplier as you level up
|
||||
NeuroFluxGovernorLevelMult: 1.14,
|
||||
@ -515,11 +514,12 @@ let CONSTANTS = {
|
||||
"must be a string containing the hostname or IP of the target server. This function will always return true. <br><br>" +
|
||||
"<i>scp(script, [source], destination)</i><br>Copies a script or literature (.lit) file to another server. The first argument is a string with " +
|
||||
"the filename of the script or literature file " +
|
||||
"to be copied. The next two arguments are strings containing the hostname/IPs of the source and target server. " +
|
||||
"to be copied, or an array of filenames to be copied. The next two arguments are strings containing the hostname/IPs of the source and target server. " +
|
||||
"The source refers to the server from which the script/literature file will be copied, while the destination " +
|
||||
"refers to the server to which it will be copied. The source server argument is optional, and if ommitted the source " +
|
||||
"will be the current server (the server on which the script is running). Returns true if the script/literature file is " +
|
||||
"successfully copied over and false otherwise. <br><br>" +
|
||||
"successfully copied over and false otherwise. If the first argument passed in is an array, then the function " +
|
||||
"will return if at least one of the files in the array is successfully copied over.<br><br>" +
|
||||
"Example: scp('hack-template.script', 'foodnstuff'); //Copies hack-template.script from the current server to foodnstuff<br>" +
|
||||
"Example: scp('foo.lit', 'helios', 'home'); //Copies foo.lit from the helios server to the home computer<br><br>" +
|
||||
"<i>ls(hostname/ip)</i><br>Returns an array containing the names of all files on the specified server. The argument must be a " +
|
||||
@ -632,6 +632,9 @@ let CONSTANTS = {
|
||||
"an empty string. The function will fail if the arguments passed in are invalid or if the player does not have enough money to purchase the specified server.<br><br>" +
|
||||
"<i>deleteServer(hostname)</i><br>Deletes one of the servers you've purchased with the specified hostname. The function will fail if " +
|
||||
"there are any scripts running on the specified server. Returns true if successful and false otherwise<br><br>" +
|
||||
"<i>getPurchasedServers([hostname=true])</i><br>Returns an array with either the hostname or IPs of all of the servers you " +
|
||||
"have purchased. It takes an optional parameter specifying whether the hostname or IP addresses will be returned. If this " +
|
||||
"parameter is not specified, it is true by default and hostnames will be returned<br><br>" +
|
||||
"<i>round(n)</i><br>Rounds the number n to the nearest integer. If the argument passed in is not a number, then the function will return 0.<br><br>" +
|
||||
"<i>write(port, data)</i><br>Writes data to a port. The first argument must be a number between 1 and 10 that specifies the port. The second " +
|
||||
"argument defines the data to write to the port. If the second argument is not specified then it will write an empty string to the port.<br><br>" +
|
||||
@ -1008,6 +1011,11 @@ let CONSTANTS = {
|
||||
"World Stock Exchange account and TIX API Access<br>",
|
||||
|
||||
LatestUpdate:
|
||||
"v0.29.2<br>" +
|
||||
"-installAugmentations() Singularity Function now takes a callback script as an argument. This is a script " +
|
||||
"that gets ran automatically after Augmentations are installed. The script is run with no arguments and only a single thread, " +
|
||||
"and must be found on your home computer.<br>" +
|
||||
"-Added functions to Netscript. See the link here for details<br>" +
|
||||
"v0.29.1<br>" +
|
||||
"-New gameplay feature that is currently in BETA: Hacking Missions. Hacking Missions is an active gameplay mechanic (its a minigame) " +
|
||||
"that is meant to be used to earn faction reputation. However, since this is currently in beta, hacking missions will NOT grant reputation " +
|
||||
|
@ -820,6 +820,15 @@ HackingMission.prototype.nodeReachable = function(node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HackingMission.prototype.nodeReachableByEnemy = function(node) {
|
||||
var x = node.pos[0], y = node.pos[1];
|
||||
if (x > 0 && this.map[x-1][y].enmyCtrl) {return true;}
|
||||
if (x < 7 && this.map[x+1][y].enmyCtrl) {return true;}
|
||||
if (y > 0 && this.map[x][y-1].enmyCtrl) {return true;}
|
||||
if (y < 7 && this.map[x][y+1].enmyCtrl) {return true;}
|
||||
return false;
|
||||
}
|
||||
|
||||
HackingMission.prototype.start = function() {
|
||||
this.started = true;
|
||||
this.initJsPlumb();
|
||||
@ -1169,6 +1178,53 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) {
|
||||
return calcStats;
|
||||
}
|
||||
|
||||
//Enemy "AI" for CPU Cor eand Transfer Nodes
|
||||
HackingMission.prototype.enemyAISelectAction = function(nodeObj) {
|
||||
if (nodeObj === null) {return;}
|
||||
switch(nodeObj.type) {
|
||||
case NodeTypes.Core:
|
||||
//Select a single RANDOM target from miscNodes and player's Nodes
|
||||
//If it is reachable, it will target it. If not, no target will
|
||||
//be selected for now, and the next time process() gets called this will repeat
|
||||
if (nodeObj.conn === null) {
|
||||
if (this.miscNodes.length === 0) {
|
||||
var rand = getRandomInt(0, this.playerNodes.length-1);
|
||||
var node = this.playerNodes[rand];
|
||||
if (this.nodeReachableByEnemy(node)) {
|
||||
//TODO Create connection
|
||||
} else {
|
||||
rand = getRandomInt(0, this.playerCores.length-1);
|
||||
node = this.playerCores[rand];
|
||||
if (this.nodeReachableByEnemy(node)) {
|
||||
//TODO Create connection
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var rand = getRandomInt(0, this.miscNodes.length-1);
|
||||
var node = this.miscNodes[rand];
|
||||
if (this.nodeReachableByEnemy(node)) {
|
||||
//TODO Create connection to this Node
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Select action
|
||||
|
||||
break;
|
||||
case NodeTypes.Transfer:
|
||||
//Switch between fortifying and overflowing as necessary
|
||||
if (nodeObj.def < 500) {
|
||||
nodeObj.action = NodeActions.Fortify;
|
||||
} else {
|
||||
nodeObj.action = NodeActions.Overflow;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var hackEffWeightSelf = 150; //Weight for Node actions on self
|
||||
var hackEffWeightTarget = 25; //Weight for Node Actions against Target
|
||||
var hackEffWeightAttack = 110; //Weight for Attack action
|
||||
|
@ -15,7 +15,7 @@ Environment.prototype = {
|
||||
//Create a "subscope", which is a new new "sub-environment"
|
||||
//The subscope is linked to this through its parent variable
|
||||
extend: function() {
|
||||
return new Environment(this);
|
||||
return new Environment(null, this);
|
||||
},
|
||||
|
||||
//Finds the scope where the variable with the given name is defined
|
||||
|
@ -8,6 +8,7 @@ import {Settings} from "./Settings.js";
|
||||
import {Script, findRunningScript,
|
||||
RunningScript} from "./Script.js";
|
||||
|
||||
import {Node} from "../utils/acorn.js";
|
||||
import {printArray} from "../utils/HelperFunctions.js";
|
||||
import {isValidIPAddress} from "../utils/IPAddress.js";
|
||||
import {isString} from "../utils/StringHelperFunctions.js";
|
||||
@ -19,7 +20,7 @@ import {isString} from "../utils/StringHelperFunctions
|
||||
*/
|
||||
function evaluate(exp, workerScript) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var env = workerScript.env;
|
||||
var env = workerScript.env;
|
||||
if (env.stopFlag) {return reject(workerScript);}
|
||||
if (exp == null) {
|
||||
return reject(makeRuntimeRejectMsg(workerScript, "Error: NULL expression"));
|
||||
@ -33,7 +34,10 @@ function evaluate(exp, workerScript) {
|
||||
evaluateProgPromise.then(function(w) {
|
||||
resolve(workerScript);
|
||||
}, function(e) {
|
||||
if (isString(e)) {
|
||||
if (e.constructor === Array && e.length === 2 && e[0] === "RETURNSTATEMENT") {
|
||||
//Returning from a Player-defined function
|
||||
resolve(e[1]);
|
||||
} else if (isString(e)) {
|
||||
workerScript.errorMessage = e;
|
||||
reject(workerScript);
|
||||
} else if (e instanceof WorkerScript) {
|
||||
@ -55,7 +59,7 @@ function evaluate(exp, workerScript) {
|
||||
case "ExpressionStatement":
|
||||
var e = evaluate(exp.expression, workerScript);
|
||||
e.then(function(res) {
|
||||
resolve("expression done");
|
||||
resolve(res);
|
||||
}, function(e) {
|
||||
reject(e);
|
||||
});
|
||||
@ -76,7 +80,32 @@ function evaluate(exp, workerScript) {
|
||||
return evaluate(arg, workerScript);
|
||||
});
|
||||
Promise.all(argPromises).then(function(args) {
|
||||
if (exp.callee.type == "MemberExpression"){
|
||||
if (func instanceof Node) { //Player-defined function
|
||||
//Create new Environment for the function
|
||||
//Should be automatically garbage collected...
|
||||
var funcEnv = env.extend();
|
||||
|
||||
//Define function arguments in this new environment
|
||||
for (var i = 0; i < func.params.length; ++i) {
|
||||
var arg;
|
||||
if (i >= args.length) {
|
||||
arg = null;
|
||||
} else {
|
||||
arg = args[i];
|
||||
}
|
||||
funcEnv.def(func.params[i].name, arg);
|
||||
}
|
||||
|
||||
//Create a new WorkerScript for this function evaluation
|
||||
var funcWorkerScript = new WorkerScript(workerScript.scriptRef);
|
||||
funcWorkerScript.env = funcEnv;
|
||||
|
||||
evaluate(func.body, funcWorkerScript).then(function(res) {
|
||||
resolve(res);
|
||||
}).catch(function(e) {
|
||||
reject(e);
|
||||
});
|
||||
} else if (exp.callee.type == "MemberExpression"){
|
||||
evaluate(exp.callee.object, workerScript).then(function(object) {
|
||||
try {
|
||||
var res = func.apply(object,args);
|
||||
@ -125,7 +154,6 @@ function evaluate(exp, workerScript) {
|
||||
}
|
||||
resolve(object[index]);
|
||||
}).catch(function(e) {
|
||||
console.log("here");
|
||||
reject(makeRuntimeRejectMsg(workerScript, "Invalid MemberExpression"));
|
||||
});
|
||||
} else {
|
||||
@ -195,8 +223,14 @@ function evaluate(exp, workerScript) {
|
||||
resolve(false);
|
||||
break;
|
||||
case "ReturnStatement":
|
||||
var lineNum = getErrorLineNumber(exp, workerScript);
|
||||
reject(makeRuntimeRejectMsg(workerScript, "Return statements are not yet implemented in Netscript (line " + (lineNum+1) + ")"));
|
||||
console.log("Evaluating Return Statement");
|
||||
//var lineNum = getErrorLineNumber(exp, workerScript);
|
||||
//reject(makeRuntimeRejectMsg(workerScript, "Return statements are not yet implemented in Netscript (line " + (lineNum+1) + ")"));
|
||||
evaluate(exp.argument, workerScript).then(function(res) {
|
||||
reject(["RETURNSTATEMENT", res]);
|
||||
}).catch(function(e) {
|
||||
reject(e);
|
||||
});
|
||||
break;
|
||||
case "BreakStatement":
|
||||
reject("BREAKSTATEMENT");
|
||||
@ -206,7 +240,7 @@ function evaluate(exp, workerScript) {
|
||||
break;
|
||||
case "IfStatement":
|
||||
evaluateIf(exp, workerScript).then(function(forLoopRes) {
|
||||
resolve("forLoopDone");
|
||||
resolve(forLoopRes);
|
||||
}).catch(function(e) {
|
||||
reject(e);
|
||||
});
|
||||
@ -217,7 +251,7 @@ function evaluate(exp, workerScript) {
|
||||
break;e
|
||||
case "WhileStatement":
|
||||
evaluateWhile(exp, workerScript).then(function(forLoopRes) {
|
||||
resolve("forLoopDone");
|
||||
resolve(forLoopRes);
|
||||
}).catch(function(e) {
|
||||
if (e == "BREAKSTATEMENT" ||
|
||||
(e instanceof WorkerScript && e.errorMessage == "BREAKSTATEMENT")) {
|
||||
@ -241,6 +275,15 @@ function evaluate(exp, workerScript) {
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "FunctionDeclaration":
|
||||
if (exp.id && exp.id.name) {
|
||||
env.set(exp.id.name, exp);
|
||||
resolve(true);
|
||||
} else {
|
||||
var lineNum = getErrorLineNumber(exp, workerScript);
|
||||
reject(makeRuntimeRejectMsg(workerScript, "Invalid function declaration at line " + lineNum+1));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
var lineNum = getErrorLineNumber(exp, workerScript);
|
||||
reject(makeRuntimeRejectMsg(workerScript, "Unrecognized token: " + exp.type + " (line " + (lineNum+1) + "). This is currently unsupported in Netscript"));
|
||||
|
@ -12,7 +12,6 @@ import {parse} from "../utils/acorn.js";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox.js";
|
||||
import {compareArrays, printArray} from "../utils/HelperFunctions.js";
|
||||
|
||||
|
||||
function WorkerScript(runningScriptObj) {
|
||||
this.name = runningScriptObj.filename;
|
||||
this.running = false;
|
||||
@ -93,7 +92,7 @@ function runScriptsLoop() {
|
||||
if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) {
|
||||
try {
|
||||
var ast = parse(workerScripts[i].code);
|
||||
//console.log(ast);
|
||||
console.log(ast);
|
||||
} catch (e) {
|
||||
console.log("Error parsing script: " + workerScripts[i].name);
|
||||
dialogBoxCreate("Syntax ERROR in " + workerScripts[i].name + ":<br>" + e);
|
||||
@ -180,6 +179,14 @@ function addWorkerScript(runningScriptObj, server) {
|
||||
}
|
||||
var ramUsage = runningScriptObj.scriptRef.ramUsage * threads
|
||||
* Math.pow(CONSTANTS.MultithreadingRAMCost, threads-1);
|
||||
var ramAvailable = server.maxRam - server.ramUsed;
|
||||
if (ramUsage > ramAvailable) {
|
||||
dialogBoxCreate("Not enough RAM to run script " + runningScriptObj.filename + " with args " +
|
||||
printArray(runningScriptObj.args) + ". This likely occurred because you re-loaded " +
|
||||
"the game and the script's RAM usage increased (either because of an update to the game or " +
|
||||
"your changes to the script.)");
|
||||
return;
|
||||
}
|
||||
server.ramUsed += ramUsage;
|
||||
|
||||
//Create the WorkerScript
|
||||
|
@ -33,7 +33,15 @@ function initSourceFiles() {
|
||||
SourceFiles["SourceFile3"] = new SourceFile(3);
|
||||
SourceFiles["SourceFile4"] = new SourceFile(4, "This Source-File lets you access and use the Singularity Functions in every BitNode. Every " +
|
||||
"level of this Source-File opens up more of the Singularity Functions you can use.");
|
||||
SourceFiles["SourceFile5"] = new SourceFile(5);
|
||||
SourceFiles["SourceFile5"] = new SourceFile(5, "This Source-File grants a special new stat called Intelligence. Intelligence " +
|
||||
"is unique because it is permanent and persistent (it never gets reset back to 1). However, " +
|
||||
"gaining Intelligence experience is much slower than other stats, and it is also hidden (you won't " +
|
||||
"know when you gain experience and how much). Higher Intelligence levels will boost your production " +
|
||||
"for many actions in the game. In addition, this Source-File will unlock the getBitNodeMultipliers() " +
|
||||
"Netscript function, and will raise all of your hacking-related multipliers by:<br><br> " +
|
||||
"Level 1: 4%<br>" +
|
||||
"Level 2: 6%<br>" +
|
||||
"Level 3: 7%");
|
||||
SourceFiles["SourceFile6"] = new SourceFile(6);
|
||||
SourceFiles["SourceFile7"] = new SourceFile(7);
|
||||
SourceFiles["SourceFile8"] = new SourceFile(8);
|
||||
@ -108,6 +116,17 @@ function applySourceFile(srcFile) {
|
||||
case 4: //The Singularity
|
||||
//No effects, just gives access to Singularity functions
|
||||
break;
|
||||
case 5: //Artificial Intelligence
|
||||
var mult = 0;
|
||||
for (var i = 0; i < srcFile.lvl; ++i) {
|
||||
mult += (4 / (Math.pow(2, i)));
|
||||
}
|
||||
var incMult = 1 + (mult / 100);
|
||||
Player.hacking_chance_mult *= incMult;
|
||||
Player.hacking_speed_mult *= incMult;
|
||||
Player.hacking_money_mult *= incMult;
|
||||
Player.hacking_grow_mult *= incMult;
|
||||
break;
|
||||
case 11: //The Big Crash
|
||||
var mult = 0;
|
||||
for (var i = 0; i < srcFile.lvl; ++i) {
|
||||
|
@ -484,6 +484,11 @@ let Engine = {
|
||||
if (Player.sourceFiles.length !== 0) {
|
||||
bnText = "<br>Current BitNode: " + Player.bitNodeN;
|
||||
}
|
||||
|
||||
var intText = "";
|
||||
if (Player.intelligence > 0) {
|
||||
intText = 'Intelligence: ' + (Player.intelligence).toLocaleString() + "<br><br><br>";
|
||||
}
|
||||
Engine.Display.characterInfo.innerHTML =
|
||||
('<b>General</b><br><br>' +
|
||||
'Current City: ' + Player.city + '<br><br>' +
|
||||
@ -502,7 +507,8 @@ let Engine = {
|
||||
'Agility: ' + (Player.agility).toLocaleString() +
|
||||
" (" + numeral(Player.agility_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
'Charisma: ' + (Player.charisma).toLocaleString() +
|
||||
" (" + numeral(Player.charisma_exp).format('(0.000a)') + ' experience)<br><br><br>' +
|
||||
" (" + numeral(Player.charisma_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
intText +
|
||||
'<b>Multipliers</b><br><br>' +
|
||||
'Hacking Chance multiplier: ' + formatNumber(Player.hacking_chance_mult * 100, 2) + '%<br>' +
|
||||
'Hacking Speed multiplier: ' + formatNumber(Player.hacking_speed_mult * 100, 2) + '%<br>' +
|
||||
|
Loading…
Reference in New Issue
Block a user