Refactored Active Scripts UI. Can no longer gain Bladeburner faction rep from infiltration. Added Disable Hotkeys setting

This commit is contained in:
danielyxie 2018-05-06 15:27:47 -05:00
parent 8dba456b65
commit 4ea365da02
15 changed files with 243 additions and 239 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>

@ -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};

@ -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

@ -1139,7 +1139,12 @@ 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>" +
"* 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>" +
"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>" +

@ -62,11 +62,12 @@ function prestigeWorkerScripts() {
function startJsScript(workerScript) { function startJsScript(workerScript) {
workerScript.running = true; workerScript.running = true;
let running = null; // The name of the currently running netscript function.
// 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) {

@ -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)) {

@ -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 : 1e6;
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({

@ -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>";
} }