Added :q, :x, :wq Vim Ex commands. Added ADR-v2 Pheromone new Augmentation. Fixed bugs and added improvements to Hacking missions.

This commit is contained in:
danielyxie 2017-10-01 21:35:22 -05:00
parent 26fe9eb519
commit 662f30cc38
12 changed files with 576 additions and 345 deletions

@ -12,7 +12,7 @@
/*grid-template-rows: 10% 10% 10% 10% 10% 10% 10% 10%;*/ /*grid-template-rows: 10% 10% 10% 10% 10% 10% 10% 10%;*/
grid-template-rows: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
grid-gap: 2.5%; grid-gap: 2.5%;
height: 100%; height: 90%;
position:absolute; position:absolute;
width: 100%; width: 100%;
overflow-y:auto; overflow-y:auto;

@ -209,7 +209,24 @@ a:link, a:visited {
z-index: 99; z-index: 99;
} }
.tooltip:hover .tooltiptext { /* Same thing as a normal tooltip except its a bit higher */
.tooltip .tooltiptexthigh {
visibility: hidden;
width: 300px;
background-color: var(--my-background-color);
border: 2px solid var(--my-highlight-color);;
color: white;
text-align: center;
padding: 4px;
left: 101%;
bottom:-25%;
position: absolute;
z-index: 99;
}
.tooltip:hover .tooltiptext,
.tooltip:hover .tooltiptexthigh {
visibility: visible; visibility: visible;
} }

657
dist/bundle.js vendored

File diff suppressed because it is too large Load Diff

@ -6,9 +6,10 @@ import {Player} from "./Player.js";
import {prestigeAugmentation} from "./Prestige.js"; import {prestigeAugmentation} from "./Prestige.js";
import {Script, RunningScript} from "./Script.js"; import {Script, RunningScript} from "./Script.js";
import {Server} from "./Server.js"; import {Server} from "./Server.js";
import {dialogBoxCreate} from "../utils/DialogBox.js"; import {dialogBoxCreate} from "../utils/DialogBox.js";
import {Reviver, Generic_toJSON, import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js"; Generic_fromJSON} from "../utils/JSONReviver.js";
import {isString} from "../utils/StringHelperFunctions.js";
//Augmentations //Augmentations
function Augmentation(name) { function Augmentation(name) {
@ -124,6 +125,7 @@ let AugmentationNames = {
PCDNIOptimizer: "PC Direct-Neural Interface Optimization Submodule", PCDNIOptimizer: "PC Direct-Neural Interface Optimization Submodule",
PCDNINeuralNetwork: "PC Direct-Neural Interface NeuroNet Injector", PCDNINeuralNetwork: "PC Direct-Neural Interface NeuroNet Injector",
ADRPheromone1: "ADR-V1 Pheromone Gene", ADRPheromone1: "ADR-V1 Pheromone Gene",
ADRPheromone2: "ADR-V2 Pheromone Gene",
HacknetNodeCPUUpload: "Hacknet Node CPU Architecture Neural-Upload", HacknetNodeCPUUpload: "Hacknet Node CPU Architecture Neural-Upload",
HacknetNodeCacheUpload: "Hacknet Node Cache Architecture Neural-Upload", HacknetNodeCacheUpload: "Hacknet Node Cache Architecture Neural-Upload",
HacknetNodeNICUpload: "HacknetNode NIC Architecture Neural-Upload", HacknetNodeNICUpload: "HacknetNode NIC Architecture Neural-Upload",
@ -820,8 +822,8 @@ function initAugmentations() {
ADRPheromone1.setRequirements(1500, 3500000); ADRPheromone1.setRequirements(1500, 3500000);
ADRPheromone1.setInfo("The body is genetically re-engineered so that it produces the ADR-V1 pheromone, " + ADRPheromone1.setInfo("The body is genetically re-engineered so that it produces the ADR-V1 pheromone, " +
"an artificial pheromone discovered by scientists. The ADR-V1 pheromone, when excreted, " + "an artificial pheromone discovered by scientists. The ADR-V1 pheromone, when excreted, " +
"triggers feelings of admiration and approval in other people. <br><br>" + "triggers feelings of admiration and approval in other people.<br><br>" +
"This augmentation: <br>" + "This augmentation:<br>" +
"Increases the amount of reputation the player gains when working for a company by 10% <br>" + "Increases the amount of reputation the player gains when working for a company by 10% <br>" +
"Increases the amount of reputation the player gains for a faction by 10%"); "Increases the amount of reputation the player gains for a faction by 10%");
ADRPheromone1.addToFactions(["Tian Di Hui", "The Syndicate", "NWO", "MegaCorp", "Four Sigma"]); ADRPheromone1.addToFactions(["Tian Di Hui", "The Syndicate", "NWO", "MegaCorp", "Four Sigma"]);
@ -830,6 +832,19 @@ function initAugmentations() {
} }
AddToAugmentations(ADRPheromone1); AddToAugmentations(ADRPheromone1);
var ADRPheromone2 = new Augmentation(AugmentationNames.ADRPheromone2);
ADRPheromone2.setRequirements(25000, 90000000000);
ADRPheromone2.setInfo("The body is genetically re-engineered so that it produces the ADR-V2 pheromone, " +
"which is similar to but more potent than ADR-V1. This pheromone, when excreted, " +
"triggers feelings of admiration, approval, and respect in others.<br><br>" +
"This augmentation:<br>" +
"Increases the amount of reputation the player gains for a faction and company by 20%.");
ADRPheromone2.addToFactions(["Silhouette", "Four Sigma", "Bachman & Associates", "Clarke Incorporated"]);
if (augmentationExists(AugmentationNames.ADRPheromone2)) {
delete Augmentations[AugmentationNames.ADRPheromone2];
}
AddToAugmentations(ADRPheromone2);
//HacknetNode Augmentations //HacknetNode Augmentations
var HacknetNodeCPUUpload = new Augmentation(AugmentationNames.HacknetNodeCPUUpload); var HacknetNodeCPUUpload = new Augmentation(AugmentationNames.HacknetNodeCPUUpload);
HacknetNodeCPUUpload.setRequirements(1500, 2200000); HacknetNodeCPUUpload.setRequirements(1500, 2200000);
@ -1629,6 +1644,10 @@ function applyAugmentation(aug, reapply=false) {
Player.company_rep_mult *= 1.1; Player.company_rep_mult *= 1.1;
Player.faction_rep_mult *= 1.1; Player.faction_rep_mult *= 1.1;
break; break;
case AugmentationNames.ADRPheromone2:
Player.company_rep_mult *= 1.2;
Player.faction_rep_mult *= 1.2;
break;
//Hacknet Node Augmentations //Hacknet Node Augmentations
case AugmentationNames.HacknetNodeCPUUpload: case AugmentationNames.HacknetNodeCPUUpload:
@ -1935,7 +1954,7 @@ function installAugmentations(cbScript=null) {
prestigeAugmentation(); prestigeAugmentation();
//Run a script after prestiging //Run a script after prestiging
if (cbScript) { if (cbScript && isString(cbScript)) {
var home = Player.getHomeComputer(); var home = Player.getHomeComputer();
for (var i = 0; i < home.scripts.length; ++i) { for (var i = 0; i < home.scripts.length; ++i) {
if (home.scripts[i].filename === cbScript) { if (home.scripts[i].filename === cbScript) {

@ -1,5 +1,5 @@
let CONSTANTS = { let CONSTANTS = {
Version: "0.29.1", Version: "0.29.2",
//Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience //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 //and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@ -115,17 +115,18 @@ let CONSTANTS = {
//Intelligence-related constants //Intelligence-related constants
IntelligenceCrimeWeight: 0.05, //Weight for how much int affects crime success rates IntelligenceCrimeWeight: 0.05, //Weight for how much int affects crime success rates
IntelligenceInfiltrationWeight: 0.1, //Weight for how much int affects infiltration success rates IntelligenceInfiltrationWeight: 0.1, //Weight for how much int affects infiltration success rates
IntelligenceCrimeBaseExpGain: 0.0002, IntelligenceCrimeBaseExpGain: 0.001,
IntelligenceProgramBaseExpGain: 1000, //Program required hack level divided by this to determine int exp gain IntelligenceProgramBaseExpGain: 1000, //Program required hack level divided by this to determine int exp gain
IntelligenceTerminalHackBaseExpGain: 200, //Hacking exp divided by this to determine int exp gain IntelligenceTerminalHackBaseExpGain: 200, //Hacking exp divided by this to determine int exp gain
IntelligenceSingFnBaseExpGain: 0.0005, IntelligenceSingFnBaseExpGain: 0.0005,
IntelligenceClassBaseExpGain: 0.0000001, IntelligenceClassBaseExpGain: 0.0000001,
//Hacking Missions //Hacking Missions
HackingMissionRepToDiffConversion: 5000, //Faction rep is divided by this to get mission difficulty HackingMissionRepToDiffConversion: 10000, //Faction rep is divided by this to get mission difficulty
HackingMissionRepToRewardConversion: 12, //Faction rep divided byt his to get mission rep reward HackingMissionRepToRewardConversion: 10, //Faction rep divided byt his to get mission rep reward
HackingMissionSpamTimeIncrease: 20000, //How much time limit increase is gained when conquering a Spam Node (ms) HackingMissionSpamTimeIncrease: 20000, //How much time limit increase is gained when conquering a Spam Node (ms)
HackingMissionTransferAttackIncrease: 1.05, //Multiplier by which the attack for all Core Nodes is increased when conquering a Transfer Node HackingMissionTransferAttackIncrease: 1.05, //Multiplier by which the attack for all Core Nodes is increased when conquering a Transfer Node
HackingMissionMiscDefenseIncrease: 5, //The amount by which every misc node's defense increases when one is conquered
HackingMissionHowToPlay: "Hacking missions are a minigame that, if won, will reward you with faction reputation.<br><br>" + HackingMissionHowToPlay: "Hacking missions are a minigame that, if won, will reward you with faction reputation.<br><br>" +
"In this game you control a set of Nodes and use them to try and defeat an enemy. Your Nodes " + "In this game you control a set of Nodes and use them to try and defeat an enemy. Your Nodes " +
"are colored blue, while the enemy's are red. There are also other nodes on the map colored gray " + "are colored blue, while the enemy's are red. There are also other nodes on the map colored gray " +
@ -160,8 +161,8 @@ let CONSTANTS = {
"select its action using the Action Buttons near the top of the screen. Every action also has a corresponding keyboard " + "select its action using the Action Buttons near the top of the screen. Every action also has a corresponding keyboard " +
"shortcut that can be used as well.<br><br>" + "shortcut that can be used as well.<br><br>" +
"For certain actions such as attacking, scanning, and weakening, the Node performing the action must have a target. To target " + "For certain actions such as attacking, scanning, and weakening, the Node performing the action must have a target. To target " +
"another node, simply click-and-drag from the 'source' Node to a target. A Node can only have one target, and you can only target " + "another node, simply click-and-drag from the 'source' Node to a target. A Node can only have one target, and you can target " +
"Nodes that are adjacent to one of your Nodes (immediately above, below, or to the side. NOT diagonal). Furthermore, only CPU Cores and Transfer Nodes " + "any Node that is adjacent to one of your Nodes (immediately above, below, or to the side. NOT diagonal). Furthermore, only CPU Cores and Transfer Nodes " +
"can target, since they are the only ones that can perform actions. To remove a target, you can simply click on the line that represents " + "can target, since they are the only ones that can perform actions. To remove a target, you can simply click on the line that represents " +
"the connection between one of your Nodes and its target. Alternatively, you can select the 'source' Node and click the 'Drop Connection' button, " + "the connection between one of your Nodes and its target. Alternatively, you can select the 'source' Node and click the 'Drop Connection' button, " +
"or press 'd',", "or press 'd',",
@ -908,10 +909,14 @@ let CONSTANTS = {
"This function will try to purchase the specified Augmentation through the given Faction.<br><br>" + "This function will try to purchase the specified Augmentation through the given Faction.<br><br>" +
"The two arguments must be strings specifying the name of the Faction and Augmentation, respectively. These arguments are both CASE-SENSITIVE.<br><br>" + "The two arguments must be strings specifying the name of the Faction and Augmentation, respectively. These arguments are both CASE-SENSITIVE.<br><br>" +
"This function will return true if the Augmentation is successfully purchased, and false otherwise.<br><br>" + "This function will return true if the Augmentation is successfully purchased, and false otherwise.<br><br>" +
"<i>installAugmentations()</i><br>" + "<i>installAugmentations(cbScript)</i><br>" +
"If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.<br><br>" + "If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.<br><br>" +
"This function will automatically install your Augmentations, resetting the game as usual.<br><br>" + "This function will automatically install your Augmentations, resetting the game as usual.<br><br>" +
"It will return true if successful, and false otherwise.", "It will return true if successful, and false otherwise.<br><br>" +
"This function takes a single optional parameter that specifies a callback script. This is " +
"a script that will automatically be run after Augmentations are installed (after the reset). " +
"This script will be run with no arguments and 1 thread. It must be located on your home computer. This argument, if used, " +
"must be a string with the name of the script.",
TutorialTravelingText:"There are six major cities in the world that you are able to travel to: <br><br> " + TutorialTravelingText:"There are six major cities in the world that you are able to travel to: <br><br> " +
" Aevum<br>" + " Aevum<br>" +
@ -1015,7 +1020,13 @@ let CONSTANTS = {
"-installAugmentations() Singularity Function now takes a callback script as an argument. This is a script " + "-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, " + "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>" + "and must be found on your home computer.<br>" +
"-Added functions to Netscript. See the link here for details<br>" + "-Added the ability to create your own functions in Netscript. See <a href='http://bitburner.wikia.com/wiki/Netscript_Functions' target='_blank'>this link</a> for details<br>" +
"-Added :q, :x, and :wq Vim Ex Commands when using the Vim script editor keybindings. :w, :x, and :wq will all save the script and return to Terminal. " +
":q will quit (return to Terminal) WITHOUT saving. If anyone thinks theres an issue with this please let me know, I don't use Vim<br>" +
"-Added a new Augmentation: ADR-V2 Pheromone Gene<br>" +
"-In Hacking Missions, enemy nodes will now automatically target Nodes and perform actions.<br>" +
"-Re-balanced Hacking Missions through minor tweaking of many numbers<br>" +
"-The faction reputation reward for Hacking Missions was slightly increased<br><br>" +
"v0.29.1<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) " + "-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 " + "that is meant to be used to earn faction reputation. However, since this is currently in beta, hacking missions will NOT grant reputation " +

@ -156,7 +156,7 @@ function HackingMission(rep, fac) {
this.faction = fac; this.faction = fac;
this.started = false; this.started = false;
this.time = 180000; //2 minutes, milliseconds this.time = 300000; //5 minutes to start, milliseconds
this.playerCores = []; this.playerCores = [];
this.playerNodes = []; //Non-core nodes this.playerNodes = []; //Non-core nodes
@ -203,8 +203,8 @@ HackingMission.prototype.init = function() {
var home = Player.getHomeComputer() var home = Player.getHomeComputer()
for (var i = 0; i < home.cpuCores; ++i) { for (var i = 0; i < home.cpuCores; ++i) {
var stats = { var stats = {
atk: (Player.hacking_skill / 10), atk: (Player.hacking_skill / 6),
def: (Player.hacking_skill / 25), def: (Player.hacking_skill / 20),
hp: (Player.hacking_skill / 5), hp: (Player.hacking_skill / 5),
}; };
this.playerCores.push(new Node(NodeTypes.Core, stats)); this.playerCores.push(new Node(NodeTypes.Core, stats));
@ -226,9 +226,9 @@ HackingMission.prototype.init = function() {
var randMult = addOffset(this.difficulty, 20); var randMult = addOffset(this.difficulty, 20);
for (var i = 0; i < numNodes; ++i) { for (var i = 0; i < numNodes; ++i) {
var stats = { var stats = {
atk: randMult * getRandomInt(125, 175), atk: randMult * getRandomInt(30, 50),
def: randMult * getRandomInt(30, 50), def: randMult * getRandomInt(20, 40),
hp: randMult * getRandomInt(225, 275) hp: randMult * getRandomInt(100, 120)
} }
this.enemyCores.push(new Node(NodeTypes.Core, stats)); this.enemyCores.push(new Node(NodeTypes.Core, stats));
this.enemyCores[i].setControlledByEnemy(); this.enemyCores[i].setControlledByEnemy();
@ -236,9 +236,9 @@ HackingMission.prototype.init = function() {
} }
for (var i = 0; i < numFirewalls; ++i) { for (var i = 0; i < numFirewalls; ++i) {
var stats = { var stats = {
atk: randMult * getRandomInt(10, 25), atk: 0,
def: randMult * getRandomInt(50, 75), def: randMult * getRandomInt(50, 75),
hp: randMult * getRandomInt(175, 200) hp: randMult * getRandomInt(150, 200)
} }
this.enemyNodes.push(new Node(NodeTypes.Firewall, stats)); this.enemyNodes.push(new Node(NodeTypes.Firewall, stats));
this.enemyNodes[i].setControlledByEnemy(); this.enemyNodes[i].setControlledByEnemy();
@ -246,8 +246,8 @@ HackingMission.prototype.init = function() {
} }
for (var i = 0; i < numDatabases; ++i) { for (var i = 0; i < numDatabases; ++i) {
var stats = { var stats = {
atk: randMult * getRandomInt(20, 30), atk: 0,
def: randMult * getRandomInt(25, 40), def: randMult * getRandomInt(20, 30),
hp: randMult * getRandomInt(120, 150) hp: randMult * getRandomInt(120, 150)
} }
var node = new Node(NodeTypes.Database, stats); var node = new Node(NodeTypes.Database, stats);
@ -332,37 +332,37 @@ HackingMission.prototype.createPageDom = function() {
} }
this.actionButtons[0].innerText = "Attack(a)"; this.actionButtons[0].innerText = "Attack(a)";
var atkTooltip = document.createElement("span"); var atkTooltip = document.createElement("span");
atkTooltip.classList.add("tooltiptext"); atkTooltip.classList.add("tooltiptexthigh");
atkTooltip.innerText = "Lowers the targeted node's HP. The effectiveness of this depends on " + atkTooltip.innerText = "Lowers the targeted node's HP. The effectiveness of this depends on " +
"this node's Attack level, your hacking level, and the opponent's defense level."; "this node's Attack level, your hacking level, and the opponent's defense level.";
this.actionButtons[0].appendChild(atkTooltip); this.actionButtons[0].appendChild(atkTooltip);
this.actionButtons[1].innerText = "Scan(s)"; this.actionButtons[1].innerText = "Scan(s)";
var scanTooltip = document.createElement("span"); var scanTooltip = document.createElement("span");
scanTooltip.classList.add("tooltiptext"); scanTooltip.classList.add("tooltiptexthigh");
scanTooltip.innerText = "Lowers the targeted node's defense. The effectiveness of this depends on " + scanTooltip.innerText = "Lowers the targeted node's defense. The effectiveness of this depends on " +
"this node's Attack level, your hacking level, and the opponent's defense level."; "this node's Attack level, your hacking level, and the opponent's defense level.";
this.actionButtons[1].appendChild(scanTooltip); this.actionButtons[1].appendChild(scanTooltip);
this.actionButtons[2].innerText = "Weaken(w)"; this.actionButtons[2].innerText = "Weaken(w)";
var WeakenTooltip = document.createElement("span"); var WeakenTooltip = document.createElement("span");
WeakenTooltip.classList.add("tooltiptext"); WeakenTooltip.classList.add("tooltiptexthigh");
WeakenTooltip.innerText = "Lowers the targeted node's attack. The effectiveness of this depends on " + WeakenTooltip.innerText = "Lowers the targeted node's attack. The effectiveness of this depends on " +
"this node's Attack level, your hacking level, and the opponent's defense level."; "this node's Attack level, your hacking level, and the opponent's defense level.";
this.actionButtons[2].appendChild(WeakenTooltip); this.actionButtons[2].appendChild(WeakenTooltip);
this.actionButtons[3].innerText = "Fortify(f)"; this.actionButtons[3].innerText = "Fortify(f)";
var fortifyTooltip = document.createElement("span"); var fortifyTooltip = document.createElement("span");
fortifyTooltip.classList.add("tooltiptext"); fortifyTooltip.classList.add("tooltiptexthigh");
fortifyTooltip.innerText = "Raises this node's Defense level. The effectiveness of this depends on " + fortifyTooltip.innerText = "Raises this node's Defense level. The effectiveness of this depends on " +
"your hacking level"; "your hacking level";
this.actionButtons[3].appendChild(fortifyTooltip); this.actionButtons[3].appendChild(fortifyTooltip);
this.actionButtons[4].innerText = "Overflow(r)"; this.actionButtons[4].innerText = "Overflow(r)";
var overflowTooltip = document.createElement("span"); var overflowTooltip = document.createElement("span");
overflowTooltip.classList.add("tooltiptext"); overflowTooltip.classList.add("tooltiptexthigh");
overflowTooltip.innerText = "Raises this node's Attack level but lowers its Defense level. The effectiveness " + overflowTooltip.innerText = "Raises this node's Attack level but lowers its Defense level. The effectiveness " +
"of this depends on your hacking level."; "of this depends on your hacking level.";
this.actionButtons[4].appendChild(overflowTooltip); this.actionButtons[4].appendChild(overflowTooltip);
this.actionButtons[5].innerText = "Drop Connection(d)"; this.actionButtons[5].innerText = "Drop Connection(d)";
var dropconnTooltip = document.createElement("span"); var dropconnTooltip = document.createElement("span");
dropconnTooltip.classList.add("tooltiptext"); dropconnTooltip.classList.add("tooltiptexthigh");
dropconnTooltip.innerText = "Removes this Node's current connection to some target Node, if it has one. This can " + dropconnTooltip.innerText = "Removes this Node's current connection to some target Node, if it has one. This can " +
"also be done by simply clicking the white connection line."; "also be done by simply clicking the white connection line.";
this.actionButtons[5].appendChild(dropconnTooltip); this.actionButtons[5].appendChild(dropconnTooltip);
@ -387,6 +387,7 @@ HackingMission.prototype.createPageDom = function() {
console.log("ERR: Pressing Action button without selected node"); console.log("ERR: Pressing Action button without selected node");
return; return;
} }
if (this.selectedNode.type !== NodeTypes.Core) {return;}
this.setActionButtonsActive(); this.setActionButtonsActive();
this.setActionButton(NodeActions.Attack, false); //Set attack button inactive this.setActionButton(NodeActions.Attack, false); //Set attack button inactive
this.selectedNode.action = NodeActions.Attack; this.selectedNode.action = NodeActions.Attack;
@ -608,7 +609,7 @@ HackingMission.prototype.createMap = function() {
case 0: //Spam case 0: //Spam
var stats = { var stats = {
atk: 0, atk: 0,
def: randMult * getRandomInt(35, 55), def: randMult * getRandomInt(30, 50),
hp: randMult * getRandomInt(125, 150) hp: randMult * getRandomInt(125, 150)
} }
node = new Node(NodeTypes.Spam, stats); node = new Node(NodeTypes.Spam, stats);
@ -616,7 +617,7 @@ HackingMission.prototype.createMap = function() {
case 1: //Transfer case 1: //Transfer
var stats = { var stats = {
atk: 0, atk: 0,
def: randMult * getRandomInt(45, 65), def: randMult * getRandomInt(40, 60),
hp: randMult * getRandomInt(150, 175) hp: randMult * getRandomInt(150, 175)
} }
node = new Node(NodeTypes.Transfer, stats); node = new Node(NodeTypes.Transfer, stats);
@ -625,7 +626,7 @@ HackingMission.prototype.createMap = function() {
default: default:
var stats = { var stats = {
atk: 0, atk: 0,
def: randMult * getRandomInt(60, 80), def: randMult * getRandomInt(50, 75),
hp: randMult * getRandomInt(200, 250) hp: randMult * getRandomInt(200, 250)
} }
node = new Node(NodeTypes.Shield, stats); node = new Node(NodeTypes.Shield, stats);
@ -761,9 +762,15 @@ HackingMission.prototype.updateNodeDomElement = function(nodeObj) {
} }
//Gets a Node DOM element's corresponding Node object using its //Gets a Node DOM element's corresponding Node object using its
//element id //element id. Function accepts either the DOM element object or the ID as
//an argument
HackingMission.prototype.getNodeFromElement = function(el) { HackingMission.prototype.getNodeFromElement = function(el) {
var id = el.id; var id;
if (isString(el)) {
id = el;
} else {
id = el.id;
}
id = id.replace("hacking-mission-node-", ""); id = id.replace("hacking-mission-node-", "");
var res = id.split('-'); var res = id.split('-');
if (res.length != 2) { if (res.length != 2) {
@ -917,6 +924,15 @@ HackingMission.prototype.initJsPlumb = function() {
var sourceNode = this.getNodeFromElement(info.source); var sourceNode = this.getNodeFromElement(info.source);
sourceNode.conn = null; sourceNode.conn = null;
}); });
//Set connection type for enemy connections
instance.registerConnectionTypes({
"basic": {
paintStyle:{ stroke:"red", strokeWidth:5 },
hoverPaintStyle:{ stroke:"red", strokeWidth:7 },
anchor:"Continuous",
},
})
} }
//Drops all connections where the specified node is the source //Drops all connections where the specified node is the source
@ -959,11 +975,13 @@ HackingMission.prototype.process = function(numCycles=1) {
//Process actions of all enemy nodes //Process actions of all enemy nodes
this.enemyCores.forEach((node)=>{ this.enemyCores.forEach((node)=>{
this.enemyAISelectAction(node);
res |= this.processNode(node, storedCycles); res |= this.processNode(node, storedCycles);
}); });
this.enemyNodes.forEach((node)=>{ this.enemyNodes.forEach((node)=>{
if (node.type === NodeTypes.Transfer) { if (node.type === NodeTypes.Transfer) {
this.enemyAISelectAction(node);
res |= this.processNode(node, storedCycles); res |= this.processNode(node, storedCycles);
} }
}); });
@ -978,7 +996,7 @@ HackingMission.prototype.process = function(numCycles=1) {
return; return;
} }
//Defense of every misc Node increase by 1 per second //Defense of every misc Node increase by 0.5 per second
this.miscNodes.forEach((node)=>{ this.miscNodes.forEach((node)=>{
node.def += (0.1 * storedCycles); node.def += (0.1 * storedCycles);
this.updateNodeDomElement(node); this.updateNodeDomElement(node);
@ -1003,7 +1021,13 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) {
var targetNode = null, def, atk; var targetNode = null, def, atk;
if (nodeObj.conn) { if (nodeObj.conn) {
targetNode = this.getNodeFromElement(nodeObj.conn.target); var targetNode;
if (nodeObj.conn.target) {
targetNode = this.getNodeFromElement(nodeObj.conn.target);
} else {
targetNode = this.getNodeFromElement(nodeObj.conn.targetId);
}
if (targetNode.plyrCtrl) { if (targetNode.plyrCtrl) {
def = this.playerDef; def = this.playerDef;
atk = this.enemyAtk; atk = this.enemyAtk;
@ -1071,7 +1095,6 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) {
//Flag for whether the target node was a misc node //Flag for whether the target node was a misc node
var isMiscNode = !targetNode.plyrCtrl && !targetNode.enmyCtrl; var isMiscNode = !targetNode.plyrCtrl && !targetNode.enmyCtrl;
console.log("isMiscNode: " + isMiscNode);
//Remove all connections from Node //Remove all connections from Node
this.dropAllConnectionsToNode(targetNode); this.dropAllConnectionsToNode(targetNode);
@ -1089,6 +1112,7 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) {
}); });
} else { } else {
targetNode.setControlledByEnemy(); targetNode.setControlledByEnemy();
nodeObj.conn = null; //Clear connection
this.jsplumbinstance.unmakeSource(targetNode.el); this.jsplumbinstance.unmakeSource(targetNode.el);
this.jsplumbinstance.makeTarget(targetNode.el, { this.jsplumbinstance.makeTarget(targetNode.el, {
maxConnections:-1, maxConnections:-1,
@ -1101,10 +1125,8 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) {
//Helper function to swap nodes between the respective enemyNodes/playerNodes arrays //Helper function to swap nodes between the respective enemyNodes/playerNodes arrays
function swapNodes(orig, dest, targetNode) { function swapNodes(orig, dest, targetNode) {
console.log("swapNodes called");
for (var i = 0; i < orig.length; ++i) { for (var i = 0; i < orig.length; ++i) {
if (orig[i] == targetNode) { if (orig[i] == targetNode) {
console.log("Swapping nodes");
var node = orig.splice(i, 1); var node = orig.splice(i, 1);
node = node[0]; node = node[0];
dest.push(node); dest.push(node);
@ -1113,7 +1135,6 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) {
} }
} }
//Whether conquered node was a misc node
switch(targetNode.type) { switch(targetNode.type) {
case NodeTypes.Core: case NodeTypes.Core:
if (conqueredByPlayer) { if (conqueredByPlayer) {
@ -1141,12 +1162,12 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) {
case NodeTypes.Spam: case NodeTypes.Spam:
if (conqueredByPlayer) { if (conqueredByPlayer) {
swapNodes(isMiscNode ? this.miscNodes : this.enemyNodes, this.playerNodes, targetNode); swapNodes(isMiscNode ? this.miscNodes : this.enemyNodes, this.playerNodes, targetNode);
//Conquering spam node increases time limit
this.time += CONSTANTS.HackingMissionSpamTimeIncrease;
} else { } else {
swapNodes(isMiscNode ? this.miscNodes : this.playerNodes, this.enemyNodes, targetNode); swapNodes(isMiscNode ? this.miscNodes : this.playerNodes, this.enemyNodes, targetNode);
} }
//Conquering spam node increases time limit
this.time += CONSTANTS.HackingMissionSpamTimeIncrease;
break; break;
case NodeTypes.Transfer: case NodeTypes.Transfer:
//Conquering a Transfer node increases the attack of all cores by some percentages //Conquering a Transfer node increases the attack of all cores by some percentages
@ -1172,7 +1193,14 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) {
} }
break; break;
} }
//If a misc node was conquered, the defense for all misc nodes increases by some fixed amount
this.miscNodes.forEach((node)=>{
node.def += CONSTANTS.HackingMissionMiscDefenseIncrease;
});
} }
//Update node DOMs
this.updateNodeDomElement(nodeObj); this.updateNodeDomElement(nodeObj);
if (targetNode) {this.updateNodeDomElement(targetNode);} if (targetNode) {this.updateNodeDomElement(targetNode);}
return calcStats; return calcStats;
@ -1188,32 +1216,66 @@ HackingMission.prototype.enemyAISelectAction = function(nodeObj) {
//be selected for now, and the next time process() gets called this will repeat //be selected for now, and the next time process() gets called this will repeat
if (nodeObj.conn === null) { if (nodeObj.conn === null) {
if (this.miscNodes.length === 0) { if (this.miscNodes.length === 0) {
//Randomly pick a player node and attack it if its reachable
var rand = getRandomInt(0, this.playerNodes.length-1); var rand = getRandomInt(0, this.playerNodes.length-1);
var node = this.playerNodes[rand]; var node = this.playerNodes[rand];
if (this.nodeReachableByEnemy(node)) { if (this.nodeReachableByEnemy(node)) {
//TODO Create connection //Create connection
console.log("Enemy core selected a Player Node as target");
nodeObj.conn = this.jsplumbinstance.connect({
source:nodeObj.el,
target:node.el
});
} else { } else {
//Randomly pick a player core and attack it if its reachable
rand = getRandomInt(0, this.playerCores.length-1); rand = getRandomInt(0, this.playerCores.length-1);
node = this.playerCores[rand]; node = this.playerCores[rand];
if (this.nodeReachableByEnemy(node)) { if (this.nodeReachableByEnemy(node)) {
//TODO Create connection //Create connection
console.log("Enemy core selected a Player Core as target");
nodeObj.conn = this.jsplumbinstance.connect({
source:nodeObj.el,
target:node.el
});
} }
} }
} else { } else {
//Randomly pick a misc node and attack it if its reachable
var rand = getRandomInt(0, this.miscNodes.length-1); var rand = getRandomInt(0, this.miscNodes.length-1);
var node = this.miscNodes[rand]; var node = this.miscNodes[rand];
if (this.nodeReachableByEnemy(node)) { if (this.nodeReachableByEnemy(node)) {
//TODO Create connection to this Node console.log("Enemy core selected a Misc Node as target: " + node.el.id);
nodeObj.conn = this.jsplumbinstance.connect({
source:nodeObj.el,
target:node.el,
type:"basic"
});
} }
} }
//If no connection was made, set the Core to Fortify
nodeObj.action = NodeActions.Fortify;
} else {
var targetNode;
if (nodeObj.conn.target) {
targetNode = this.getNodeFromElement(nodeObj.conn.target);
} else {
targetNode = this.getNodeFromElement(nodeObj.conn.targetId);
}
if (targetNode === null) {
console.log("Error getting Target node Object in enemyAISelectAction()");
}
if (targetNode.def > this.enemyAtk - 25) {
nodeObj.action = NodeActions.Scan;
} else {
nodeObj.action = NodeActions.Attack;
}
} }
//TODO Select action
break; break;
case NodeTypes.Transfer: case NodeTypes.Transfer:
//Switch between fortifying and overflowing as necessary //Switch between fortifying and overflowing as necessary
if (nodeObj.def < 500) { if (nodeObj.def < 125) {
nodeObj.action = NodeActions.Fortify; nodeObj.action = NodeActions.Fortify;
} else { } else {
nodeObj.action = NodeActions.Overflow; nodeObj.action = NodeActions.Overflow;
@ -1224,10 +1286,9 @@ HackingMission.prototype.enemyAISelectAction = function(nodeObj) {
} }
} }
var hackEffWeightSelf = 130; //Weight for Node actions on self
var hackEffWeightSelf = 150; //Weight for Node actions on self
var hackEffWeightTarget = 25; //Weight for Node Actions against Target var hackEffWeightTarget = 25; //Weight for Node Actions against Target
var hackEffWeightAttack = 110; //Weight for Attack action var hackEffWeightAttack = 80; //Weight for Attack action
//Returns damage per cycle based on stats //Returns damage per cycle based on stats
HackingMission.prototype.calculateAttackDamage = function(atk, def, hacking = 0) { HackingMission.prototype.calculateAttackDamage = function(atk, def, hacking = 0) {

@ -4,7 +4,9 @@ import {NetscriptFunctions} from "./NetscriptFunctions.js";
*/ */
function Environment(workerScript,parent) { function Environment(workerScript,parent) {
if (parent){ if (parent){
this.vars = parent.vars; //Create a copy of parent's variables
//this.vars = parent.vars;
this.vars = Object.assign({}, parent.vars);
} else { } else {
this.vars = NetscriptFunctions(workerScript); this.vars = NetscriptFunctions(workerScript);
} }
@ -22,10 +24,12 @@ Environment.prototype = {
lookup: function(name) { lookup: function(name) {
var scope = this; var scope = this;
while (scope) { while (scope) {
if (Object.prototype.hasOwnProperty.call(scope.vars, name)) if (Object.prototype.hasOwnProperty.call(scope.vars, name)) {
return scope; return scope;
}
scope = scope.parent; scope = scope.parent;
} }
return null;
}, },
//Get the current value of a variable //Get the current value of a variable
@ -39,15 +43,14 @@ Environment.prototype = {
//Sets the value of a variable in any scope //Sets the value of a variable in any scope
set: function(name, value) { set: function(name, value) {
var scope = this.lookup(name); var scope = this.lookup(name);
// let's not allow defining globals from a nested environment
// //If scope has a value, then this variable is already set in a higher scope, so
// If scope is null (aka existing variable with name could not be found) //set is there. Otherwise, create a new variable in the local scope
// and this is NOT the global scope, throw error if (scope !== null) {
if (!scope && this.parent) { return scope.vars[name] = value;
console.log("Here"); } else {
throw new Error("Undefined variable " + name); return this.vars[name] = value;
} }
return (scope || this).vars[name] = value;
}, },
setArrayElement: function(name, idx, value) { setArrayElement: function(name, idx, value) {
@ -56,7 +59,6 @@ Environment.prototype = {
} }
var scope = this.lookup(name); var scope = this.lookup(name);
if (!scope && this.parent) { if (!scope && this.parent) {
console.log("Here");
throw new Error("Undefined variable " + name); throw new Error("Undefined variable " + name);
} }
var arr = (scope || this).vars[name]; var arr = (scope || this).vars[name];

@ -84,6 +84,8 @@ function evaluate(exp, workerScript) {
//Create new Environment for the function //Create new Environment for the function
//Should be automatically garbage collected... //Should be automatically garbage collected...
var funcEnv = env.extend(); var funcEnv = env.extend();
console.log("Printing new environment for function:");
console.log(funcEnv);
//Define function arguments in this new environment //Define function arguments in this new environment
for (var i = 0; i < func.params.length; ++i) { for (var i = 0; i < func.params.length; ++i) {

@ -1973,7 +1973,7 @@ function NetscriptFunctions(workerScript) {
return false; return false;
} }
}, },
installAugmentations() { installAugmentations(cbScript) {
if (Player.bitNodeN != 4) { if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 3)) { if (!(hasSingularitySF && singularitySFLvl >= 3)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run installAugmentations(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); throw makeRuntimeRejectMsg(workerScript, "Cannot run installAugmentations(). It is a Singularity Function and requires SourceFile-4 (level 3) to run.");
@ -1987,7 +1987,7 @@ function NetscriptFunctions(workerScript) {
} }
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain); Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
workerScript.scriptRef.log("Installing Augmentations. This will cause this script to be killed"); workerScript.scriptRef.log("Installing Augmentations. This will cause this script to be killed");
installAugmentations(); installAugmentations(cbScript);
return true; return true;
} }
} }

@ -92,7 +92,7 @@ function runScriptsLoop() {
if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) { if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) {
try { try {
var ast = parse(workerScripts[i].code); var ast = parse(workerScripts[i].code);
console.log(ast); //console.log(ast);
} catch (e) { } catch (e) {
console.log("Error parsing script: " + workerScripts[i].name); console.log("Error parsing script: " + workerScripts[i].name);
dialogBoxCreate("Syntax ERROR in " + workerScripts[i].name + ":<br>" + e); dialogBoxCreate("Syntax ERROR in " + workerScripts[i].name + ":<br>" + e);

@ -1483,6 +1483,7 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
break; break;
case CONSTANTS.CrimeKidnap: case CONSTANTS.CrimeKidnap:
this.karma -= 6; this.karma -= 6;
this.gainIntelligenceExp(CONSTANTS.IntelligenceCrimeBaseExpGain);
break; break;
case CONSTANTS.CrimeAssassination: case CONSTANTS.CrimeAssassination:
++this.numPeopleKilled; ++this.numPeopleKilled;

@ -94,6 +94,12 @@ function scriptEditorInit() {
VimApi.defineEx('quit', 'q', function(cm, input) { VimApi.defineEx('quit', 'q', function(cm, input) {
Engine.loadTerminalContent(); Engine.loadTerminalContent();
}); });
VimApi.defineEx('xwritequit', 'x', function(cm, input) {
saveAndCloseScriptEditor();
});
VimApi.defineEx('wqwritequit', 'wq', function(cm, input) {
saveAndCloseScriptEditor();
});
}); });
} }
document.addEventListener("DOMContentLoaded", scriptEditorInit, false); document.addEventListener("DOMContentLoaded", scriptEditorInit, false);
@ -243,6 +249,7 @@ function calculateRamUsage(codeCopy) {
numOccurrences(codeCopy, "getServerMaxMoney(") + numOccurrences(codeCopy, "getServerMaxMoney(") +
numOccurrences(codeCopy, "getServerSecurityLevel(") + numOccurrences(codeCopy, "getServerSecurityLevel(") +
numOccurrences(codeCopy, "getServerBaseSecurityLevel(") + numOccurrences(codeCopy, "getServerBaseSecurityLevel(") +
numOccurrences(codeCopy, "getServerMinSecurityLevel(") +
numOccurrences(codeCopy, "getServerGrowth(") + numOccurrences(codeCopy, "getServerGrowth(") +
numOccurrences(codeCopy, "getServerRequiredHackingLevel(") + numOccurrences(codeCopy, "getServerRequiredHackingLevel(") +
numOccurrences(codeCopy, "getServerNumPortsRequired(") + numOccurrences(codeCopy, "getServerNumPortsRequired(") +
@ -260,7 +267,8 @@ function calculateRamUsage(codeCopy) {
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("); numOccurrences(codeCopy, "deleteServer(") +
numOccurrences(codeCopy, "getPurchasedServers(");
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(");
@ -271,7 +279,8 @@ function calculateRamUsage(codeCopy) {
numOccurrences(codeCopy, "getScriptExpGain("); numOccurrences(codeCopy, "getScriptExpGain(");
var getHackTimeCount = numOccurrences(codeCopy, "getHackTime(") + var getHackTimeCount = numOccurrences(codeCopy, "getHackTime(") +
numOccurrences(codeCopy, "getGrowTime(") + numOccurrences(codeCopy, "getGrowTime(") +
numOccurrences(codeCopy, "getWeakenTime("); numOccurrences(codeCopy, "getWeakenTime(") +
numOccurrences(codeCopy, "getTimeSinceLastAug(");
var singFn1Count = numOccurrences(codeCopy, "universityCourse(") + var singFn1Count = numOccurrences(codeCopy, "universityCourse(") +
numOccurrences(codeCopy, "gymWorkout(") + numOccurrences(codeCopy, "gymWorkout(") +
numOccurrences(codeCopy, "travelToCity(") + numOccurrences(codeCopy, "travelToCity(") +