Merge branch 'dev' into improve-get-script-ram

This commit is contained in:
Olivier Gagnon 2018-05-07 16:00:24 -04:00 committed by GitHub
commit dcc09d561e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 320 additions and 259 deletions

Binary file not shown.

Binary file not shown.

@ -147,7 +147,7 @@ Terminal commands::
$ download * $ download *
$ download *.script $ download *.script
$download *.txt $ download *.txt
free free
^^^^ ^^^^

@ -185,7 +185,7 @@ $ download importantInfo.txt
Terminal commands:</p> Terminal commands:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span>$ download * <div class="highlight-default"><div class="highlight"><pre><span></span>$ download *
$ download *.script $ download *.script
$download *.txt $ download *.txt
</pre></div> </pre></div>
</div> </div>
</div> </div>

@ -779,6 +779,12 @@ scriptKill
Kills all scripts with the specified filename on the target server specified by *hostname/ip*, regardless of arguments. Returns Kills all scripts with the specified filename on the target server specified by *hostname/ip*, regardless of arguments. Returns
true if one or more scripts were successfully killed, and false if none were. true if one or more scripts were successfully killed, and false if none were.
getScriptName
^^^^^^^^^^^^^
.. js:function:: getScriptName()
Returns the current script name
getScriptRam getScriptRam
^^^^^^^^^^^^ ^^^^^^^^^^^^

@ -17,6 +17,22 @@ hacknetnodes
accessed using *hacknetnodes[0]*. The fourth Hacknet Node you purchase will have the name accessed using *hacknetnodes[0]*. The fourth Hacknet Node you purchase will have the name
"hacknet-node-3" and can be accessed using *hacknetnodes[3]*. "hacknet-node-3" and can be accessed using *hacknetnodes[3]*.
Purchasing Hacknet Nodes
^^^^^^^^^^^^^^^^^^^^^^^^
The following is a list of supported functions for purchasing Hacknet Nodes.
.. js:function:: getNextHacknetNodeCost()
Returns the cost of purchasing a new Hacknet Node
.. js:function:: purchaseHacknetNode()
Purchases a new Hacknet Node. Returns a number with the index of the Hacknet Node. This index is equivalent to the number at the
end of the Hacknet Node's name (e.g The Hacknet Node named 'hacknet-node-4' will have an index of 4). If the player cannot afford
to purchase a new Hacknet Node then the function will return false.
Hacknet Node Member Variables Hacknet Node Member Variables
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -25,6 +41,11 @@ a value to these.
Note that these must be called on an element inside the *hacknetnodes* array, not the array itself. Note that these must be called on an element inside the *hacknetnodes* array, not the array itself.
.. js:attribute:: hacknetnodes[i].name
Returns the name of the corresponding Hacknet Node
.. js:attribute:: hacknetnodes[i].level .. js:attribute:: hacknetnodes[i].level
Returns the level of the corresponding Hacknet Node Returns the level of the corresponding Hacknet Node

@ -819,6 +819,18 @@
<input type="checkbox" name="settingsSuppressFactionInvites" id="settingsSuppressFactionInvites"> <input type="checkbox" name="settingsSuppressFactionInvites" id="settingsSuppressFactionInvites">
</fieldset> </fieldset>
<!-- Disable Terminal and Navigation Shortcuts -->
<fieldset>
<label for="settingsDisableHotkeys" class="tooltip">Disable Hotkeys:
<span class="tooltiptext">
If this is set, then most hotkeys (keyboard shortcuts) in the game are disabled.
This includes Terminal commands, hotkeys to navigate between different parts of the game,
and the "Save and Close (Ctrl + b)" hotkey in the Text Editor.
</span>
</label>
<input type="checkbox" name="settingsDisableHotkeys" id="settingsDisableHotkeys">
</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">

@ -4,156 +4,136 @@ import {workerScripts,
import {Player} from "./Player.js"; import {Player} from "./Player.js";
import {getServer} from "./Server.js"; import {getServer} from "./Server.js";
import {dialogBoxCreate} from "../utils/DialogBox.js"; import {dialogBoxCreate} from "../utils/DialogBox.js";
import {printArray} from "../utils/HelperFunctions.js"; import {printArray, createElement,
createAccordionElement, removeElement,
removeChildrenFromElement} from "../utils/HelperFunctions.js";
import {logBoxCreate} from "../utils/LogBox.js"; import {logBoxCreate} from "../utils/LogBox.js";
import numeral from "../utils/numeral.min.js"; import numeral from "../utils/numeral.min.js";
import {formatNumber} from "../utils/StringHelperFunctions.js"; import {formatNumber} from "../utils/StringHelperFunctions.js";
/* {
/* Active Scripts UI*/ * serverName: {
function setActiveScriptsClickHandlers() { * header: Server Header Element
//Server panel click handlers * panel: Server Panel List (ul) element
var serverPanels = document.getElementsByClassName("active-scripts-server-header"); * scripts: {
if (serverPanels == null) { * script id: Ref to Script information
console.log("ERROR: Could not find Active Scripts server panels"); * }
return; * }
} * ...
for (i = 0; i < serverPanels.length; ++i) { */
serverPanels[i].onclick = function() { let ActiveScriptsUI = {};
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
}
}
//Script Panel click handlers
var scriptPanels = document.getElementsByClassName("active-scripts-script-header");
if (scriptPanels == null) {
console.log("ERROR: Could not find Active Scripts panels for individual scripts");
return;
}
for (var i = 0; i < scriptPanels.length; ++i) {
scriptPanels[i].onclick = function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
}
}
}
//Returns the ul element containins all script items for a specific server
function getActiveScriptsServerList(server) {
if (server == null) {return null;}
var panelname = "active-scripts-server-panel-" + server.hostname;
var item = document.getElementById(panelname + "-script-list");
if (item == null) {
console.log("ERROR: Cannot find list for: " + server.hostname);
}
return item;
}
function createActiveScriptsServerPanel(server) { function createActiveScriptsServerPanel(server) {
var panelname = "active-scripts-server-panel-" + server.hostname; let hostname = server.hostname;
if (ActiveScriptsUI[hostname] != null) {
console.log("WARNING: Tried to create already-existing Active Scripts Server panel. Aborting");
return;
}
var activeScriptsList = document.getElementById("active-scripts-list"); var activeScriptsList = document.getElementById("active-scripts-list");
//Div of entire Panel let res = createAccordionElement({hdrText:hostname});
var panelDiv = document.createElement("div"); let li = res[0];
panelDiv.setAttribute("id", panelname); var hdr = res[1];
let panel = res[2];
//Panel Header var panelScriptList = createElement("ul");
var panelHdr = document.createElement("button"); panel.appendChild(panelScriptList);
panelHdr.setAttribute("class", "active-scripts-server-header") activeScriptsList.appendChild(li);
panelHdr.setAttribute("id", panelname + "-hdr");
panelHdr.innerHTML = server.hostname;
//Panel content ActiveScriptsUI[hostname] = {
var panelContentDiv = document.createElement("div"); header: hdr,
panelContentDiv.setAttribute("class", "active-scripts-server-panel"); panel: panel,
panelContentDiv.setAttribute("id", panelname + "-content"); panelList: panelScriptList,
scripts: {}, //Holds references to li elements for each active script
scriptHdrs: {}, //Holds references to header elements for each active script
scriptStats: {} //Holds references to the p elements containing text for each active script
};
//List of scripts return li;
var panelScriptList = document.createElement("ul");
panelScriptList.setAttribute("id", panelname + "-script-list");
panelContentDiv.appendChild(panelScriptList);
panelDiv.appendChild(panelHdr);
panelDiv.appendChild(panelContentDiv);
activeScriptsList.appendChild(panelDiv);
setActiveScriptsClickHandlers() //Reset click handlers
return panelDiv;
} }
//Deletes the info for a particular server (Dropdown header + Panel with all info) //Deletes the info for a particular server (Dropdown header + Panel with all info)
//in the Active Scripts page if it exists //in the Active Scripts page if it exists
function deleteActiveScriptsServerPanel(server) { function deleteActiveScriptsServerPanel(server) {
var panelname = "active-scripts-server-panel-" + server.hostname; let hostname = server.hostname;
var panel = document.getElementById(panelname); if (ActiveScriptsUI[hostname] == null) {
if (panel == null) { console.log("WARNING: Tried to delete non-existent Active Scripts Server panel. Aborting");
console.log("No such panel exists: " + panelname);
return; return;
} }
//Remove the panel if it has no elements //Make sure it's empty
var scriptList = document.getElementById(panelname + "-script-list"); if (Object.keys(ActiveScriptsUI[hostname].scripts).length > 0) {
if (scriptList.childNodes.length == 0) { console.log("WARNING: Tried to delete Active Scripts Server panel that still has scripts. Aborting");
panel.parentNode.removeChild(panel); return;
} }
removeElement(ActiveScriptsUI[hostname].panel);
removeElement(ActiveScriptsUI[hostname].header);
delete ActiveScriptsUI[hostname];
} }
function addActiveScriptsItem(workerscript) { function addActiveScriptsItem(workerscript) {
//Get server panel //Get server panel
var server = getServer(workerscript.serverIp); var server = getServer(workerscript.serverIp);
if (server == null) { if (server == null) {
console.log("ERROR: Invalid server IP for workerscript."); console.log("ERROR: Invalid server IP for workerscript in addActiveScriptsItem()");
return; return;
} }
var panelname = "active-scripts-server-panel-" + server.hostname; let hostname = server.hostname;
if (ActiveScriptsUI[hostname] == null) {
var panel = document.getElementById(panelname); createActiveScriptsServerPanel(server);
if (panel == null) {
panel = createActiveScriptsServerPanel(server);
} }
//Create the element itself. Each element is an accordion collapsible //Create the unique identifier (key) for this script
var itemNameArray = ["active", "scripts", server.hostname, workerscript.name]; var itemNameArray = ["active", "scripts", server.hostname, workerscript.name];
for (var i = 0; i < workerscript.args.length; ++i) { for (var i = 0; i < workerscript.args.length; ++i) {
itemNameArray.push(String(workerscript.args[i])); itemNameArray.push(String(workerscript.args[i]));
} }
var itemName = itemNameArray.join("-"); var itemName = itemNameArray.join("-");
var item = document.createElement("li");
item.setAttribute("id", itemName);
var btn = document.createElement("button"); let res = createAccordionElement({hdrText:workerscript.name});
btn.setAttribute("class", "active-scripts-script-header"); let li = res[0];
btn.setAttribute("id", itemName + "-header"); let hdr = res[1];
btn.innerHTML = workerscript.name; let panel = res[2];
var itemContentDiv = document.createElement("div"); hdr.classList.remove("accordion-header");
itemContentDiv.setAttribute("class", "active-scripts-script-panel"); hdr.classList.add("active-scripts-script-header");
itemContentDiv.setAttribute("id", itemName + "-content"); panel.classList.remove("accordion-panel");
panel.classList.add("active-scripts-script-panel");
item.appendChild(btn); //Handle the constant elements on the panel that don't change after creation
item.appendChild(itemContentDiv); //Threads, args, kill/log button
panel.appendChild(createElement("p", {
createActiveScriptsText(workerscript, itemContentDiv); innerHTML: "Threads: " + workerscript.scriptRef.threads + "<br>" +
"Args: " + printArray(workerscript.args)
}));
var panelText = createElement("p", {
innerText:"Loading...", fontSize:"14px",
});
updateActiveScriptsText(workerscript, panelText, itemName);
panel.appendChild(panelText);
panel.appendChild(createElement("br"));
panel.appendChild(createElement("span", {
innerText:"Log", class:"active-scripts-button", margin:"4px", padding:"4px",
clickListener:()=>{
logBoxCreate(workerscript.scriptRef);
return false;
}
}));
panel.appendChild(createElement("span", {
innerText:"Kill Script", class:"active-scripts-button", margin:"4px", padding:"4px",
clickListener:()=>{
killWorkerScript(workerscript.scriptRef, workerscript.scriptRef.scriptRef.server);
dialogBoxCreate("Killing script, may take a few minutes to complete...");
return false;
}
}));
//Append element to list //Append element to list
var list = getActiveScriptsServerList(server); ActiveScriptsUI[hostname]["panelList"].appendChild(li);
list.appendChild(item); ActiveScriptsUI[hostname].scripts[itemName] = li;
ActiveScriptsUI[hostname].scriptHdrs[itemName] = hdr;
setActiveScriptsClickHandlers() //Reset click handlers ActiveScriptsUI[hostname].scriptStats[itemName] = panelText;
} }
function deleteActiveScriptsItem(workerscript) { function deleteActiveScriptsItem(workerscript) {
@ -162,18 +142,31 @@ function deleteActiveScriptsItem(workerscript) {
console.log("ERROR: Invalid server IP for workerscript."); console.log("ERROR: Invalid server IP for workerscript.");
return; return;
} }
let hostname = server.hostname;
if (ActiveScriptsUI[hostname] == null) {
console.log("ERROR: Trying to delete Active Script UI Element with a hostname that cant be found in ActiveScriptsUI: " + hostname);
return;
}
var itemNameArray = ["active", "scripts", server.hostname, workerscript.name]; var itemNameArray = ["active", "scripts", server.hostname, workerscript.name];
for (var i = 0; i < workerscript.args.length; ++i) { for (var i = 0; i < workerscript.args.length; ++i) {
itemNameArray.push(String(workerscript.args[i])); itemNameArray.push(String(workerscript.args[i]));
} }
var itemName = itemNameArray.join("-"); var itemName = itemNameArray.join("-");
var li = document.getElementById(itemName);
let li = ActiveScriptsUI[hostname].scripts[itemName];
if (li == null) { if (li == null) {
console.log("could not find Active scripts li element for: " + workerscript.name); console.log("ERROR: Cannot find Active Script UI element for workerscript: ");
console.log(workerscript);
return; return;
} }
li.parentNode.removeChild(li); removeElement(li);
delete ActiveScriptsUI[hostname].scripts[itemName];
delete ActiveScriptsUI[hostname].scriptHdrs[itemName];
delete ActiveScriptsUI[hostname].scriptStats[itemName];
if (Object.keys(ActiveScriptsUI[hostname].scripts).length === 0) {
deleteActiveScriptsServerPanel(server); deleteActiveScriptsServerPanel(server);
}
} }
//Update the ActiveScriptsItems array //Update the ActiveScriptsItems array
@ -197,69 +190,47 @@ function updateActiveScriptsItemContent(workerscript) {
console.log("ERROR: Invalid server IP for workerscript."); console.log("ERROR: Invalid server IP for workerscript.");
return; return;
} }
let hostname = server.hostname;
if (ActiveScriptsUI[hostname] == null) {
console.log("ERROR: Trying to update Active Script UI Element with a hostname that cant be found in ActiveScriptsUI: " + hostname);
return;
}
var itemNameArray = ["active", "scripts", server.hostname, workerscript.name]; var itemNameArray = ["active", "scripts", server.hostname, workerscript.name];
for (var i = 0; i < workerscript.args.length; ++i) { for (var i = 0; i < workerscript.args.length; ++i) {
itemNameArray.push(String(workerscript.args[i])); itemNameArray.push(String(workerscript.args[i]));
} }
var itemName = itemNameArray.join("-"); var itemName = itemNameArray.join("-");
var itemContent = document.getElementById(itemName + "-content") var item = ActiveScriptsUI[hostname].scriptStats[itemName];
//Add the updated text back. Returns the total online production rate //Update the text if necessary. This fn returns the online $/s production
return updateActiveScriptsText(workerscript, itemContent); return updateActiveScriptsText(workerscript, item, itemName);
} }
function createActiveScriptsText(workerscript, item) { function updateActiveScriptsText(workerscript, item, itemName) {
var itemTextHeader = document.createElement("p"); var server = getServer(workerscript.serverIp);
var itemTextStats = document.createElement("p"); if (server == null) {
var itemId = item.id; console.log("ERROR: Invalid server IP for workerscript.");
itemTextStats.setAttribute("id", itemId + "-stats"); return;
}
//Server ip/hostname let hostname = server.hostname;
var threads = "Threads: " + workerscript.scriptRef.threads; if (ActiveScriptsUI[hostname] == null) {
var args = "Args: " + printArray(workerscript.args); console.log("ERROR: Trying to update Active Script UI Element with a hostname that cant be found in ActiveScriptsUI: " + hostname);
return;
itemTextHeader.innerHTML = threads + "<br>" + args + "<br>";
item.appendChild(itemTextHeader);
item.appendChild(itemTextStats);
var onlineMps = updateActiveScriptsText(workerscript, item, itemTextStats);
var logButton = document.createElement("span");
logButton.innerHTML = "Log";
var killButton = document.createElement("span");
killButton.innerHTML = "Kill script";
logButton.setAttribute("class", "active-scripts-button");
killButton.setAttribute("class", "active-scripts-button");
logButton.addEventListener("click", function() {
logBoxCreate(workerscript.scriptRef);
return false;
});
killButton.addEventListener("click", function() {
killWorkerScript(workerscript.scriptRef, workerscript.scriptRef.scriptRef.server);
dialogBoxCreate("Killing script, may take a few minutes to complete...");
return false;
});
item.appendChild(logButton);
item.appendChild(killButton);
//Return total online production rate
return onlineMps;
}
function updateActiveScriptsText(workerscript, item, statsEl=null) {
var itemId = item.id
var itemTextStats = document.getElementById(itemId + "-stats");
if (itemTextStats == null || itemTextStats === undefined) {
itemTextStats = statsEl;
} }
//Updates statistics only var onlineMps = workerscript.scriptRef.onlineMoneyMade / workerscript.scriptRef.onlineRunningTime;
//Only update if the item is visible
if (ActiveScriptsUI[hostname].header.classList.contains("active") === false) {return onlineMps;}
if (ActiveScriptsUI[hostname].scriptHdrs[itemName].classList.contains("active") === false) {return onlineMps;}
removeChildrenFromElement(item);
//Online //Online
var onlineTotalMoneyMade = "Total online production: $" + formatNumber(workerscript.scriptRef.onlineMoneyMade, 2); var onlineTotalMoneyMade = "Total online production: $" + formatNumber(workerscript.scriptRef.onlineMoneyMade, 2);
var onlineTotalExpEarned = (Array(26).join(" ") + formatNumber(workerscript.scriptRef.onlineExpGained, 2) + " hacking exp").replace( / /g, "&nbsp;"); var onlineTotalExpEarned = (Array(26).join(" ") + formatNumber(workerscript.scriptRef.onlineExpGained, 2) + " hacking exp").replace( / /g, "&nbsp;");
var onlineMps = workerscript.scriptRef.onlineMoneyMade / workerscript.scriptRef.onlineRunningTime;
var onlineMpsText = "Online production rate: $" + formatNumber(onlineMps, 2) + "/second"; var onlineMpsText = "Online production rate: $" + formatNumber(onlineMps, 2) + "/second";
var onlineEps = workerscript.scriptRef.onlineExpGained / workerscript.scriptRef.onlineRunningTime; var onlineEps = workerscript.scriptRef.onlineExpGained / workerscript.scriptRef.onlineRunningTime;
var onlineEpsText = (Array(25).join(" ") + formatNumber(onlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;"); var onlineEpsText = (Array(25).join(" ") + formatNumber(onlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;");
@ -273,10 +244,10 @@ function updateActiveScriptsText(workerscript, item, statsEl=null) {
var offlineEps = workerscript.scriptRef.offlineExpGained / workerscript.scriptRef.offlineRunningTime; var offlineEps = workerscript.scriptRef.offlineExpGained / workerscript.scriptRef.offlineRunningTime;
var offlineEpsText = (Array(26).join(" ") + formatNumber(offlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;"); var offlineEpsText = (Array(26).join(" ") + formatNumber(offlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;");
itemTextStats.innerHTML = onlineTotalMoneyMade + "<br>" + onlineTotalExpEarned + "<br>" + item.innerHTML = onlineTotalMoneyMade + "<br>" + onlineTotalExpEarned + "<br>" +
onlineMpsText + "<br>" + onlineEpsText + "<br>" + offlineTotalMoneyMade + "<br>" + offlineTotalExpEarned + "<br>" + onlineMpsText + "<br>" + onlineEpsText + "<br>" + offlineTotalMoneyMade + "<br>" + offlineTotalExpEarned + "<br>" +
offlineMpsText + "<br>" + offlineEpsText + "<br>"; offlineMpsText + "<br>" + offlineEpsText + "<br>";
return onlineMps; return onlineMps;
} }
export {setActiveScriptsClickHandlers, addActiveScriptsItem, deleteActiveScriptsItem, updateActiveScriptsItems}; export {addActiveScriptsItem, deleteActiveScriptsItem, updateActiveScriptsItems};

@ -105,10 +105,10 @@ function initBitNodes() {
"for progression. Furthermore:<br><br>" + "for progression. Furthermore:<br><br>" +
"Hacking and Hacknet Nodes will be significantly less profitable<br>" + "Hacking and Hacknet Nodes will be significantly less profitable<br>" +
"Your hacking level is reduced by 50%<br>" + "Your hacking level is reduced by 50%<br>" +
"Hacking experience gain from scripts is reduced by 80%<br>" + "Hacking experience gain from scripts is reduced by 75%<br>" +
"Corporations have 80% lower valuations and are therefore less profitable<br>" + "Corporations have 80% lower valuations and are therefore less profitable<br>" +
"Working for companies is 50% less profitable<br>" + "Working for companies is 50% less profitable<br>" +
"Crimes and Infiltration are 75% less profitable<br><br>" + "Crimes and Infiltration are 50% less profitable<br><br>" +
"Destroying this BitNode will give you Source-File 6, or if you already have this Source-File it will upgrade " + "Destroying this BitNode will give you Source-File 6, or if you already have this Source-File it will upgrade " +
"its level up to a maximum of 3. This Source-File allows you to access the NSA's Bladeburner Division in other " + "its level up to a maximum of 3. This Source-File allows you to access the NSA's Bladeburner Division in other " +
"BitNodes. In addition, this Source-File will raise the experience gain rate of all your combat stats by:<br><br>" + "BitNodes. In addition, this Source-File will raise the experience gain rate of all your combat stats by:<br><br>" +
@ -274,12 +274,12 @@ function initBitNodeMultipliers() {
BitNodeMultipliers.ServerStartingSecurity = 1.5; BitNodeMultipliers.ServerStartingSecurity = 1.5;
BitNodeMultipliers.ScriptHackMoney = 0.5; BitNodeMultipliers.ScriptHackMoney = 0.5;
BitNodeMultipliers.CompanyWorkMoney = 0.5; BitNodeMultipliers.CompanyWorkMoney = 0.5;
BitNodeMultipliers.CrimeMoney = 0.25; BitNodeMultipliers.CrimeMoney = 0.5;
BitNodeMultipliers.InfiltrationMoney = 0.25; BitNodeMultipliers.InfiltrationMoney = 0.5;
BitNodeMultipliers.CorporationValuation = 0.2; BitNodeMultipliers.CorporationValuation = 0.2;
BitNodeMultipliers.HacknetNodeMoney = 0.2; BitNodeMultipliers.HacknetNodeMoney = 0.2;
BitNodeMultipliers.FactionPassiveRepGain = 0; BitNodeMultipliers.FactionPassiveRepGain = 0;
BitNodeMultipliers.HackExpGain = 0.2; BitNodeMultipliers.HackExpGain = 0.25;
break; break;
case 8: //Ghost of Wall Street case 8: //Ghost of Wall Street
BitNodeMultipliers.ScriptHackMoney = 0; BitNodeMultipliers.ScriptHackMoney = 0;

@ -691,9 +691,9 @@ Bladeburner.prototype.create = function() {
"and information-gathering ONLY. Do NOT engage. Stealth is of the utmost importance.<br><br>" + "and information-gathering ONLY. Do NOT engage. Stealth is of the utmost importance.<br><br>" +
"Successfully completing Tracking contracts will slightly improve your Synthoid population estimate for " + "Successfully completing Tracking contracts will slightly improve your Synthoid population estimate for " +
"whatever city you are currently in.", "whatever city you are currently in.",
baseDifficulty:150,difficultyFac:1.02,rewardFac:1.041, baseDifficulty:125,difficultyFac:1.02,rewardFac:1.041,
rankGain:0.3, hpLoss:0.5, rankGain:0.3, hpLoss:0.5,
count:getRandomInt(400, 800), countGrowth:getRandomInt(1, 5), count:getRandomInt(300, 800), countGrowth:getRandomInt(1, 5),
weights:{hack:0,str:0.05,def:0.05,dex:0.35,agi:0.35,cha:0.1, int:0.05}, weights:{hack:0,str:0.05,def:0.05,dex:0.35,agi:0.35,cha:0.1, int:0.05},
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.9, int:1}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.9, int:1},
isStealth:true isStealth:true
@ -705,7 +705,7 @@ Bladeburner.prototype.create = function() {
"current city, and will also increase its chaos level.", "current city, and will also increase its chaos level.",
baseDifficulty:250, difficultyFac:1.04,rewardFac:1.085, baseDifficulty:250, difficultyFac:1.04,rewardFac:1.085,
rankGain:0.9, hpLoss:1, rankGain:0.9, hpLoss:1,
count:getRandomInt(250, 500), countGrowth:getRandomInt(1, 3), count:getRandomInt(200, 750), countGrowth:getRandomInt(1, 3),
weights:{hack:0,str:0.15,def:0.15,dex:0.25,agi:0.25,cha:0.1, int:0.1}, weights:{hack:0,str:0.15,def:0.15,dex:0.25,agi:0.25,cha:0.1, int:0.1},
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
isKill:true isKill:true
@ -717,7 +717,7 @@ Bladeburner.prototype.create = function() {
"city, and will also increase its chaos level.", "city, and will also increase its chaos level.",
baseDifficulty:200, difficultyFac:1.03, rewardFac:1.065, baseDifficulty:200, difficultyFac:1.03, rewardFac:1.065,
rankGain:0.6, hpLoss:1, rankGain:0.6, hpLoss:1,
count:getRandomInt(300, 600), countGrowth:getRandomInt(1,4), count:getRandomInt(300, 900), countGrowth:getRandomInt(1,4),
weights:{hack:0,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0.1, int:0.1}, weights:{hack:0,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0.1, int:0.1},
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
isKill:true isKill:true
@ -732,7 +732,7 @@ Bladeburner.prototype.create = function() {
"You will NOT lose HP from failed Investigation ops.", "You will NOT lose HP from failed Investigation ops.",
baseDifficulty:400, difficultyFac:1.03,rewardFac:1.07,reqdRank:25, baseDifficulty:400, difficultyFac:1.03,rewardFac:1.07,reqdRank:25,
rankGain:2, rankLoss:0.2, rankGain:2, rankLoss:0.2,
count:getRandomInt(100, 300), countGrowth:1, count:getRandomInt(50, 400), countGrowth:1,
weights:{hack:0.25,str:0.05,def:0.05,dex:0.2,agi:0.1,cha:0.25, int:0.1}, weights:{hack:0.25,str:0.05,def:0.05,dex:0.2,agi:0.1,cha:0.25, int:0.1},
decays:{hack:0.85,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9}, decays:{hack:0.85,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
isStealth:true isStealth:true
@ -745,7 +745,7 @@ Bladeburner.prototype.create = function() {
"data.", "data.",
baseDifficulty:500, difficultyFac:1.04, rewardFac:1.09, reqdRank:100, baseDifficulty:500, difficultyFac:1.04, rewardFac:1.09, reqdRank:100,
rankGain:4, rankLoss:0.4, hpLoss:2, rankGain:4, rankLoss:0.4, hpLoss:2,
count:getRandomInt(100, 250), countGrowth:1, count:getRandomInt(50, 300), countGrowth:1,
weights:{hack:0.2,str:0.05,def:0.05,dex:0.2,agi:0.2,cha:0.2, int:0.1}, weights:{hack:0.2,str:0.05,def:0.05,dex:0.2,agi:0.2,cha:0.2, int:0.1},
decays:{hack:0.8,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9}, decays:{hack:0.8,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
isStealth:true isStealth:true
@ -756,7 +756,7 @@ Bladeburner.prototype.create = function() {
"notorious Synthoid criminals.", "notorious Synthoid criminals.",
baseDifficulty:650, difficultyFac:1.04, rewardFac:1.095, reqdRank:500, baseDifficulty:650, difficultyFac:1.04, rewardFac:1.095, reqdRank:500,
rankGain:5, rankLoss:0.5, hpLoss:2.5, rankGain:5, rankLoss:0.5, hpLoss:2.5,
count:getRandomInt(100,250), countGrowth:0.75, count:getRandomInt(25,400), countGrowth:0.75,
weights:{hack:0.25,str:0.05,def:0.05,dex:0.25,agi:0.1,cha:0.2, int:0.1}, weights:{hack:0.25,str:0.05,def:0.05,dex:0.25,agi:0.1,cha:0.2, int:0.1},
decays:{hack:0.8,str:0.85,def:0.85,dex:0.85,agi:0.85,cha:0.7, int:0.9}, decays:{hack:0.8,str:0.85,def:0.85,dex:0.85,agi:0.85,cha:0.7, int:0.9},
isStealth:true isStealth:true
@ -768,7 +768,7 @@ Bladeburner.prototype.create = function() {
"in order for this Operation to be successful", "in order for this Operation to be successful",
baseDifficulty:800, difficultyFac:1.045, rewardFac:1.1, reqdRank:3000, baseDifficulty:800, difficultyFac:1.045, rewardFac:1.1, reqdRank:3000,
rankGain:50,rankLoss:2.5,hpLoss:50, rankGain:50,rankLoss:2.5,hpLoss:50,
count:getRandomInt(50, 100), countGrowth:0.2, count:getRandomInt(25, 150), countGrowth:0.2,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9}, decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
isKill:true isKill:true
@ -780,7 +780,7 @@ Bladeburner.prototype.create = function() {
"drawing any attention. Stealth and discretion are key.", "drawing any attention. Stealth and discretion are key.",
baseDifficulty:1000, difficultyFac:1.05, rewardFac:1.11, reqdRank:20e3, baseDifficulty:1000, difficultyFac:1.05, rewardFac:1.11, reqdRank:20e3,
rankGain:20, rankLoss:2, hpLoss:10, rankGain:20, rankLoss:2, hpLoss:10,
count:getRandomInt(50, 200), countGrowth:0.1, count:getRandomInt(25, 250), countGrowth:0.1,
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1}, weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9}, decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
isStealth:true, isKill:true isStealth:true, isKill:true
@ -792,7 +792,7 @@ Bladeburner.prototype.create = function() {
"in the Synthoid communities.", "in the Synthoid communities.",
baseDifficulty:1500, difficultyFac:1.06, rewardFac:1.14, reqdRank:50e3, baseDifficulty:1500, difficultyFac:1.06, rewardFac:1.14, reqdRank:50e3,
rankGain:40, rankLoss:4, hpLoss:5, rankGain:40, rankLoss:4, hpLoss:5,
count:getRandomInt(50, 150), countGrowth:0.1, count:getRandomInt(25, 200), countGrowth:0.1,
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1}, weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.8}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.8},
isStealth:true, isKill:true isStealth:true, isKill:true
@ -3202,11 +3202,11 @@ function initBladeburner() {
Skills[SkillNames.Datamancer] = new Skill({ Skills[SkillNames.Datamancer] = new Skill({
name:SkillNames.Datamancer, name:SkillNames.Datamancer,
desc:"Each level of this skill increases your effectiveness in " + desc:"Each level of this skill increases your effectiveness in " +
"synthoid population analysis and investigation by 4%. " + "synthoid population analysis and investigation by 5%. " +
"This affects all actions that can potentially increase " + "This affects all actions that can potentially increase " +
"the accuracy of your synthoid population/community estimates.", "the accuracy of your synthoid population/community estimates.",
baseCost:3,costInc:1, baseCost:3,costInc:1,
successChanceEstimate:4 successChanceEstimate:5
}); });
Skills[SkillNames.Tracer] = new Skill({ Skills[SkillNames.Tracer] = new Skill({
name:SkillNames.Tracer, name:SkillNames.Tracer,

@ -40,6 +40,7 @@ let CONSTANTS = {
/* Netscript Constants */ /* Netscript Constants */
//RAM Costs for different commands //RAM Costs for different commands
ScriptBaseRamCost: 1.4,
ScriptWhileRamCost: 0.2, ScriptWhileRamCost: 0.2,
ScriptForRamCost: 0.2, ScriptForRamCost: 0.2,
ScriptIfRamCost: 0.15, ScriptIfRamCost: 0.15,
@ -1139,7 +1140,14 @@ let CONSTANTS = {
LatestUpdate: LatestUpdate:
"v0.36.1<br>" + "v0.36.1<br>" +
"* Bladeburner Changes: <br>" +
"** Bug Fix: You can no longer get Bladeburner faction reputation through Infiltration<br>" +
"** Initial difficulty of Tracking contracts reduced<br>" +
"* Crime, Infiltration, and Hacking are now slightly more profitable in BN-6<br>" +
"* The ctrl+b hotkey in the text editor is now also triggered by command+b or winkey+b<br>" + "* The ctrl+b hotkey in the text editor is now also triggered by command+b or winkey+b<br>" +
"* Many servers now have additional RAM<br>" +
"* Added an option to disable hotkeys/keyboard shortcuts<br>" +
"* Refactored 'Active Scripts' UI page to optimize its performance<br>" +
"v0.36.0<br>" + "v0.36.0<br>" +
"* Added BN-6: Bladeburners<br>" + "* Added BN-6: Bladeburners<br>" +
"* Rebalanced many combat Augmentations so that they are slightly less powerful<br>" + "* Rebalanced many combat Augmentations so that they are slightly less powerful<br>" +

@ -2013,7 +2013,10 @@ function purchaseTorRouter() {
} }
Player.loseMoney(CONSTANTS.TorRouterCost); Player.loseMoney(CONSTANTS.TorRouterCost);
var darkweb = new Server(createRandomIp(), "darkweb", "", false, false, false, 1); var darkweb = new Server({
ip:createRandomIp(), hostname:"darkweb", organizationName:"",
isConnectedTo:false, adminRights:false, purchasedByPlayer:false, maxRam:1
});
AddToAllServers(darkweb); AddToAllServers(darkweb);
SpecialServerIps.addIp("Darkweb Server", darkweb.ip); SpecialServerIps.addIp("Darkweb Server", darkweb.ip);

@ -1633,7 +1633,15 @@ function NetscriptFunctions(workerScript) {
workerScript.scriptRef.log("Error: Not enough money to purchase server. Need $" + formatNumber(cost, 2)); workerScript.scriptRef.log("Error: Not enough money to purchase server. Need $" + formatNumber(cost, 2));
return ""; return "";
} }
var newServ = new Server(createRandomIp(), hostnameStr, "", false, true, true, ram); var newServ = new Server({
ip: createRandomIp(),
hostname: hostnameStr,
organizationName: "",
isConnectedTo: false,
adminRights: true,
purchasedByPlayer: true,
maxRam: ram,
});
AddToAllServers(newServ); AddToAllServers(newServ);
Player.purchasedServers.push(newServ.ip); Player.purchasedServers.push(newServ.ip);
@ -1994,7 +2002,11 @@ function NetscriptFunctions(workerScript) {
} }
return suc; return suc;
}, },
getScriptRam : function (scriptname, ip=workerScript.serverIp) { getScriptName : function() {
if (workerScript.checkingRam) {return 0;}
return workerScript.name;
},
getScriptRam : function (scriptname, ip=workerScript.serverIp)
if (workerScript.checkingRam) { if (workerScript.checkingRam) {
if (workerScript.loadedFns.getScriptRam) { if (workerScript.loadedFns.getScriptRam) {
return 0; return 0;
@ -2432,7 +2444,10 @@ function NetscriptFunctions(workerScript) {
} }
Player.loseMoney(CONSTANTS.TorRouterCost); Player.loseMoney(CONSTANTS.TorRouterCost);
var darkweb = new Server(createRandomIp(), "darkweb", "", false, false, false, 1); var darkweb = new Server({
ip:createRandomIp(), hostname:"darkweb", organizationName:"",
isConnectedTo:false, adminRights:false, purchasedByPlayer:false, maxRam:1
});
AddToAllServers(darkweb); AddToAllServers(darkweb);
SpecialServerIps.addIp("Darkweb Server", darkweb.ip); SpecialServerIps.addIp("Darkweb Server", darkweb.ip);

@ -62,29 +62,32 @@ function prestigeWorkerScripts() {
function startJsScript(workerScript) { function startJsScript(workerScript) {
workerScript.running = true; workerScript.running = true;
// The name of the currently running netscript function, to prevent concurrent
// calls to hack, grow, etc.
let runningFn = null;
// We need to go through the environment and wrap each function in such a way that it // We need to go through the environment and wrap each function in such a way that it
// can be called at most once at a time. This will prevent situations where multiple // can be called at most once at a time. This will prevent situations where multiple
// hack promises are outstanding, for example. // hack promises are outstanding, for example.
function wrap(propName, f) { function wrap(propName, f) {
let running = null; // The name of the currently running netscript function.
// This function unfortunately cannot be an async function, because we don't // This function unfortunately cannot be an async function, because we don't
// know if the original one was, and there's no way to tell. // know if the original one was, and there's no way to tell.
return function (...args) { return function (...args) {
const msg = "Concurrent calls to Netscript functions not allowed! " + const msg = "Concurrent calls to Netscript functions not allowed! " +
"Did you forget to await hack(), grow(), or some other " + "Did you forget to await hack(), grow(), or some other " +
"promise-returning function? (Currently running: %s tried to run: %s)" "promise-returning function? (Currently running: %s tried to run: %s)"
if (running) { if (runningFn) {
workerScript.errorMessage = makeRuntimeRejectMsg(workerScript, sprintf(msg, running, propName), null) workerScript.errorMessage = makeRuntimeRejectMsg(workerScript, sprintf(msg, runningFn, propName), null)
throw workerScript; throw workerScript;
} }
running = propName; runningFn = propName;
let result = f(...args); let result = f(...args);
if (result && result.finally !== undefined) { if (result && result.finally !== undefined) {
return result.finally(function () { return result.finally(function () {
running = null; runningFn = null;
}); });
} else { } else {
running = null; runningFn = null;
return result; return result;
} }
} }
@ -104,7 +107,8 @@ function startJsScript(workerScript) {
return [mainReturnValue, workerScript]; return [mainReturnValue, workerScript];
}).catch(e => { }).catch(e => {
if (e instanceof Error) { if (e instanceof Error) {
workerScript.errorMessage = makeRuntimeRejectMsg(workerScript, e.message + (e.stack && ("\nstack:\n" + e.stack.toString()) || "")); workerScript.errorMessage = makeRuntimeRejectMsg(
workerScript, e.message + (e.stack && ("\nstack:\n" + e.stack.toString()) || ""));
throw workerScript; throw workerScript;
} else if (isScriptErrorMessage(e)) { } else if (isScriptErrorMessage(e)) {
workerScript.errorMessage = e; workerScript.errorMessage = e;

@ -210,7 +210,10 @@ function PlayerObject() {
PlayerObject.prototype.init = function() { PlayerObject.prototype.init = function() {
/* Initialize Player's home computer */ /* Initialize Player's home computer */
var t_homeComp = new Server(createRandomIp(), "home", "Home PC", true, true, true, 8); var t_homeComp = new Server({
ip:createRandomIp(), hostname:"home", organizationName:"Home PC",
isConnectedTo:true, adminRights:true, purchasedByPlayer:true, maxRam:8
});
this.homeComputer = t_homeComp.ip; this.homeComputer = t_homeComp.ip;
this.currentServer = t_homeComp.ip; this.currentServer = t_homeComp.ip;
AddToAllServers(t_homeComp); AddToAllServers(t_homeComp);

@ -233,6 +233,7 @@ function updateScriptEditorContent() {
//Define key commands in script editor (ctrl o to save + close, etc.) //Define key commands in script editor (ctrl o to save + close, etc.)
$(document).keydown(function(e) { $(document).keydown(function(e) {
if (Settings.DisableHotkeys === true) {return;}
if (Engine.currentPage == Engine.Page.ScriptEditor) { if (Engine.currentPage == Engine.Page.ScriptEditor) {
//Ctrl + b //Ctrl + b
if (e.keyCode == 66 && (e.ctrlKey || e.metaKey)) { if (e.keyCode == 66 && (e.ctrlKey || e.metaKey)) {
@ -417,7 +418,7 @@ function parseOnlyRamCalculate(server, code, workerScript) {
// Finally, walk the reference map and generate a ram cost. The initial set of keys to scan // Finally, walk the reference map and generate a ram cost. The initial set of keys to scan
// are those that start with __SPECIAL_INITIAL_MODULE__. // are those that start with __SPECIAL_INITIAL_MODULE__.
let ram = 1.4; let ram = CONSTANTS.ScriptBaseRamCost;
const unresolvedRefs = Object.keys(dependencyMap).filter(s => s.startsWith(initialModule)); const unresolvedRefs = Object.keys(dependencyMap).filter(s => s.startsWith(initialModule));
const resolvedRefs = new Set(); const resolvedRefs = new Set();
while (unresolvedRefs.length > 0) { while (unresolvedRefs.length > 0) {

@ -23,16 +23,16 @@ function Server(params={ip:createRandomIp(), hostname:""}) {
++i; ++i;
} }
this.hostname = hostname + suffix; this.hostname = hostname + suffix;
this.organizationName = params.organizationName ? params.organizationName : ""; this.organizationName = params.organizationName != null ? params.organizationName : "";
this.isConnectedTo = params.isConnectedTo ? params.isConnectedTo : false; this.isConnectedTo = params.isConnectedTo != null ? params.isConnectedTo : false;
//Access information //Access information
this.hasAdminRights = params.adminRights ? params.adminRights : false; this.hasAdminRights = params.adminRights != null ? params.adminRights : false;
this.purchasedByPlayer = params.purchasedByPlayer ? params.purchasedByPlayer : false; this.purchasedByPlayer = params.purchasedByPlayer != null ? params.purchasedByPlayer : false;
this.manuallyHacked = false; //Flag that tracks whether or not the server has been hacked at least once this.manuallyHacked = false; //Flag that tracks whether or not the server has been hacked at least once
//RAM, CPU speed and Scripts //RAM, CPU speed and Scripts
this.maxRam = params.maxRam ? params.maxRam : 0; //GB this.maxRam = params.maxRam != null ? params.maxRam : 0; //GB
this.ramUsed = 0; this.ramUsed = 0;
this.cpuCores = 1; //Max of 8, affects hacking times and Hacking Mission starting Cores this.cpuCores = 1; //Max of 8, affects hacking times and Hacking Mission starting Cores
@ -44,22 +44,22 @@ function Server(params={ip:createRandomIp(), hostname:""}) {
this.dir = 0; //new Directory(this, null, ""); TODO this.dir = 0; //new Directory(this, null, ""); TODO
/* Hacking information (only valid for "foreign" aka non-purchased servers) */ /* Hacking information (only valid for "foreign" aka non-purchased servers) */
this.requiredHackingSkill = params.requiredHackingSkill ? params.requiredHackingSkill : 1; this.requiredHackingSkill = params.requiredHackingSkill != null ? params.requiredHackingSkill : 1;
this.moneyAvailable = params.moneyAvailable ? params.moneyAvailable * BitNodeMultipliers.ServerStartingMoney : 1e6; this.moneyAvailable = params.moneyAvailable != null ? params.moneyAvailable * BitNodeMultipliers.ServerStartingMoney : 0;
this.moneyMax = 25 * this.moneyAvailable * BitNodeMultipliers.ServerMaxMoney; this.moneyMax = 25 * this.moneyAvailable * BitNodeMultipliers.ServerMaxMoney;
//Hack Difficulty is synonymous with server security. Base Difficulty = Starting difficulty //Hack Difficulty is synonymous with server security. Base Difficulty = Starting difficulty
this.hackDifficulty = params.hackDifficulty ? params.hackDifficulty * BitNodeMultipliers.ServerStartingSecurity : 1; this.hackDifficulty = params.hackDifficulty != null ? params.hackDifficulty * BitNodeMultipliers.ServerStartingSecurity : 1;
this.baseDifficulty = this.hackDifficulty; this.baseDifficulty = this.hackDifficulty;
this.minDifficulty = Math.max(1, Math.round(this.hackDifficulty / 3)); this.minDifficulty = Math.max(1, Math.round(this.hackDifficulty / 3));
this.serverGrowth = params.serverGrowth ? params.serverGrowth : 1; //Integer from 0 to 100. Affects money increase from grow() this.serverGrowth = params.serverGrowth != null ? params.serverGrowth : 1; //Integer from 0 to 100. Affects money increase from grow()
//The IP's of all servers reachable from this one (what shows up if you run scan/netstat) //The IP's of all servers reachable from this one (what shows up if you run scan/netstat)
// NOTE: Only contains IP and not the Server objects themselves // NOTE: Only contains IP and not the Server objects themselves
this.serversOnNetwork = []; this.serversOnNetwork = [];
//Port information, required for porthacking servers to get admin rights //Port information, required for porthacking servers to get admin rights
this.numOpenPortsRequired = params.numOpenPortsRequired ? params.numOpenPortsRequired : 5; this.numOpenPortsRequired = params.numOpenPortsRequired != null ? params.numOpenPortsRequired : 5;
this.sshPortOpen = false; //Port 22 this.sshPortOpen = false; //Port 22
this.ftpPortOpen = false; //Port 21 this.ftpPortOpen = false; //Port 21
this.smtpPortOpen = false; //Port 25 this.smtpPortOpen = false; //Port 25
@ -527,7 +527,6 @@ function initForeignServers() {
requiredHackingSkill:20, moneyAvailable:2.75e6, requiredHackingSkill:20, moneyAvailable:2.75e6,
hackDifficulty:20, serverGrowth:25, numOpenPortsRequired:0 hackDifficulty:20, serverGrowth:25, numOpenPortsRequired:0
}); });
NectarNightclubServer.setPortProperties(0);
AddToAllServers(NectarNightclubServer); AddToAllServers(NectarNightclubServer);
var NeoNightclubServer = new Server({ var NeoNightclubServer = new Server({

@ -32,7 +32,10 @@ function purchaseServer(ram, cost) {
} }
//Create server //Create server
var newServ = new Server(createRandomIp(), hostname, "", false, true, true, ram); var newServ = new Server({
ip:createRandomIp(), hostname:hostname, organizationName:"",
isConnectedTo:false, adminRights:true, purchasedByPlayer:true, maxRam:ram
});
AddToAllServers(newServ); AddToAllServers(newServ);
//Add to Player's purchasedServers array //Add to Player's purchasedServers array

@ -8,6 +8,7 @@ let Settings = {
SuppressMessages: false, SuppressMessages: false,
SuppressFactionInvites: false, SuppressFactionInvites: false,
AutosaveInterval: 60, AutosaveInterval: 60,
DisableHotkeys: false,
ThemeHighlightColor: "#ffffff", ThemeHighlightColor: "#ffffff",
ThemeFontColor: "#66ff33", ThemeFontColor: "#66ff33",
ThemeBackgroundColor: "#000000", ThemeBackgroundColor: "#000000",
@ -26,6 +27,7 @@ function initSettings() {
Settings.SuppressMessages = false; Settings.SuppressMessages = false;
Settings.SuppressFactionInvites = false; Settings.SuppressFactionInvites = false;
Settings.AutosaveInterval = 60; Settings.AutosaveInterval = 60;
Settings.DisableHotkeys = false;
} }
function setSettingsLabels() { function setSettingsLabels() {
@ -35,6 +37,7 @@ function setSettingsLabels() {
var suppressMsgs = document.getElementById("settingsSuppressMessages"); var suppressMsgs = document.getElementById("settingsSuppressMessages");
var suppressFactionInv = document.getElementById("settingsSuppressFactionInvites") var suppressFactionInv = document.getElementById("settingsSuppressFactionInvites")
var autosaveInterval = document.getElementById("settingsAutosaveIntervalValLabel"); var autosaveInterval = document.getElementById("settingsAutosaveIntervalValLabel");
var disableHotkeys = document.getElementById("settingsDisableHotkeys");
//Initialize values on labels //Initialize values on labels
nsExecTime.innerHTML = Settings.CodeInstructionRunTime + "ms"; nsExecTime.innerHTML = Settings.CodeInstructionRunTime + "ms";
@ -43,6 +46,7 @@ function setSettingsLabels() {
suppressMsgs.checked = Settings.SuppressMessages; suppressMsgs.checked = Settings.SuppressMessages;
suppressFactionInv.checked = Settings.SuppressFactionInvites; suppressFactionInv.checked = Settings.SuppressFactionInvites;
autosaveInterval.innerHTML = Settings.AutosaveInterval; autosaveInterval.innerHTML = Settings.AutosaveInterval;
disableHotkeys.checked = Settings.DisableHotkeys;
//Set handlers for when input changes //Set handlers for when input changes
var nsExecTimeInput = document.getElementById("settingsNSExecTimeRangeVal"); var nsExecTimeInput = document.getElementById("settingsNSExecTimeRangeVal");
@ -79,14 +83,18 @@ function setSettingsLabels() {
} }
}; };
document.getElementById("settingsSuppressMessages").onclick = function() { suppressMsgs.onclick = function() {
Settings.SuppressMessages = this.checked; Settings.SuppressMessages = this.checked;
}; };
document.getElementById("settingsSuppressFactionInvites").onclick = function() { suppressFactionInv.onclick = function() {
Settings.SuppressFactionInvites = this.checked; Settings.SuppressFactionInvites = this.checked;
}; };
disableHotkeys.onclick = function() {
Settings.DisableHotkeys = this.checked;
}
//Theme //Theme
if (Settings.ThemeHighlightColor == null || Settings.ThemeFontColor == null || Settings.ThemeBackgroundColor == null) { if (Settings.ThemeHighlightColor == null || Settings.ThemeFontColor == null || Settings.ThemeBackgroundColor == null) {
console.log("ERROR: Cannot find Theme Settings"); console.log("ERROR: Cannot find Theme Settings");

@ -86,11 +86,15 @@ var KEY = {
E: 69, E: 69,
F: 70, F: 70,
H: 72, H: 72,
J: 74,
K: 75, K: 75,
L: 76, L: 76,
M: 77, M: 77,
N: 78, N: 78,
O: 79,
P: 80, P: 80,
R: 82,
S: 83,
U: 85, U: 85,
W: 87, W: 87,
} }
@ -259,9 +263,9 @@ $(document).keydown(function(event) {
}); });
//Keep terminal in focus //Keep terminal in focus
let terminalCtrlPressed = false; let terminalCtrlPressed = false, shiftKeyPressed = false;
$(document).ready(function() { $(document).ready(function() {
if (Engine.currentPage == Engine.Page.Terminal) { if (Engine.currentPage === Engine.Page.Terminal) {
$('.terminal-input').focus(); $('.terminal-input').focus();
} }
}); });
@ -269,15 +273,16 @@ $(document).keydown(function(e) {
if (Engine.currentPage == Engine.Page.Terminal) { if (Engine.currentPage == Engine.Page.Terminal) {
if (e.which == 17) { if (e.which == 17) {
terminalCtrlPressed = true; terminalCtrlPressed = true;
} else if (terminalCtrlPressed == true) { } else if (e.shiftKey) {
shiftKeyPressed = true;
} else if (terminalCtrlPressed || shiftKeyPressed) {
//Don't focus //Don't focus
} else { } else {
var inputTextBox = document.getElementById("terminal-input-text-box"); var inputTextBox = document.getElementById("terminal-input-text-box");
if (inputTextBox != null) { if (inputTextBox != null) {inputTextBox.focus();}
inputTextBox.focus();
}
terminalCtrlPressed = false; terminalCtrlPressed = false;
shiftKeyPressed = false;
} }
} }
}) })
@ -286,6 +291,9 @@ $(document).keyup(function(e) {
if (e.which == 17) { if (e.which == 17) {
terminalCtrlPressed = false; terminalCtrlPressed = false;
} }
if (e.shiftKey) {
shiftKeyPressed = false;
}
} }
}) })
@ -1304,12 +1312,11 @@ let Terminal = {
} }
//Check if its a script or just a program/executable //Check if its a script or just a program/executable
if (isScriptFilename(executableName) == -1) { //if (isScriptFilename(executableName)) {
// Not a script if (executableName.includes(".script") || executableName.includes(".js") || executableName.includes(".ns")) {
Terminal.runProgram(executableName);
} else {
//Script
Terminal.runScript(executableName); Terminal.runScript(executableName);
} else {
Terminal.runProgram(executableName);
} }
} }
break; break;

@ -9,8 +9,7 @@ import {formatNumber,
import {loxBoxCreate, logBoxUpdateText, import {loxBoxCreate, logBoxUpdateText,
logBoxOpened} from "../utils/LogBox.js"; logBoxOpened} from "../utils/LogBox.js";
import {setActiveScriptsClickHandlers, import {updateActiveScriptsItems} from "./ActiveScriptsUI.js";
updateActiveScriptsItems} from "./ActiveScriptsUI.js";
import {Augmentations, installAugmentations, import {Augmentations, installAugmentations,
initAugmentations, AugmentationNames, initAugmentations, AugmentationNames,
displayAugmentationsContent} from "./Augmentations.js"; displayAugmentationsContent} from "./Augmentations.js";
@ -58,7 +57,7 @@ import {StockMarket, StockSymbols,
initSymbolToStockMap, stockMarketCycle, initSymbolToStockMap, stockMarketCycle,
updateStockPrices, updateStockPrices,
displayStockMarketContent} from "./StockMarket.js"; displayStockMarketContent} from "./StockMarket.js";
import {Terminal, postNetburnerText, post} from "./Terminal.js"; import {Terminal, postNetburnerText, post, KEY} from "./Terminal.js";
/* Shortcuts to navigate through the game /* Shortcuts to navigate through the game
* Alt-t - Terminal * Alt-t - Terminal
@ -76,51 +75,52 @@ import {Terminal, postNetburnerText, post} from "./Terminal.js";
* Alt-o - Options * Alt-o - Options
*/ */
$(document).keydown(function(e) { $(document).keydown(function(e) {
if (Settings.DisableHotkeys === true) {return;}
if (!Player.isWorking && !redPillFlag && !inMission && !cinematicTextFlag) { if (!Player.isWorking && !redPillFlag && !inMission && !cinematicTextFlag) {
if (e.keyCode == 84 && e.altKey) { if (e.keyCode == 84 && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadTerminalContent(); Engine.loadTerminalContent();
} else if (e.keyCode == 67 && e.altKey) { } else if (e.keyCode === KEY.C && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadCharacterContent(); Engine.loadCharacterContent();
} else if (e.keyCode == 69 && e.altKey) { } else if (e.keyCode === KEY.E && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadScriptEditorContent(); Engine.loadScriptEditorContent();
} else if (e.keyCode == 83 && e.altKey) { } else if (e.keyCode === KEY.S && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadActiveScriptsContent(); Engine.loadActiveScriptsContent();
} else if (e.keyCode == 72 && e.altKey) { } else if (e.keyCode === KEY.H && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadHacknetNodesContent(); Engine.loadHacknetNodesContent();
} else if (e.keyCode == 87 && e.altKey) { } else if (e.keyCode === KEY.W && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadWorldContent(); Engine.loadWorldContent();
} else if (e.keyCode == 74 && e.altKey) { } else if (e.keyCode === KEY.J && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadJobContent(); Engine.loadJobContent();
} else if (e.keyCode == 82 && e.altKey) { } else if (e.keyCode === KEY.R && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadTravelContent(); Engine.loadTravelContent();
} else if (e.keyCode == 80 && e.altKey) { } else if (e.keyCode === KEY.P && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadCreateProgramContent(); Engine.loadCreateProgramContent();
} else if (e.keyCode == 70 && e.altKey) { } else if (e.keyCode === KEY.F && e.altKey) {
//Overriden by Fconf //Overriden by Fconf
if (Engine.currentPage === Engine.Page.Terminal && FconfSettings.ENABLE_BASH_HOTKEYS) { if (Engine.currentPage === Engine.Page.Terminal && FconfSettings.ENABLE_BASH_HOTKEYS) {
return; return;
} }
e.preventDefault(); e.preventDefault();
Engine.loadFactionsContent(); Engine.loadFactionsContent();
} else if (e.keyCode == 65 && e.altKey) { } else if (e.keyCode === KEY.A && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadAugmentationsContent(); Engine.loadAugmentationsContent();
} else if (e.keyCode == 85 && e.altKey) { } else if (e.keyCode === KEY.U && e.altKey) {
e.preventDefault(); e.preventDefault();
Engine.loadTutorialContent(); Engine.loadTutorialContent();
} }
} }
if (e.keyCode == 79 && e.altKey) { if (e.keyCode === KEY.O && e.altKey) {
e.preventDefault(); e.preventDefault();
gameOptionsBoxOpen(); gameOptionsBoxOpen();
} }
@ -260,7 +260,6 @@ let Engine = {
loadActiveScriptsContent: function() { loadActiveScriptsContent: function() {
Engine.hideAllContent(); Engine.hideAllContent();
Engine.Display.activeScriptsContent.style.display = "block"; Engine.Display.activeScriptsContent.style.display = "block";
setActiveScriptsClickHandlers();
updateActiveScriptsItems(); updateActiveScriptsItems();
Engine.currentPage = Engine.Page.ActiveScripts; Engine.currentPage = Engine.Page.ActiveScripts;
document.getElementById("active-scripts-menu-link").classList.add("active"); document.getElementById("active-scripts-menu-link").classList.add("active");
@ -963,7 +962,7 @@ let Engine = {
} else if (Engine.currentPage === Engine.Page.Corporation) { } else if (Engine.currentPage === Engine.Page.Corporation) {
Player.corporation.updateUIContent(); Player.corporation.updateUIContent();
} }
Engine.Counters.updateDisplaysMed = 9; Engine.Counters.updateDisplaysMed = 6;
} }
if (Engine.Counters.updateDisplaysLong <= 0) { if (Engine.Counters.updateDisplaysLong <= 0) {

@ -61,6 +61,7 @@ function infiltrationBoxCreate(inst) {
var selector = document.getElementById("infiltration-faction-select"); var selector = document.getElementById("infiltration-faction-select");
selector.innerHTML = ""; selector.innerHTML = "";
for (var i = 0; i < Player.factions.length; ++i) { for (var i = 0; i < Player.factions.length; ++i) {
if (Player.factions[i] === "Bladeburners") {continue;}
selector.innerHTML += "<option value='" + Player.factions[i] + selector.innerHTML += "<option value='" + Player.factions[i] +
"'>" + Player.factions[i] + "</option>"; "'>" + Player.factions[i] + "</option>";
} }