Merge branch 'master' of https://github.com/danielyxie/netburner into bugfixes

This commit is contained in:
danielyxie 2017-09-01 15:41:17 -05:00
commit c34e74f5c1
54 changed files with 68024 additions and 1815 deletions

3
.gitignore vendored

@ -1,3 +1,4 @@
Changelog.txt Changelog.txt
Netburner.txt Netburner.txt
README.md README.md
/node_modules

@ -40,6 +40,7 @@
-moz-box-shadow: 1px 1px 3px #000; -moz-box-shadow: 1px 1px 3px #000;
-webkit-box-shadow: 1px 1px 3px #000; -webkit-box-shadow: 1px 1px 3px #000;
box-shadow: 1px 1px 3px #000; box-shadow: 1px 1px 3px #000;
background-color:black;
} }
#interactive-tutorial-exit { #interactive-tutorial-exit {
@ -65,4 +66,3 @@
text-decoration: none; text-decoration: none;
cursor: pointer; cursor: pointer;
} }

@ -16,6 +16,42 @@
} }
/* Script Editor */ /* Script Editor */
#script-editor-container {
background-color:transparent;
}
#javascript-editor {
margin: 10px;
height: 80%;
width: 100%;
margin-left: 6px;
padding-left: 6px;
padding-top: 6px;
padding-bottom: 6px;
border: 2px solid var(--my-highlight-color);
z-index: 1;
font-family: 'Lucida Console', 'Lucida Sans Unicode', 'Fira Mono', 'Consolas', 'Courier New', Courier, monospace, 'Times New Roman';
}
#javascript-editor textarea {
color: var(--my-font-color);
}
.ace_line,
.ace_line * {
color: var(--my-font-color);
background-color:transparent;
margin:0px;
padding:0px;
}
.ace_text-input {
font-size:16px;
background-color:transparent;
}
/* This temp element is used for auto adjusting filename field */ /* This temp element is used for auto adjusting filename field */
.tmp-element { .tmp-element {
visibility: hidden; visibility: hidden;
@ -56,6 +92,7 @@
#script-editor-wrapper { #script-editor-wrapper {
height:100%; height:100%;
width: 70%; width: 70%;
background:transparent;
} }
#script-editor-filename-wrapper { #script-editor-filename-wrapper {
@ -103,28 +140,6 @@
color: #ffffff; color: #ffffff;
} }
#script-editor-text {
color: var(--my-font-color);
height: 80%;
width: 100%;
margin-left: 6px;
padding-left: 6px;
padding-top: 6px;
padding-bottom: 6px;
border: 2px solid var(--my-highlight-color);
-webkit-box-shadow:
inset 0 0 8px rgba(0,0,0,0.1),
0 0 16px rgba(0,0,0,0.1);
-moz-box-shadow:
inset 0 0 8px rgba(0,0,0,0.1),
0 0 16px rgba(0,0,0,0.1);
box-shadow:
inset 0 0 8px rgba(0,0,0,0.1),
0 0 16px rgba(0,0,0,0.1);
}
/* Active scripts */ /* Active scripts */
.active-scripts-list { .active-scripts-list {
list-style-type: none; list-style-type: none;
@ -261,6 +276,7 @@
box-shadow: 1px 1px 3px #000; box-shadow: 1px 1px 3px #000;
margin: 4px; margin: 4px;
padding: 4px; padding: 4px;
background-color:black;
} }
.active-scripts-button:hover, .active-scripts-button:hover,
@ -569,6 +585,7 @@ div.faction-clear {
color: var(--my-font-color); color: var(--my-font-color);
padding: 4px; padding: 4px;
margin: 4px; margin: 4px;
background-color:black;
} }
.stock-market-buy-sell-button { .stock-market-buy-sell-button {

@ -7,6 +7,7 @@
top: 0; top: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow:auto;
background-color: rbga(var(--my-background-color), 0.4); background-color: rbga(var(--my-background-color), 0.4);
} }
@ -16,7 +17,6 @@
padding: 12px; padding: 12px;
border: 5px solid var(--my-highlight-color); border: 5px solid var(--my-highlight-color);
width: 70%; width: 70%;
overflow: auto; /* Enable scroll if needed */
color: var(--my-font-color); color: var(--my-font-color);
} }
@ -29,6 +29,7 @@
padding: 2px; padding: 2px;
margin: 6px; margin: 6px;
border: 1px solid white; border: 1px solid white;
background-color:black;
} }
.popup-box-button:hover, .popup-box-button:hover,
@ -43,6 +44,12 @@
cursor: default; cursor: default;
} }
#yes-no-text-input-box-input {
color: var(--my-font-color);
border: 1px solid white;
background-color:black;
}
.dialog-box-container, .dialog-box-container,
#log-box-container { #log-box-container {
display: block; display: block;
@ -94,20 +101,6 @@
cursor: pointer; cursor: pointer;
} }
/* Purchase server box */
#purchase-server-box-container {
transition: opacity 400ms ease-in;
}
#purchase-server-box-input {
color: white;
}
/* Purchase Augmentation Box */
#purchase-augmentation-box-container {
transition: opacity 400ms ease-in;
}
/* Faction invitation box */ /* Faction invitation box */
#faction-invitation-box-container { #faction-invitation-box-container {
transition: opacity 400ms ease-in; transition: opacity 400ms ease-in;

@ -1,20 +1,20 @@
/** This removes all padding and margins as well as /** This removes all padding and margins as well as
setting a default font size and family for the page **/ setting a default font size and family for the page **/
:root{ :root{
--my-font-color: #66ff33; --my-font-color: #66ff33;
--my-background-color: #000000; --my-background-color: #000000;
--my-highlight-color: #ffffff; --my-highlight-color: #ffffff;
} }
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;
font-size: 16px; font-size: 16px;
font-family: 'Lucida Console', 'Lucida Sans Unicode', 'Fira Mono', 'Consolas', 'Courier New', Courier, monospace, 'Times New Roman'; font-family: 'Lucida Console', 'Lucida Sans Unicode', 'Fira Mono', 'Consolas', 'Courier New', Courier, monospace, 'Times New Roman';
/*background-color: #252527;*/ }
body {
background-color: var(--my-background-color); background-color: var(--my-background-color);
} }
@ -41,6 +41,10 @@ span {
padding: 4px; padding: 4px;
} }
#entire-game-container {
background-color:transparent;
}
/* Disable border highlight on elements */ /* Disable border highlight on elements */
input:focus, input:focus,
textarea:focus, textarea:focus,
@ -346,6 +350,7 @@ a:link, a:visited {
-webkit-box-shadow: 1px 1px 3px #000; -webkit-box-shadow: 1px 1px 3px #000;
box-shadow: 1px 1px 3px #000; box-shadow: 1px 1px 3px #000;
height: 22px; height: 22px;
background-color:black;
} }
#character-overview-save-button:hover, #character-overview-save-button:hover,

64355
dist/bundle.js vendored Normal file

File diff suppressed because one or more lines are too long

@ -89,6 +89,24 @@
</ul> </ul>
</div> </div>
<div id="script-editor-container" class="generic-menupage-container">
<div id="script-editor-wrapper">
<div id="script-editor-filename-wrapper">
<p id="script-editor-filename-tag"> <strong style="background-color:#555;">Script name: </strong></p>
<input id="script-editor-filename" type="text" maxlength="30" tabindex="1"> </input>
</div>
<div id="javascript-editor"></div>
<div id="script-editor-buttons-wrapper">
<span id="script-editor-save-and-close-button" class="a-link-button">Save & Close (Ctrl + b)</span>
<p id="script-editor-status-text"> </p>
<a id="script-editor-netscript-doc-button" class="a-link-button" href="https://bitburner.wikia.com/wiki/Netscript" target="_blank"> Netscript Documentation </a>
</div>
</div> <!-- End wrapper -->
</div>
<!-- Terminal page --> <!-- Terminal page -->
<div id="terminal-container"> <div id="terminal-container">
<table id="terminal"> <table id="terminal">
@ -108,23 +126,6 @@
</div> </div>
</div> </div>
<!-- Script editor -->
<div id="script-editor-container" class="generic-menupage-container">
<div id="script-editor-wrapper">
<div id="script-editor-filename-wrapper">
<p id="script-editor-filename-tag"> <strong style="background-color:#555;">Script name: </strong></p>
<input id="script-editor-filename" type="text" maxlength="30" tabindex="1"> </input>
</div>
<textarea id="script-editor-text" tabindex="2" autofocus> </textarea>
<div id="script-editor-buttons-wrapper">
<span id="script-editor-save-and-close-button" class="a-link-button">Save & Close (Ctrl + b)</span>
<p id="script-editor-status-text"> </p>
<a id="script-editor-netscript-doc-button" class="a-link-button" href="https://bitburner.wikia.com/wiki/Netscript" target="_blank"> Netscript Documentation </a>
</div>
</div>
<p> <br><br> </p>
</div>
<!-- Active scripts info page --> <!-- Active scripts info page -->
<div id="active-scripts-container" class="generic-menupage-container"> <div id="active-scripts-container" class="generic-menupage-container">
<p id="active-scripts-text"> This page displays a list of all of your scripts that are currently running across every machine. It also <p id="active-scripts-text"> This page displays a list of all of your scripts that are currently running across every machine. It also
@ -839,8 +840,6 @@
</label> </label>
<input type ="range" max="200" min="25" <input type ="range" max="200" min="25"
oninput="document.getElementById('settingsNSExecTimeRangeValLabel').innerHTML = this.value + 'ms';
Settings.CodeInstructionRunTime=this.value;"
step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="100"> step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="100">
</input> </input>
<em id="settingsNSExecTimeRangeValLabel" style="font-style: normal;"></em> <em id="settingsNSExecTimeRangeValLabel" style="font-style: normal;"></em>
@ -857,8 +856,6 @@
</label> </label>
<input type="range" max="100" min="20" <input type="range" max="100" min="20"
oninput="document.getElementById('settingsNSLogRangeValLabel').innerHTML = this.value;
Settings.MaxLogCapacity=this.value;"
step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50"> step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50">
</input> </input>
<em id="settingsNSLogRangeValLabel" style="font-style: normal;"></em> <em id="settingsNSLogRangeValLabel" style="font-style: normal;"></em>
@ -875,8 +872,6 @@
</label> </label>
<input type="range" max="100" min="20" <input type="range" max="100" min="20"
oninput="document.getElementById('settingsNSPortRangeValLabel').innerHTML = this.value;
Settings.MaxPortCapacity=this.value;"
step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50"> step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50">
</input> </input>
<em id="settingsNSPortRangeValLabel" style="font-style: normal;"></em> <em id="settingsNSPortRangeValLabel" style="font-style: normal;"></em>
@ -891,8 +886,7 @@
and can be viewed with the 'cat' Terminal command. and can be viewed with the 'cat' Terminal command.
</span> </span>
</label> </label>
<input type="checkbox" name="settingsSuppressMessages" id="settingsSuppressMessages" <input type="checkbox" name="settingsSuppressMessages" id="settingsSuppressMessages">
onclick="Settings.SuppressMessages = this.checked;">
</fieldset> </fieldset>
<!-- Suppress faction invites --> <!-- Suppress faction invites -->
@ -903,8 +897,7 @@
on the screen. Your outstanding faction invites can be viewed in the 'Factions' page. on the screen. Your outstanding faction invites can be viewed in the 'Factions' page.
</span> </span>
</label> </label>
<input type="checkbox" name="settingsSuppressFactionInvites" id="settingsSuppressFactionInvites" <input type="checkbox" name="settingsSuppressFactionInvites" id="settingsSuppressFactionInvites">
onclick="Settings.SuppressFactionInvites = this.checked;">
</fieldset> </fieldset>
<!-- Donate button --> <!-- Donate button -->
@ -924,7 +917,7 @@
<a id="delete-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Delete Game </a> <a id="delete-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Delete Game </a>
<a id="export-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Export Game </a> <a id="export-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Export Game </a>
<input type="file" id="import-game-file-selector" name="file"/> <input type="file" id="import-game-file-selector" name="file"/>
<a id="import-game-link" class="a-link-button" style="display:inline-block;width:46%;" onclick="saveObject.importGame();"> Import Game </a> <a id="import-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Import Game </a>
<a id="debug-delete-scripts-link" class="a-link-button tooltip" style="display:block;width:46%;"> <a id="debug-delete-scripts-link" class="a-link-button tooltip" style="display:block;width:46%;">
(DEBUG) Delete Active Scripts (DEBUG) Delete Active Scripts
<span class="tooltiptext"> <span class="tooltiptext">
@ -949,64 +942,5 @@
<div class="loaderlabel">Loading Bitburner...</div> <div class="loaderlabel">Loading Bitburner...</div>
</div> </div>
</body> </body>
<!--jQuery library--> <script src="dist/bundle.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<!-- Utils -->
<script src="utils/IPAddress.js"></script>
<script src="utils/JSONReviver.js"></script>
<script src="utils/StringHelperFunctions.js"></script>
<script src="utils/HelperFunctions.js"></script>
<script src="utils/DialogBox.js"></script>
<script src="utils/FactionInvitationBox.js"></script>
<script src="utils/GameOptions.js"></script>
<script src="utils/LogBox.js"></script>
<script src="utils/InfiltrationBox.js"></script>
<script src="utils/decimal.js"></script>
<script src="utils/YesNoBox.js"></script>
<script src="utils/numeral.min.js"></script>
<!-- Netscript -->
<script src="src/NetscriptWorker.js"></script>
<script src="src/NetscriptEvaluator.js"></script>
<script src="src/NetscriptEnvironment.js"></script>
<script src="src/NetscriptFunctions.js"></script>
<script src="utils/acorn.js"></script>
<!-- Main game files -->
<script src="src/Constants.js"></script>
<script src="src/HelpText.js"></script>
<script src="src/SpecialServerIps.js"></script>
<script src="src/Location.js"></script>
<script src="src/Script.js"></script>
<script src="src/Server.js"></script>
<script src="src/Player.js"></script>
<script src="src/Faction.js"></script>
<script src="src/FactionInfo.js"></script>
<script src="src/Company.js"></script>
<script src="src/CompanyJobApplication.js"></script>
<script src="src/Terminal.js"></script>
<script src="src/ServerPurchases.js"></script>
<script src="src/CreateProgram.js"></script>
<script src="src/Augmentations.js"></script>
<script src="src/Perk.js"></script>
<script src="src/HacknetNode.js"></script>
<script src="src/Crimes.js"></script>
<script src="src/Prestige.js"></script>
<script src="src/SaveObject.js"></script>
<script src="src/DarkWeb.js"></script>
<script src="src/InteractiveTutorial.js"></script>
<script src="src/Alias.js"></script>
<script src="src/Message.js"></script>
<script src="src/ActiveScriptsUI.js"></script>
<script src="src/Infiltration.js"></script>
<script src="src/StockMarket.js"></script>
<script src="src/RedPill.js"></script>
<script src="src/BitNode.js"></script>
<script src="src/Settings.js"></script>
<script src="src/SourceFile.js"></script>
<script src="src/Gang.js"></script>
<script src="src/Literature.js"></script>
<script src="src/engine.js"></script>
</html> </html>

@ -1,5 +1,14 @@
/* Active Scripts UI*/ import {workerScripts,
addWorkerScript,
killWorkerScript} from "./NetscriptWorker.js";
import {getServer} from "./Server.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {printArray} from "../utils/HelperFunctions.js";
import {logBoxCreate} from "../utils/LogBox.js";
import {formatNumber} from "../utils/StringHelperFunctions.js";
/* Active Scripts UI*/
function setActiveScriptsClickHandlers() { function setActiveScriptsClickHandlers() {
//Server panel click handlers //Server panel click handlers
var serverPanels = document.getElementsByClassName("active-scripts-server-header"); var serverPanels = document.getElementsByClassName("active-scripts-server-header");
@ -10,7 +19,7 @@ function setActiveScriptsClickHandlers() {
for (i = 0; i < serverPanels.length; ++i) { for (i = 0; i < serverPanels.length; ++i) {
serverPanels[i].onclick = function() { serverPanels[i].onclick = function() {
this.classList.toggle("active"); this.classList.toggle("active");
var panel = this.nextElementSibling; var panel = this.nextElementSibling;
if (panel.style.display === "block") { if (panel.style.display === "block") {
panel.style.display = "none"; panel.style.display = "none";
@ -19,7 +28,7 @@ function setActiveScriptsClickHandlers() {
} }
} }
} }
//Script Panel click handlers //Script Panel click handlers
var scriptPanels = document.getElementsByClassName("active-scripts-script-header"); var scriptPanels = document.getElementsByClassName("active-scripts-script-header");
if (scriptPanels == null) { if (scriptPanels == null) {
@ -29,13 +38,13 @@ function setActiveScriptsClickHandlers() {
for (var i = 0; i < scriptPanels.length; ++i) { for (var i = 0; i < scriptPanels.length; ++i) {
scriptPanels[i].onclick = function() { scriptPanels[i].onclick = function() {
this.classList.toggle("active"); this.classList.toggle("active");
var panel = this.nextElementSibling; var panel = this.nextElementSibling;
if (panel.style.display === "block") { if (panel.style.display === "block") {
panel.style.display = "none"; panel.style.display = "none";
} else { } else {
panel.style.display = "block"; panel.style.display = "block";
} }
} }
} }
} }
@ -54,35 +63,34 @@ function getActiveScriptsServerList(server) {
function createActiveScriptsServerPanel(server) { function createActiveScriptsServerPanel(server) {
var panelname = "active-scripts-server-panel-" + server.hostname; var panelname = "active-scripts-server-panel-" + server.hostname;
var activeScriptsList = document.getElementById("active-scripts-list"); var activeScriptsList = document.getElementById("active-scripts-list");
//Div of entire Panel //Div of entire Panel
var panelDiv = document.createElement("div"); var panelDiv = document.createElement("div");
panelDiv.setAttribute("id", panelname); panelDiv.setAttribute("id", panelname);
//Panel Header //Panel Header
var panelHdr = document.createElement("button"); var panelHdr = document.createElement("button");
panelHdr.setAttribute("class", "active-scripts-server-header") panelHdr.setAttribute("class", "active-scripts-server-header")
panelHdr.setAttribute("id", panelname + "-hdr"); panelHdr.setAttribute("id", panelname + "-hdr");
panelHdr.innerHTML = server.hostname; panelHdr.innerHTML = server.hostname;
//Panel content //Panel content
var panelContentDiv = document.createElement("div"); var panelContentDiv = document.createElement("div");
panelContentDiv.setAttribute("class", "active-scripts-server-panel"); panelContentDiv.setAttribute("class", "active-scripts-server-panel");
panelContentDiv.setAttribute("id", panelname + "-content"); panelContentDiv.setAttribute("id", panelname + "-content");
//List of scripts //List of scripts
var panelScriptList = document.createElement("ul"); var panelScriptList = document.createElement("ul");
panelScriptList.setAttribute("id", panelname + "-script-list"); panelScriptList.setAttribute("id", panelname + "-script-list");
panelContentDiv.appendChild(panelScriptList); panelContentDiv.appendChild(panelScriptList);
panelDiv.appendChild(panelHdr); panelDiv.appendChild(panelHdr);
panelDiv.appendChild(panelContentDiv); panelDiv.appendChild(panelContentDiv);
activeScriptsList.appendChild(panelDiv); activeScriptsList.appendChild(panelDiv);
setActiveScriptsClickHandlers() //Reset click handlers setActiveScriptsClickHandlers() //Reset click handlers
return panelDiv; return panelDiv;
//TODO Alphabetize Active Scripts list?
} }
//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)
@ -94,7 +102,7 @@ function deleteActiveScriptsServerPanel(server) {
console.log("No such panel exists: " + panelname); console.log("No such panel exists: " + panelname);
return; return;
} }
//Remove the panel if it has no elements //Remove the panel if it has no elements
var scriptList = document.getElementById(panelname + "-script-list"); var scriptList = document.getElementById(panelname + "-script-list");
if (scriptList.childNodes.length == 0) { if (scriptList.childNodes.length == 0) {
@ -110,12 +118,12 @@ function addActiveScriptsItem(workerscript) {
return; return;
} }
var panelname = "active-scripts-server-panel-" + server.hostname; var panelname = "active-scripts-server-panel-" + server.hostname;
var panel = document.getElementById(panelname); var panel = document.getElementById(panelname);
if (panel == null) { if (panel == null) {
panel = createActiveScriptsServerPanel(server); panel = createActiveScriptsServerPanel(server);
} }
//Create the element itself. Each element is an accordion collapsible //Create the element itself. Each element is an accordion collapsible
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) {
@ -125,24 +133,24 @@ function addActiveScriptsItem(workerscript) {
//var itemName = "active-scripts-" + server.hostname + "-" + workerscript.name; //var itemName = "active-scripts-" + server.hostname + "-" + workerscript.name;
var item = document.createElement("li"); var item = document.createElement("li");
item.setAttribute("id", itemName); item.setAttribute("id", itemName);
var btn = document.createElement("button"); var btn = document.createElement("button");
btn.setAttribute("class", "active-scripts-script-header"); btn.setAttribute("class", "active-scripts-script-header");
btn.innerHTML = workerscript.name; btn.innerHTML = workerscript.name;
var itemContentDiv = document.createElement("div"); var itemContentDiv = document.createElement("div");
itemContentDiv.setAttribute("class", "active-scripts-script-panel"); itemContentDiv.setAttribute("class", "active-scripts-script-panel");
itemContentDiv.setAttribute("id", itemName + "-content"); itemContentDiv.setAttribute("id", itemName + "-content");
item.appendChild(btn); item.appendChild(btn);
item.appendChild(itemContentDiv); item.appendChild(itemContentDiv);
createActiveScriptsText(workerscript, itemContentDiv); createActiveScriptsText(workerscript, itemContentDiv);
//Append element to list //Append element to list
var list = getActiveScriptsServerList(server); var list = getActiveScriptsServerList(server);
list.appendChild(item); list.appendChild(item);
setActiveScriptsClickHandlers() //Reset click handlers setActiveScriptsClickHandlers() //Reset click handlers
} }
@ -191,47 +199,47 @@ function updateActiveScriptsItemContent(workerscript) {
var itemName = itemNameArray.join("-"); var itemName = itemNameArray.join("-");
//var itemName = "active-scripts-" + server.hostname + "-" + workerscript.name; //var itemName = "active-scripts-" + server.hostname + "-" + workerscript.name;
var itemContent = document.getElementById(itemName + "-content") var itemContent = document.getElementById(itemName + "-content")
//Clear the item //Clear the item
while (itemContent.firstChild) { while (itemContent.firstChild) {
itemContent.removeChild(itemContent.firstChild); itemContent.removeChild(itemContent.firstChild);
} }
//Add the updated text back. Returns the total online production rate //Add the updated text back. Returns the total online production rate
return createActiveScriptsText(workerscript, itemContent); return createActiveScriptsText(workerscript, itemContent);
} }
function createActiveScriptsText(workerscript, item) { function createActiveScriptsText(workerscript, item) {
var itemText = document.createElement("p"); var itemText = document.createElement("p");
//Server ip/hostname //Server ip/hostname
var threads = "Threads: " + workerscript.scriptRef.threads; var threads = "Threads: " + workerscript.scriptRef.threads;
var args = "Args: " + printArray(workerscript.args); var args = "Args: " + printArray(workerscript.args);
//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 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;");
//Offline //Offline
var offlineTotalMoneyMade = "Total offline production: $" + formatNumber(workerscript.scriptRef.offlineMoneyMade, 2); var offlineTotalMoneyMade = "Total offline production: $" + formatNumber(workerscript.scriptRef.offlineMoneyMade, 2);
var offlineTotalExpEarned = (Array(27).join(" ") + formatNumber(workerscript.scriptRef.offlineExpGained, 2) + " hacking exp").replace( / /g, "&nbsp;"); var offlineTotalExpEarned = (Array(27).join(" ") + formatNumber(workerscript.scriptRef.offlineExpGained, 2) + " hacking exp").replace( / /g, "&nbsp;");
var offlineMps = workerscript.scriptRef.offlineMoneyMade / workerscript.scriptRef.offlineRunningTime; var offlineMps = workerscript.scriptRef.offlineMoneyMade / workerscript.scriptRef.offlineRunningTime;
var offlineMpsText = "Offline production rate: $" + formatNumber(offlineMps, 2) + "/second"; var offlineMpsText = "Offline production rate: $" + formatNumber(offlineMps, 2) + "/second";
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;");
itemText.innerHTML = threads + "<br>" + args + "<br>" + onlineTotalMoneyMade + "<br>" + onlineTotalExpEarned + "<br>" + itemText.innerHTML = threads + "<br>" + args + "<br>" + 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>";
item.appendChild(itemText); item.appendChild(itemText);
var logButton = document.createElement("span"); var logButton = document.createElement("span");
logButton.innerHTML = "Log"; logButton.innerHTML = "Log";
var killButton = document.createElement("span"); var killButton = document.createElement("span");
@ -249,7 +257,9 @@ function createActiveScriptsText(workerscript, item) {
}); });
item.appendChild(logButton); item.appendChild(logButton);
item.appendChild(killButton); item.appendChild(killButton);
//Return total online production rate //Return total online production rate
return onlineMps; return onlineMps;
} }
export {setActiveScriptsClickHandlers, addActiveScriptsItem, deleteActiveScriptsItem, updateActiveScriptsItems};

@ -1,6 +1,23 @@
/* Alias.js */ import {post} from "./Terminal.js";
Aliases = {};
GlobalAliases = {}; let Aliases = {};
let GlobalAliases = {};
function loadAliases(saveString) {
if (saveString === "") {
Aliases = {};
} else {
Aliases = JSON.parse(saveString);
}
}
function loadGlobalAliases(saveString) {
if (saveString === "") {
GlobalAliases = {};
} else {
GlobalAliases = JSON.parse(saveString);
}
}
//Print all aliases to terminal //Print all aliases to terminal
function printAliases() { function printAliases() {
@ -91,4 +108,7 @@ function substituteAliases(origCommand) {
} }
} }
return commandArray.join(" "); return commandArray.join(" ");
} }
export {Aliases, GlobalAliases, printAliases, parseAliasDeclaration,
removeAlias, substituteAliases, loadAliases, loadGlobalAliases};

@ -1,3 +1,12 @@
import {BitNodeMultipliers} from "./BitNode.js";
import {CONSTANTS} from "./Constants.js";
import {Player} from "./Player.js";
import {prestigeAugmentation} from "./Prestige.js";
import {Factions, getNextNeurofluxLevel} from "./Faction.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js";
//Augmentations //Augmentations
function Augmentation(name) { function Augmentation(name) {
this.name = name; this.name = name;
@ -18,8 +27,8 @@ Augmentation.prototype.setInfo = function(inf) {
} }
Augmentation.prototype.setRequirements = function(rep, cost) { Augmentation.prototype.setRequirements = function(rep, cost) {
this.baseRepRequirement = rep * CONSTANTS.AugmentationRepMultiplier; this.baseRepRequirement = rep * CONSTANTS.AugmentationRepMultiplier * BitNodeMultipliers.AugmentationRepCost;
this.baseCost = cost * CONSTANTS.AugmentationCostMultiplier; this.baseCost = cost * CONSTANTS.AugmentationCostMultiplier * BitNodeMultipliers.AugmentationMoneyCost;
} }
//Takes in an array of faction names and adds this augmentation to all of those factions //Takes in an array of faction names and adds this augmentation to all of those factions
@ -57,14 +66,14 @@ Augmentation.fromJSON = function(value) {
Reviver.constructors.Augmentation = Augmentation; Reviver.constructors.Augmentation = Augmentation;
Augmentations = {} let Augmentations = {}
AddToAugmentations = function(aug) { function AddToAugmentations(aug) {
var name = aug.name; var name = aug.name;
Augmentations[name] = aug; Augmentations[name] = aug;
} }
AugmentationNames = { let AugmentationNames = {
Targeting1: "Augmented Targeting I", Targeting1: "Augmented Targeting I",
Targeting2: "Augmented Targeting II", Targeting2: "Augmented Targeting II",
Targeting3: "Augmented Targeting III", Targeting3: "Augmented Targeting III",
@ -153,7 +162,7 @@ AugmentationNames = {
SNA: "Social Negotiation Assistant (S.N.A)" SNA: "Social Negotiation Assistant (S.N.A)"
} }
initAugmentations = function() { function initAugmentations() {
for (var name in Factions) { for (var name in Factions) {
if (Factions.hasOwnProperty(name)) { if (Factions.hasOwnProperty(name)) {
Factions[name].augmentations = []; Factions[name].augmentations = [];
@ -377,7 +386,7 @@ initAugmentations = function() {
} }
AddToAugmentations(SpeechProcessor); AddToAugmentations(SpeechProcessor);
TITN41Injection = new Augmentation(AugmentationNames.TITN41Injection); let TITN41Injection = new Augmentation(AugmentationNames.TITN41Injection);
TITN41Injection.setRequirements(10000, 38000000); TITN41Injection.setRequirements(10000, 38000000);
TITN41Injection.setInfo("TITN is a series of viruses that targets and alters the sequences of human DNA in genes that " + TITN41Injection.setInfo("TITN is a series of viruses that targets and alters the sequences of human DNA in genes that " +
"control personality. The TITN-41 strain alters these genes so that the subject becomes more " + "control personality. The TITN-41 strain alters these genes so that the subject becomes more " +
@ -1403,7 +1412,7 @@ initAugmentations = function() {
} }
} }
applyAugmentation = function(aug, reapply=false) { function applyAugmentation(aug, reapply=false) {
Augmentations[aug.name].owned = true; Augmentations[aug.name].owned = true;
switch(aug.name) { switch(aug.name) {
//Combat stat augmentations //Combat stat augmentations
@ -1904,7 +1913,7 @@ function PlayerOwnedAugmentation(name) {
function installAugmentations() { function installAugmentations() {
if (Player.queuedAugmentations.length == 0) { if (Player.queuedAugmentations.length == 0) {
dialogBoxCreate("You have not purchased any Augmentations to install!"); dialogBoxCreate("You have not purchased any Augmentations to install!");
return; return false;
} }
var augmentationList = ""; var augmentationList = "";
for (var i = 0; i < Player.queuedAugmentations.length; ++i) { for (var i = 0; i < Player.queuedAugmentations.length; ++i) {
@ -1923,39 +1932,6 @@ function installAugmentations() {
prestigeAugmentation(); prestigeAugmentation();
} }
PlayerObject.prototype.reapplyAllAugmentations = function(resetMultipliers=true) {
console.log("Re-applying augmentations");
if (resetMultipliers) {
this.resetMultipliers();
}
for (i = 0; i < this.augmentations.length; ++i) {
//Compatibility with new version
if (typeof this.augmentations[i] === 'string' || this.augmentations[i] instanceof String) {
var newOwnedAug = new PlayerOwnedAugmentation(this.augmentations[i]);
if (this.augmentations[i] == AugmentationNames.NeuroFluxGovernor) {
newOwnedAug.level = Augmentations[AugmentationNames.NeuroFluxGovernor].level;
}
this.augmentations[i] = newOwnedAug;
}
var augName = this.augmentations[i].name;
var aug = Augmentations[augName];
aug.owned = true;
if (aug == null) {
console.log("WARNING: Invalid augmentation name");
continue;
}
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
for (j = 0; j < aug.level; ++j) {
applyAugmentation(this.augmentations[i], true);
}
continue;
}
applyAugmentation(this.augmentations[i], true);
}
}
function augmentationExists(name) { function augmentationExists(name) {
return Augmentations.hasOwnProperty(name); return Augmentations.hasOwnProperty(name);
} }
@ -1970,3 +1946,6 @@ function giveAllAugmentations() {
} }
Player.reapplyAllAugmentations(); Player.reapplyAllAugmentations();
} }
export {AugmentationNames, Augmentations, PlayerOwnedAugmentation, installAugmentations,
initAugmentations, applyAugmentation, augmentationExists, Augmentation};

@ -1,7 +1,16 @@
/* BitNode.js */ import {Player} from "./Player.js";
BitNodes = { function BitNode(n, name, desc="", info="") {
BitNode1: new BitNode(1, "Source Genesis", "The original BitNode", this.number = n;
this.name = name;
this.desc = desc;
this.info = info;
}
let BitNodes = {};
function initBitNodes() {
BitNodes = {};
BitNodes["BitNode1"] = new BitNode(1, "Source Genesis", "The original BitNode",
"The first BitNode created by the Enders to imprison the minds of humans. It became " + "The first BitNode created by the Enders to imprison the minds of humans. It became " +
"the prototype and testing-grounds for all of the BitNodes that followed.<br><br>" + "the prototype and testing-grounds for all of the BitNodes that followed.<br><br>" +
"This is the first BitNode that you play through. It has no special " + "This is the first BitNode that you play through. It has no special " +
@ -12,8 +21,8 @@ BitNodes = {
"new BitNode, and also increases all of the player's multipliers by:<br><br>" + "new BitNode, and also increases all of the player's multipliers by:<br><br>" +
"Level 1: 16%<br>" + "Level 1: 16%<br>" +
"Level 2: 24%<br>" + "Level 2: 24%<br>" +
"Level 3: 28%"), "Level 3: 28%");
BitNode2: new BitNode(2, "Rise of the Underworld", "From the shadows, they rose", //Gangs BitNodes["BitNode2"] = new BitNode(2, "Rise of the Underworld", "From the shadows, they rose", //Gangs
"From the shadows, they rose.<br><br>Organized crime groups quickly filled the void of power " + "From the shadows, they rose.<br><br>Organized crime groups quickly filled the void of power " +
"left behind from the collapse of Western government in the 2050's. As society and civlization broke down, " + "left behind from the collapse of Western government in the 2050's. As society and civlization broke down, " +
"people quickly succumbed to the innate human impulse of evil and savagery. The organized crime " + "people quickly succumbed to the innate human impulse of evil and savagery. The organized crime " +
@ -31,52 +40,71 @@ BitNodes = {
"crime money, and charisma multipliers by:<br><br>" + "crime money, and charisma multipliers by:<br><br>" +
"Level 1: 20%<br>" + "Level 1: 20%<br>" +
"Level 2: 30%<br>" + "Level 2: 30%<br>" +
"Level 3: 35%"), "Level 3: 35%");
BitNode3: new BitNode(3, "The Price of Civilization", "COMING SOON"), //Corporate Warfare, Run own company BitNodes["BitNode3"] = new BitNode(3, "The Price of Civilization", "COMING SOON"); //Corporate Warfare, Run own company
BitNode4: new BitNode(4, "The Singularity", "COMING SOON"), //Everything automatable BitNodes["BitNode4"] = new BitNode(4, "The Singularity", "The Man and the Machine", "The Singularity has arrived. The human race is gone, replaced " +
BitNode5: new BitNode(5, "2084", "COMING SOON"), //Big Brother "by artificially superintelligent beings that are more machine than man. <br><br>" +
BitNode6: new BitNode(6, "Hacktocracy", "COMING SOON"), //Healthy Hacknet balancing mechanic "In this BitNode, progressing is significantly harder. Experience gain rates " +
BitNode7: new BitNode(7, "Do Androids Dream?", "COMING SOON"), //Build androids for automation "for all stats are reduced. Most methods of earning money will now give significantly less.<br><br>" +
BitNode8: new BitNode(8, "Ghost of Wall Street", "COMING SOON"), //Trading only viable strategy "In this BitNode you will gain access to a new set of Netscript Functions known as Singularity Functions. " +
BitNode9: new BitNode(9, "MegaCorp", "COMING SOON"), //Single corp/server with increasing difficulty "These functions allow you to control most aspects of the game through scripts, including working for factions/companies, " +
BitNode10: new BitNode(10, "Wasteland", "COMING SOON"), //Postapocalyptic "purchasing/installing Augmentations, and creating programs.<br><br>" +
BitNode11: new BitNode(11, "The Big Crash", "COMING SOON"), //Crashing economy "Destroying this BitNode will give you Source-File 4, or if you already have this Source-File it will " +
/* Okay. Sell it all. "upgrade its level up to a maximum of 3. This Source-File lets you access and use the Singularity " +
"The 2050s was defined by the massive amounts of violent civil unrest and anarchic rebellion that rose all around the world. It was this period " + "Functions in other BitNodes. Each level of this Source-File will open up more Singularity Functions " +
"of disorder that eventually lead to the governmental reformation of many global superpowers, most notably " + "that you can use.");
"the USA and China. But just as the world was slowly beginning to recover from these dark times, financial catastrophe hit.<br><br>" + BitNodes["BitNode5"] = new BitNode(5, "Artificial Intelligence", "COMING SOON"); //Int
"In many countries, the high cost of trying to deal with the civil disorder bankrupted the governments. In all of this chaos and confusion hackers " + BitNodes["BitNode6"] = new BitNode(6, "Hacktocracy", "COMING SOON"); //Healthy Hacknet balancing mechanic
"were able to steal billions of dollars from the world's largest electronic banks, prompting an international banking crisis as " + BitNodes["BitNode7"] = new BitNode(7, "Do Androids Dream?", "COMING SOON"); //Build androids for automation
"governments were unable to bail out insolvent banks. Now, the world is slowly crumbling in the middle of the biggest economic crisis of all time.<br><br>" + BitNodes["BitNode8"] = new BitNode(8, "Ghost of Wall Street", "COMING SOON"); //Trading only viable strategy
"In this BitNode:<br><br>" + BitNodes["BitNode9"] = new BitNode(9, "MegaCorp", "COMING SOON"); //Single corp/server with increasing difficulty
"The starting and maximum amount of money available on servers is significantly decreased<br>" + BitNodes["BitNode10"] = new BitNode(10, "Wasteland", "COMING SOON"); //Postapocalyptic
"The growth rate of servers is halved<br>" + BitNodes["BitNode11"] = new BitNode(11, "The Big Crash", "Okay. Sell it all.", //Crashing economy
"Weakening a server is twice as effective<br>" + "The 2050s was defined by the massive amounts of violent civil unrest and anarchic rebellion that rose all around the world. It was this period " +
"Company wages are decreased by 25%<br>" + "of disorder that eventually lead to the governmental reformation of many global superpowers, most notably " +
"Hacknet Node production is significantly decreased<br>" + "the USA and China. But just as the world was slowly beginning to recover from these dark times, financial catastrophe hit.<br><br>" +
"Augmentations are twice as expensive<br><br>" + "In many countries, the high cost of trying to deal with the civil disorder bankrupted the governments. In all of this chaos and confusion, hackers " +
"Destroying this BitNode will give you Source-File 11, or if you already have this Source-File it will " + "were able to steal billions of dollars from the world's largest electronic banks, prompting an international banking crisis as " +
"upgrade its level up to a maximum of 3. This Source-File increases the player's company salary multiplier by:<br><br>" + "governments were unable to bail out insolvent banks. Now, the world is slowly crumbling in the middle of the biggest economic crisis of all time.<br><br>" +
"Level 1: 60%<br>" + "In this BitNode:<br><br>" +
"Level 2: 90%<br>" + "The starting and maximum amount of money available on servers is significantly decreased<br>" +
"Level 3: 105%"; "The growth rate of servers is halved<br>" +
"Weakening a server is twice as effective<br>" +
"Company wages are decreased by 50%<br>" +
"Hacknet Node production is significantly decreased<br>" +
"Augmentations are twice as expensive<br><br>" +
"Destroying this BitNode will give you Source-File 11, or if you already have this Source-File it will " +
"upgrade its level up to a maximum of 3. This Source-File increases the player's company salary and reputation gain multipliers by:<br><br>" +
"Level 1: 60%<br>" +
"Level 2: 90%<br>" +
"Level 3: 105%");
*/ BitNodes["BitNode12"] = new BitNode(12, "Eye of the World", "COMING SOON"); //Become AI
BitNode12: new BitNode(12, "Eye of the World", "COMING SOON"), //Become AI
} }
function BitNode(n, name, desc="", info="") { let BitNodeMultipliers = {
this.number = n;
this.name = name;
this.desc = desc;
this.info = info;
}
BitNodeMultipliers = {
ServerMaxMoney: 1, ServerMaxMoney: 1,
ServerStartingMoney: 1,
ServerGrowthRate: 1,
ServerWeakenRate: 1,
ManualHackMoney: 1,
ScriptHackMoney: 1,
CompanyWorkMoney: 1,
CrimeMoney: 1, CrimeMoney: 1,
HacknetNodeMoney: 1,
CompanyWorkExpGain: 1,
ClassGymExpGain: 1,
FactionWorkExpGain: 1,
HackExpGain: 1,
CrimeExpGain: 1,
FactionWorkRepGain: 1, FactionWorkRepGain: 1,
FactionPassiveRepGain: 1, FactionPassiveRepGain: 1,
AugmentationRepCost: 1,
AugmentationMoneyCost: 1,
} }
function initBitNodeMultipliers() { function initBitNodeMultipliers() {
@ -93,13 +121,37 @@ function initBitNodeMultipliers() {
case 1: case 1:
break; break;
case 2: //Rise of the Underworld case 2: //Rise of the Underworld
BitNodeMultipliers.ServerMaxMoney = 0.2; BitNodeMultipliers.ServerMaxMoney = 0.2;
BitNodeMultipliers.CrimeMoney = 2; BitNodeMultipliers.CrimeMoney = 2;
BitNodeMultipliers.FactionWorkRepGain = 0.5; BitNodeMultipliers.FactionWorkRepGain = 0.5;
BitNodeMultipliers.FactionPassiveRepGain = 0; BitNodeMultipliers.FactionPassiveRepGain = 0;
break;
case 4: //The Singularity
BitNodeMultipliers.ServerMaxMoney = 0.15;
BitNodeMultipliers.ScriptHackMoney = 0.2;
BitNodeMultipliers.CompanyWorkMoney = 0.1;
BitNodeMultipliers.CrimeMoney = 0.2;
BitNodeMultipliers.HacknetNodeMoney = 0.05;
BitNodeMultipliers.CompanyWorkExpGain = 0.5;
BitNodeMultipliers.ClassGymExpGain = 0.5;
BitNodeMultipliers.FactionWorkExpGain = 0.5;
BitNodeMultipliers.HackExpGain = 0.4;
BitNodeMultipliers.CrimeExpGain = 0.5;
BitNodeMultipliers.FactionWorkRepGain = 0.75;
break;
case 11: //The Big Crash
BitNodeMultipliers.ServerMaxMoney = 0.1;
BitNodeMultipliers.ServerStartingMoney = 0.25;
BitNodeMultipliers.ServerGrowthRate = 0.5;
BitNodeMultipliers.ServerWeakenRate = 2;
BitNodeMultipliers.CompanyWorkMoney = 0.5;
BitNodeMultipliers.HacknetNodeMoney = 0.1;
BitNodeMultipliers.AugmentationMoneyCost = 2;
break; break;
default: default:
console.log("WARNING: Player.bitNodeN invalid"); console.log("WARNING: Player.bitNodeN invalid");
break; break;
} }
} }
export {initBitNodes, BitNode, BitNodes, BitNodeMultipliers, initBitNodeMultipliers};

@ -1,3 +1,10 @@
import {CONSTANTS} from "./Constants.js";
import {Locations} from "./Location.js";
import {Player} from "./Player.js";
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js";
//Netburner Company class //Netburner Company class
// Note: Company Positions can be loaded every time with init() but Company class needs // Note: Company Positions can be loaded every time with init() but Company class needs
// to be saved/loaded from localStorage // to be saved/loaded from localStorage
@ -251,7 +258,7 @@ CompanyPosition.fromJSON = function(value) {
Reviver.constructors.CompanyPosition = CompanyPosition; Reviver.constructors.CompanyPosition = CompanyPosition;
CompanyPositions = { let CompanyPositions = {
//Constructor: CompanyPosition(name, reqHack, reqStr, reqDef, reqDex, reqAgi, reqCha, reqRep, salary) //Constructor: CompanyPosition(name, reqHack, reqStr, reqDef, reqDex, reqAgi, reqCha, reqRep, salary)
//Software //Software
@ -403,7 +410,7 @@ CompanyPositions = {
//Returns the next highest position in the company for the relevant career/field //Returns the next highest position in the company for the relevant career/field
//I.E returns what your next job would be if you qualify for a promotion //I.E returns what your next job would be if you qualify for a promotion
getNextCompanyPosition = function(currPos) { function getNextCompanyPosition(currPos) {
if (currPos == null) {return null;} if (currPos == null) {return null;}
//Software //Software
if (currPos.positionName == CompanyPositions.SoftwareIntern.positionName) { if (currPos.positionName == CompanyPositions.SoftwareIntern.positionName) {
@ -511,7 +518,7 @@ getNextCompanyPosition = function(currPos) {
/* Initialize all companies. Only called when creating new game/prestiging. Otherwise companies are /* Initialize all companies. Only called when creating new game/prestiging. Otherwise companies are
* usually loaded from localStorage */ * usually loaded from localStorage */
initCompanies = function() { function initCompanies() {
/* Companies that also have servers */ /* Companies that also have servers */
//Megacorporations //Megacorporations
var ECorp = new Company(Locations.AevumECorp, 3.0, 3.0, 249); var ECorp = new Company(Locations.AevumECorp, 3.0, 3.0, 249);
@ -1088,10 +1095,14 @@ initCompanies = function() {
} }
//Map of all companies that exist in the game, indexed by their name //Map of all companies that exist in the game, indexed by their name
Companies = {} let Companies = {}
function loadCompanies(saveString) {
Companies = JSON.parse(saveString, Reviver);
}
//Add a Company object onto the map of all Companies in the game //Add a Company object onto the map of all Companies in the game
AddToCompanies = function (company) { function AddToCompanies(company) {
var name = company.companyName; var name = company.companyName;
Companies[name] = company; Companies[name] = company;
} }
@ -1099,3 +1110,41 @@ AddToCompanies = function (company) {
function companyExists(name) { function companyExists(name) {
return Companies.hasOwnProperty(name); return Companies.hasOwnProperty(name);
} }
function getJobRequirementText(company, pos, tooltiptext=false) {
var reqText = "";
var offset = company.jobStatReqOffset;
var reqHacking = pos.requiredHacking > 0 ? pos.requiredHacking+offset : 0;
var reqStrength = pos.requiredStrength > 0 ? pos.requiredStrength+offset : 0;
var reqDefense = pos.requiredDefense > 0 ? pos.requiredDefense+offset : 0;
var reqDexterity = pos.requiredDexterity > 0 ? pos.requiredDexterity+offset : 0;
var reqAgility = pos.requiredDexterity > 0 ? pos.requiredDexterity+offset : 0;
var reqCharisma = pos.requiredCharisma > 0 ? pos.requiredCharisma+offset : 0;
var reqRep = pos.requiredReputation;
if (tooltiptext) {
reqText = "Requires:<br>";
reqText += (reqHacking.toString() + " hacking<br>");
reqText += (reqStrength.toString() + " strength<br>");
reqText += (reqDefense.toString() + " defense<br>");
reqText += (reqDexterity.toString() + " dexterity<br>");
reqText += (reqAgility.toString() + " agility<br>");
reqText += (reqCharisma.toString() + " charisma<br>");
reqText += (reqRep.toString() + " reputation");
} else {
reqText = "(Requires ";
if (reqHacking > 0) {reqText += (reqHacking + " hacking, ");}
if (reqStrength > 0) {reqText += (reqStrength + " strength, ");}
if (reqDefense > 0) {reqText += (reqDefense + " defense, ");}
if (reqDexterity > 0) {reqText += (reqDexterity + " dexterity, ");}
if (reqAgility > 0) {reqText += (reqAgility + " agility, ");}
if (reqCharisma > 0) {reqText += (reqCharisma + " charisma, ");}
if (reqRep > 1) {reqText += (reqRep + " reputation, ");}
reqText = reqText.substring(0, reqText.length - 2);
reqText += ")";
}
return reqText;
}
export {CompanyPositions, initCompanies, Companies, getJobRequirementText,
getNextCompanyPosition, loadCompanies, Company, CompanyPosition,
companyExists};

@ -1,273 +1 @@
/* Functions that handle applying for different jobs/positions in a Company */ //TODO probably just move this to whatever file needs it then delete this
//Determines the job that the Player should get (if any) at the current
//company
PlayerObject.prototype.applyForJob = function(entryPosType) {
var currCompany = "";
if (this.companyName != "") {
currCompany = Companies[this.companyName];
}
var currPositionName = "";
if (this.companyPosition != "") {
currPositionName = this.companyPosition.positionName;
}
var company = Companies[this.location]; //Company being applied to
var pos = entryPosType;
if (!this.isQualified(company, pos)) {
var reqText = getJobRequirementText(company, pos);
dialogBoxCreate("Unforunately, you do not qualify for this position<br>" + reqText);
return;
}
while (true) {
if (Engine.Debug) {console.log("Determining qualification for next Company Position");}
var newPos = getNextCompanyPosition(pos);
if (newPos == null) {break;}
//Check if this company has this position
if (company.hasPosition(newPos)) {
if (!this.isQualified(company, newPos)) {
//If player not qualified for next job, break loop so player will be given current job
break;
}
pos = newPos;
} else {
break;
}
}
//Check if the determined job is the same as the player's current job
if (currCompany != "") {
if (currCompany.companyName == company.companyName &&
pos.positionName == currPositionName) {
var nextPos = getNextCompanyPosition(pos);
if (nextPos == null) {
dialogBoxCreate("You are already at the highest position for your field! No promotion available");
} else if (company.hasPosition(nextPos)) {
var reqText = getJobRequirementText(company, nextPos);
dialogBoxCreate("Unfortunately, you do not qualify for a promotion<br>" + reqText);
} else {
dialogBoxCreate("You are already at the highest position for your field! No promotion available");
}
return; //Same job, do nothing
}
}
//Lose reputation from a Company if you are leaving it for another job
var leaveCompany = false;
var oldCompanyName = "";
if (currCompany != "") {
if (currCompany.companyName != company.companyName) {
leaveCompany = true;
oldCompanyName = currCompany.companyName;
company.playerReputation -= 1000;
if (company.playerReputation < 0) {company.playerReputation = 0;}
if (Engine.debug) {
console.log("Lost reputation for " + company.companyName + ". It is now " + company.playerReputation);
}
}
}
this.companyName = company.companyName;
this.companyPosition = pos;
if (leaveCompany) {
dialogBoxCreate("Congratulations! You were offered a new job at " + this.companyName + " as a " +
pos.positionName + "!<br>" +
"You lost 1000 reputation at your old company " + oldCompanyName + " because you left.");
} else {
dialogBoxCreate("Congratulations! You were offered a new job at " + this.companyName + " as a " + pos.positionName + "!");
}
Engine.loadLocationContent();
}
function getJobRequirementText(company, pos, tooltiptext=false) {
var reqText = "";
var offset = company.jobStatReqOffset;
var reqHacking = pos.requiredHacking > 0 ? pos.requiredHacking+offset : 0;
var reqStrength = pos.requiredStrength > 0 ? pos.requiredStrength+offset : 0;
var reqDefense = pos.requiredDefense > 0 ? pos.requiredDefense+offset : 0;
var reqDexterity = pos.requiredDexterity > 0 ? pos.requiredDexterity+offset : 0;
var reqAgility = pos.requiredDexterity > 0 ? pos.requiredDexterity+offset : 0;
var reqCharisma = pos.requiredCharisma > 0 ? pos.requiredCharisma+offset : 0;
var reqRep = pos.requiredReputation;
if (tooltiptext) {
reqText = "Requires:<br>";
reqText += (reqHacking.toString() + " hacking<br>");
reqText += (reqStrength.toString() + " strength<br>");
reqText += (reqDefense.toString() + " defense<br>");
reqText += (reqDexterity.toString() + " dexterity<br>");
reqText += (reqAgility.toString() + " agility<br>");
reqText += (reqCharisma.toString() + " charisma<br>");
reqText += (reqRep.toString() + " reputation");
} else {
reqText = "(Requires ";
if (reqHacking > 0) {reqText += (reqHacking + " hacking, ");}
if (reqStrength > 0) {reqText += (reqStrength + " strength, ");}
if (reqDefense > 0) {reqText += (reqDefense + " defense, ");}
if (reqDexterity > 0) {reqText += (reqDexterity + " dexterity, ");}
if (reqAgility > 0) {reqText += (reqAgility + " agility, ");}
if (reqCharisma > 0) {reqText += (reqCharisma + " charisma, ");}
if (reqRep > 1) {reqText += (reqRep + " reputation, ");}
reqText = reqText.substring(0, reqText.length - 2);
reqText += ")";
}
return reqText;
}
//Returns your next position at a company given the field (software, business, etc.)
PlayerObject.prototype.getNextCompanyPosition = function(company, entryPosType) {
var currCompany = null;
if (this.companyName != "") {
currCompany = Companies[this.companyName];
}
//Not employed at this company, so return the entry position
if (currCompany == null || (currCompany.companyName != company.companyName)) {
return entryPosType;
}
//If the entry pos type and the player's current position have the same type,
//return the player's "nextCompanyPosition". Otherwise return the entryposType
//Employed at this company, so just return the next position if it exists.
if ((this.companyPosition.isSoftwareJob() && entryPosType.isSoftwareJob()) ||
(this.companyPosition.isITJob() && entryPosType.isITJob()) ||
(this.companyPosition.isSecurityEngineerJob() && entryPosType.isSecurityEngineerJob()) ||
(this.companyPosition.isNetworkEngineerJob() && entryPosType.isNetworkEngineerJob()) ||
(this.companyPosition.isSecurityJob() && entryPosType.isSecurityJob()) ||
(this.companyPosition.isAgentJob() && entryPosTypeisAgentJob()) ||
(this.companyPosition.isSoftwareConsultantJob() && entryPosType.isSoftwareConsultantJob()) ||
(this.companyPosition.isBusinessConsultantJob() && entryPosType.isBusinessConsultantJob()) ||
(this.companyPosition.isPartTimeJob() && entryPosType.isPartTimeJob())) {
return getNextCompanyPosition(this.companyPosition);
}
return entryPosType;
}
PlayerObject.prototype.applyForSoftwareJob = function() {
this.applyForJob(CompanyPositions.SoftwareIntern);
}
PlayerObject.prototype.applyForSoftwareConsultantJob = function() {
this.applyForJob(CompanyPositions.SoftwareConsultant);
}
PlayerObject.prototype.applyForItJob = function() {
this.applyForJob(CompanyPositions.ITIntern);
}
PlayerObject.prototype.applyForSecurityEngineerJob = function() {
var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.SecurityEngineer)) {
this.applyForJob(CompanyPositions.SecurityEngineer);
} else {
dialogBoxCreate("Unforunately, you do not qualify for this position");
}
}
PlayerObject.prototype.applyForNetworkEngineerJob = function() {
var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.NetworkEngineer)) {
this.applyForJob(CompanyPositions.NetworkEngineer);
} else {
dialogBoxCreate("Unforunately, you do not qualify for this position");
}
}
PlayerObject.prototype.applyForBusinessJob = function() {
this.applyForJob(CompanyPositions.BusinessIntern);
}
PlayerObject.prototype.applyForBusinessConsultantJob = function() {
this.applyForJob(CompanyPositions.BusinessConsultant);
}
PlayerObject.prototype.applyForSecurityJob = function() {
//TODO If case for POlice departments
this.applyForJob(CompanyPositions.SecurityGuard);
}
PlayerObject.prototype.applyForAgentJob = function() {
var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.FieldAgent)) {
this.applyForJob(CompanyPositions.FieldAgent);
} else {
dialogBoxCreate("Unforunately, you do not qualify for this position");
}
}
PlayerObject.prototype.applyForEmployeeJob = function() {
var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.Employee)) {
this.companyName = company.companyName;
this.companyPosition = CompanyPositions.Employee;
dialogBoxCreate("Congratulations, you are now employed at " + this.companyName);
Engine.loadLocationContent();
} else {
dialogBoxCreate("Unforunately, you do not qualify for this position");
}
}
PlayerObject.prototype.applyForPartTimeEmployeeJob = function() {
var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.PartTimeEmployee)) {
this.companyName = company.companyName;
this.companyPosition = CompanyPositions.PartTimeEmployee;
dialogBoxCreate("Congratulations, you are now employed part-time at " + this.companyName);
Engine.loadLocationContent();
} else {
dialogBoxCreate("Unforunately, you do not qualify for this position");
}
}
PlayerObject.prototype.applyForWaiterJob = function() {
var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.Waiter)) {
this.companyName = company.companyName;
this.companyPosition = CompanyPositions.Waiter;
dialogBoxCreate("Congratulations, you are now employed as a waiter at " + this.companyName);
Engine.loadLocationContent();
} else {
dialogBoxCreate("Unforunately, you do not qualify for this position");
}
}
PlayerObject.prototype.applyForPartTimeWaiterJob = function() {
var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.PartTimeWaiter)) {
this.companyName = company.companyName;
this.companyPosition = CompanyPositions.PartTimeWaiter;
dialogBoxCreate("Congratulations, you are now employed as a part-time waiter at " + this.companyName);
Engine.loadLocationContent();
} else {
dialogBoxCreate("Unforunately, you do not qualify for this position");
}
}
//Checks if the Player is qualified for a certain position
PlayerObject.prototype.isQualified = function(company, position) {
var offset = company.jobStatReqOffset;
var reqHacking = position.requiredHacking > 0 ? position.requiredHacking+offset : 0;
var reqStrength = position.requiredStrength > 0 ? position.requiredStrength+offset : 0;
var reqDefense = position.requiredDefense > 0 ? position.requiredDefense+offset : 0;
var reqDexterity = position.requiredDexterity > 0 ? position.requiredDexterity+offset : 0;
var reqAgility = position.requiredDexterity > 0 ? position.requiredDexterity+offset : 0;
var reqCharisma = position.requiredCharisma > 0 ? position.requiredCharisma+offset : 0;
if (this.hacking_skill >= reqHacking &&
this.strength >= reqStrength &&
this.defense >= reqDefense &&
this.dexterity >= reqDexterity &&
this.agility >= reqAgility &&
this.charisma >= reqCharisma &&
company.playerReputation >= position.requiredReputation) {
return true;
}
return false;
}

@ -1,5 +1,5 @@
CONSTANTS = { let CONSTANTS = {
Version: "0.27.3", Version: "0.28.1",
//Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience //Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
//and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then //and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@ -75,8 +75,12 @@ CONSTANTS = {
ScriptRoundRamCost: 0.05, ScriptRoundRamCost: 0.05,
ScriptReadWriteRamCost: 1.0, ScriptReadWriteRamCost: 1.0,
ScriptArbScriptRamCost: 1.0, //Functions that apply to all scripts regardless of args ScriptArbScriptRamCost: 1.0, //Functions that apply to all scripts regardless of args
ScriptGetScriptCost: 0.1, ScriptGetScriptRamCost: 0.1,
ScriptGetHackTimeCost: 0.05, ScriptGetHackTimeRamCost: 0.05,
ScriptSingularityFn1RamCost: 1,
ScriptSingularityFn2RamCost: 2,
ScriptSingularityFn3RamCost: 3,
MultithreadingRAMCost: 1, MultithreadingRAMCost: 1,
@ -320,6 +324,9 @@ CONSTANTS = {
"numeric - Integers and floats (eg. 6, 10.4999)<br>" + "numeric - Integers and floats (eg. 6, 10.4999)<br>" +
"string - Encapsulated by single or double quotes (eg. 'this is a string')<br>" + "string - Encapsulated by single or double quotes (eg. 'this is a string')<br>" +
"boolean - true or false<br><br>" + "boolean - true or false<br><br>" +
"Strings are fully functional <a href='https://www.w3schools.com/jsref/jsref_obj_string.asp' target='_blank'>Javascript strings</a>, " +
"which means that all of the member functions of Javascript strings such as toLowerCase() and includes() are also " +
"available in Netscript!<br><br>" +
"To create a variable, use the assign (=) operator. The language is not strongly typed. Examples: <br>" + "To create a variable, use the assign (=) operator. The language is not strongly typed. Examples: <br>" +
"i = 5;<br>" + "i = 5;<br>" +
"s = 'this game is awesome!';<br><br>" + "s = 'this game is awesome!';<br><br>" +
@ -388,7 +395,8 @@ CONSTANTS = {
"any server, regardless of where the script is running. This command requires root access to the target server, but " + "any server, regardless of where the script is running. This command requires root access to the target server, but " +
"there is no required hacking level to run the command. Returns " + "there is no required hacking level to run the command. Returns " +
"0.1. Works offline at a slower rate<br> Example: weaken('foodnstuff');<br><br>" + "0.1. Works offline at a slower rate<br> Example: weaken('foodnstuff');<br><br>" +
"<i>print(x)</i> <br>Prints a value or a variable to the scripts logs (which can be viewed with the 'tail [script]' terminal command ). <br><br>" + "<i>print(x)</i><br>Prints a value or a variable to the scripts logs (which can be viewed with the 'tail [script]' terminal command ). <br><br>" +
"<i>tprint(x)</i><br>Prints a value or a variable to the Terminal<br><br>" +
"<i>clearLog()</i><br>Clears the script's logs. <br><br>" + "<i>clearLog()</i><br>Clears the script's logs. <br><br>" +
"<i>scan(hostname/ip)</i><br>Returns an array containing the hostnames of all servers that are one node away from the specified server. " + "<i>scan(hostname/ip)</i><br>Returns an array containing the hostnames of all servers that are one node away from the specified server. " +
"The argument must be a string containing the IP or hostname of the target server. The hostnames in the returned array are strings.<br><br>" + "The argument must be a string containing the IP or hostname of the target server. The hostnames in the returned array are strings.<br><br>" +
@ -618,6 +626,140 @@ CONSTANTS = {
"The code above will use the getServerMoneyAvailable() function to check how much money there is on the 'foodnstuff' server. " + "The code above will use the getServerMoneyAvailable() function to check how much money there is on the 'foodnstuff' server. " +
"If there is more than $200,000, then it will try to hack that server. If there is $200,000 or less on the server, " + "If there is more than $200,000, then it will try to hack that server. If there is $200,000 or less on the server, " +
"then the code will call grow('foodnstuff') instead and add more money to the server.<br><br>", "then the code will call grow('foodnstuff') instead and add more money to the server.<br><br>",
TutorialSingularityFunctionsText: "<u><h1>Singularity Functions</h1></u><br>" +
"The Singularity Functions are a special set of Netscript functions that are unlocked in BitNode-4. " +
"These functions allow you to control many additional aspects of the game through scripts, such as " +
"working for factions/companies, purchasing/installing Augmentations, and creating programs.<br><br>" +
"If you are in BitNode-4, then you will automatically have access to all of these functions. " +
"You can use the Singularity Functions in other BitNodes if and only if you have the Source-File " +
"for BitNode-4 (aka Source-File 4). Each level of Source-File 4 will open up additional Singularity " +
"Functions that you can use in other BitNodes. If your Source-File 4 is upgraded all the way to level 3, " +
"then you will be able to access all of the Singularity Functions.<br><br>" +
"Note that Singularity Functions require a lot of RAM outside of BitNode-4 (their RAM costs are multiplied by " +
"10 if you are not in BitNode-4).<br><br>" +
"<i>universityCourse(universityName, courseName)</i><br>" +
"If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to use this function.<br><br>" +
"This function will automatically set you to start taking a course at a university. If you are already " +
"in the middle of some 'working' action (such as working at a company, for a faction, or on a program), " +
"then running this function will automatically cancel that action and give you your earnings.<br><br>" +
"The first argument must be a string with the name of the university. The names are NOT case-sensitive. " +
"Note that you must be in the correct city for whatever university you specify. The three universities are:<br><br>" +
"Summit University<br>Rothman University<br>ZB Institute of Technology<br><br>" +
"The second argument must be a string with the name of the course you are taking. These names are NOT case-sensitive. " +
"The available courses are:<br><br>" +
"Study Computer Science<br>Data Structures<br>Networks<br>Algorithms<br>Management<br>Leadership<br><br>" +
"The cost and experience gains for all of these universities and classes are the same as if you were to manually " +
"visit and take these classes.<br><br>" +
"This function will return true if you successfully start taking the course, and false otherwise.<br><br>" +
"<i>gymWorkout(gymName, stat)</i><br>" +
"If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to use this function.<br><br>" +
"This function will automatically set you to start working out at a gym to train a particular stat. If you are " +
"already in the middle of some 'working' action (such as working at a company, for a faction, or on a program), then " +
"running this function will automatically cancel that action and give you your earnings.<br><br>" +
"The first argument must be a string with the name of the gym. The names are NOT case-sensitive. Note that you must " +
"be in the correct city for whatever gym you specify. The available gyms are:<br><br>" +
"Crush Fitness Gym<br>Snap Fitness Gym<br>Iron Gym<br>Powerhouse Gym<br>Millenium Fitness Gym<br><br>" +
"The second argument must be a string with the stat you want to work out. These are NOT case-sensitive. " +
"The valid stats are:<br><br>strength OR str<br>defense OR def<br>dexterity OR dex<br>agility OR agi<br><br>" +
"The cost and experience gains for all of these gyms are the same as if you were to manually visit these gyms and train " +
"This function will return true if you successfully start working out at the gym, and false otherwise.<br><br>" +
"<i>travelToCity(cityname)</i><br>" +
"If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to use this function.<br><br>" +
"This function allows the player to travel to any city. The cost for using this function is the same as the cost for traveling through the Travel Agency.<br><br>" +
"The argument passed into this must be a string with the name of the city to travel to. Note that this argument IS CASE SENSITIVE. The valid cities are:<br><br>" +
"Aevum<br>Chongqing<br>Sector-12<br>New Tokyo<br>Ishima<br>Volhaven<br><br>" +
"This function will return true if you successfully travel to the specified city and false otherwise.<br><br>" +
"<i>purchaseTor()</i><br>" +
"If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to use this function.<br><br>" +
"This function allows you to automatically purchase a TOR router. The cost for purchasing a TOR router using this " +
"function is the same as if you were to manually purchase one.<br><br>" +
"This function will return true if it successfully purchase a TOR router and false otherwise.<br><br>" +
"<i>purchaseProgram(programName)</i><br>" +
"If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to use this function.<br><br>" +
"This function allows you to automatically purchase programs. You MUST have a TOR router in order to use this function.<br><br>" +
"The argument passed in must be a string with the name of the program (including the '.exe' extension). This argument is " +
"NOT case-sensitive.<br><br>Example: " +
"purchaseProgram('brutessh.exe');<br><br>" +
"The cost of purchasing programs using this function is the same as if you were purchasing them through the Dark Web (using " +
"the buy Terminal command).<br><br>" +
"This function will return true if the specified program is purchased, and false otherwise.<br><br>" +
"<i>upgradeHomeRam()</i><br>" +
"If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.<br><br>" +
"This function will upgrade amount of RAM on the player's home computer. The cost is the same as if you were to do it manually.<br><br>" +
"This function will return true if the player's home computer RAM is successfully upgraded, and false otherwise.<br><br>" +
"<i>getUpgradeHomeRamCost()</i><br>" +
"If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.<br><br>" +
"Returns the cost of upgrading the player's home computer RAM.<br><br>" +
"<i>workForCompany()</i><br>" +
"If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.<br><br>" +
"This function will automatically set you to start working at the company at which you are employed. If you are already " +
"in the middle of some 'working' action (such as working for a faction, training at a gym, or creating a program), then " +
"running this function will automatically cancel that action and give you your earnings.<br><br>" +
"This function will return true if the player starts working, and false otherwise.<br><br>" +
"<i>applyToCompany(companyName, field)</i><br>" +
"If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.<br><br>" +
"This function will automatically try to apply to the specified company for a position in the specified field. This " +
"function can also be used to apply for promotions by specifying the company and field you are already employed at.<br><br>" +
"The first argument must be a string with the name of the company. This argument IS CASE-SENSITIVE. The second argument must " +
"be a string representing the 'field' to which you want to apply. This second argument is NOT case-sensitive. Valid values for " +
"the second argument are:<br><br>" +
"software<br>software consultant<br>it<br>security engineer<br>network engineer<br>business<br>business consultant<br>" +
"security<br>agent<br>employee<br>part-time employee<br>waiter<br>part-time waiter<br><br>" +
"This function will return true if you successfully get a job/promotion, and false otherwise. Note " +
"that if you are trying to use this function to apply for a promotion and you don't get one, it will return false.<br><br>" +
"<i>getCompanyRep(companyName)</i><br>" +
"If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.<br><br>" +
"This function will return the amount of reputation you have at the specified company. If the company passed in as " +
"an argument is invalid, -1 will be returned.<br><br>" +
"The argument passed in must be a string with the name of the company. This argument IS CASE-SENSITIVE.<br><br>" +
"<i>checkFactionInvitations()</i><br>" +
"If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.<br><br>" +
"Returns an array with the name of all Factions you currently have oustanding invitations from.<br><br>" +
"<i>joinFaction(name)</i><br>" +
"If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.<br><br>" +
"This function will automatically accept an invitation from a faction and join it.<br><br>" +
"The argument must be a string with the name of the faction. This name IS CASE-SENSITIVE.<br><br>" +
"<i>workForFaction(factionName, workType)</i><br>" +
"If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.<br><br>" +
"This function will automatically set you to start working for the specified Faction. Obviously, you " +
"must be a member of the Faction or else this function will fail. If you are already in the middle of " +
"some 'working' action (such as working for a company, training at a gym, or creating a program), then running " +
"this function will automatically cancel that action and give you your earnings.<br><br>" +
"The first argument must be a string with the name of the faction. This argument IS CASE-SENSITIVE. The second argument " +
"must be a string with the type of work you want to perform for the faction. The valid values for this argument are:<br><br>" +
"<br>hacking/hacking contracts/hackingcontracts<br>field/fieldwork/field work<br>security/securitywork/security work<br><br>" +
"This function will return true if you successfully start working for the specified faction, and false otherwise.<br><br>" +
"<i>getFactionRep(factionName)</i><br>" +
"If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.<br><br>" +
"This function returns the amount of reputation you have for the specified Faction. The argument must be a " +
"string with the name of the Faction. The argument IS CASE-SENSITIVE.<br><br>" +
"<i>createProgram(programName)</i><br>" +
"If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.<br><br>" +
"This function will automatically set you to start working on creating the specified program. If you are already in " +
"the middle of some 'working' action (such as working for a company, training at a gym, or taking a course), then " +
"running this function will automatically cancel that action and give you your earnings.<br><br>" +
"The argument passed in must be a string designating the name of the program. This argument is NOT case-sensitive.<br><br>" +
"Example:<br><br>createProgram('relaysmtp.exe');<br><br>" +
"Note that creating a program using this function has the same hacking level requirements as it normally would. These level requirements are:<br><br>" +
"BruteSSH.exe: 50<br>FTPCrack.exe: 100<br>relaySMTP.exe: 250<br>HTTPWorm.exe: 500<br>SQLInject.exe: 750<br>" +
"DeepscanV1.exe: 75<br>DeepscanV2.exe: 400<br>ServerProfiler.exe: 75<br>AutoLink.exe: 25<br><br>" +
"This function returns true if you successfully start working on the specified program, and false otherwise.<br><br>" +
"<i>getAugmentationCost(augName)</i><br>" +
"If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.<br><br>" +
"This function returns an array with two elements that gives the cost for the specified Augmentation" +
". The first element in the returned array is the reputation requirement of the Augmentation, and the second element " +
"is the money cost.<br><br>" +
"The argument passed in must be a string with the name of the Augmentation. This argument IS CASE-SENSITIVE. " +
"If an invalid Augmentation name is passed in, this function will return the array [-1, -1].<br><br>" +
"<i>purchaseAugmentation(factionName, augName)</i><br>" +
"If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.<br><br>" +
"This function will try to purchase the specified Augmentation through the given Faction.<br><br>" +
"The two arguments must be strings specifying the name of the Faction and Augmentation, respectively. These arguments are both CASE-SENSITIVE.<br><br>" +
"This function will return true if the Augmentation is successfully purchased, and false otherwise.<br><br>" +
"<i>installAugmentations()</i><br>" +
"If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.<br><br>" +
"This function will automatically install your Augmentations, resetting the game as usual.<br><br>" +
"It will return true if successful, and false otherwise.",
TutorialTravelingText:"There are six major cities in the world that you are able to travel to: <br><br> " + TutorialTravelingText:"There are six major cities in the world that you are able to travel to: <br><br> " +
" Aevum<br>" + " Aevum<br>" +
@ -717,38 +859,14 @@ CONSTANTS = {
"World Stock Exchange account and TIX API Access<br>", "World Stock Exchange account and TIX API Access<br>",
LatestUpdate: LatestUpdate:
"v0.27.3<br>" + "v0.28.1<br>" +
"-You can now purchase upgrades for Gang Members (BitNode 2 only)<br>" + "-The script editor now uses the open-source Ace editor, which provides a much better experience when coding!<br>" +
"-Decreased Gang respect gains and slightly increased wanted gains (BitNode 2 only)<br>" + "-Added tprint() Netscript function<br><br>" +
"-Other gangs will increase in power faster (BitNode 2 only)<br>" + "v0.28.0<br>" +
"-Added getHackTime(), getGrowTime(), and getWeakenTime() Netscript functions<br><br>" + "-Added BitNode-4: The Singularity<br>" +
"v0.27.2<br>" + "-Added BitNode-11: The Big Crash<br>" +
"-Added getServerGrowth() Netscript function<br>" + "-Migrated the codebase to use webpack (doesn't affect any in game content, except maybe some slight " +
"-Added getNextHacknetNodeCost() Netscript function<br>" + "performance improvements and there may be bugs that result from dependency errors)"
"-Added new 'literature' files (.lit extension) that are used to build lore for the game. " +
"These .lit files can be found in certain servers throughout the game. They can be viewed with the 'cat' Terminal " +
"command and copied over to other servers using the 'scp' command. These .lit files won't be found until you reset " +
"by installing Augmentations<br>" +
"Fixed some bugs with Gang Territory(BitNode 2 only)<br><br>" +
"v0.27.1<br>" +
"-Changed the way Gang power was calculated to make it scale better late game (BitNode 2 only)<br>" +
"-Lowered the respect gain rate in Gangs (Bitnode 2 only)<br>" +
"-Added '| grep pattern' option for ls Terminal command. This allows you to only list files that contain a certain pattern<br>" +
"-Added break statement in Netscript<br>" +
"-Display for some numerical values is now done in shorthand (e.g 1.000m instead of 1,000,000)<br><br>" +
"v0.27.0<br>" +
"-Added secondary 'prestige' system - featuring Source Files and BitNodes<br>" +
"-MILD SPOILERS HERE: Installing 'The Red Pill' Augmentation from Daedalus will unlock a special server called " +
"w0r1d_d43m0n. Finding and manually hacking this server through Terminal will destroy the Player's current BitNode, and allow the player " +
"to enter a new one. When destroying a BitNode, the player loses everything except the scripts on his/her " +
"home computer. The player will then gain a powerful second-tier persistent upgrade called a Source File. The player can then " +
"enter a new BitNode to start the game over. Each BitNode has different characteristics, and many will have new content/mechanics " +
"as well. Right now there are only 2 BitNodes. Each BitNode grants its own unique Source File. Restarting and destroying a BitNode you already " +
"have a Source File for will upgrade your Source File up to a maximum level of 3.<br><br>" +
"-Reputation gain with factions and companies is no longer a linear conversion, but an exponential one. It " +
"will be much easier to gain faction favor at first, but much harder later on. <br>" +
"-Significantly increased Infiltration exp gains<br>" +
"-Fixed a bug with company job requirement tooltips<br>" +
"-Added scriptRunning(), scriptKill(), and getScriptRam() Netscript functions. See documentation for details<br>" +
"-Fixed a bug with deleteServer() Netscript function<br><br>"
} }
export {CONSTANTS};

@ -1,17 +1,20 @@
import {CONSTANTS} from "./Constants.js";
import {Player} from "./Player.js";
/* Create programs */ /* Create programs */
Programs = { let Programs = {
NukeProgram: "NUKE.exe", NukeProgram: "NUKE.exe",
BruteSSHProgram: "BruteSSH.exe", BruteSSHProgram: "BruteSSH.exe",
FTPCrackProgram: "FTPCrack.exe", FTPCrackProgram: "FTPCrack.exe",
RelaySMTPProgram: "relaySMTP.exe", RelaySMTPProgram: "relaySMTP.exe",
HTTPWormProgram: "HTTPWorm.exe", HTTPWormProgram: "HTTPWorm.exe",
SQLInjectProgram: "SQLInject.exe", SQLInjectProgram: "SQLInject.exe",
DeepscanV1: "DeepscanV1.exe", DeepscanV1: "DeepscanV1.exe",
DeepscanV2: "DeepscanV2.exe", DeepscanV2: "DeepscanV2.exe",
ServerProfiler: "ServerProfiler.exe", ServerProfiler: "ServerProfiler.exe",
AutoLink: "AutoLink.exe", AutoLink: "AutoLink.exe",
Flight: "fl1ght.exe", Flight: "fl1ght.exe",
} };
//TODO Right now the times needed to complete work are hard-coded... //TODO Right now the times needed to complete work are hard-coded...
//maybe later make this dependent on hacking level or something //maybe later make this dependent on hacking level or something
@ -26,9 +29,9 @@ function displayCreateProgramContent() {
var deepscanv2ALink = document.getElementById("create-program-deepscanv2"); var deepscanv2ALink = document.getElementById("create-program-deepscanv2");
var servProfilerALink = document.getElementById("create-program-serverprofiler"); var servProfilerALink = document.getElementById("create-program-serverprofiler");
var autolinkALink = document.getElementById("create-program-autolink"); var autolinkALink = document.getElementById("create-program-autolink");
nukeALink.style.display = "none"; nukeALink.style.display = "none";
bruteSshALink.style.display = "none"; bruteSshALink.style.display = "none";
ftpCrackALink.style.display = "none"; ftpCrackALink.style.display = "none";
relaySmtpALink.style.display = "none"; relaySmtpALink.style.display = "none";
httpWormALink.style.display = "none"; httpWormALink.style.display = "none";
@ -37,15 +40,15 @@ function displayCreateProgramContent() {
deepscanv2ALink.style.display = "none"; deepscanv2ALink.style.display = "none";
servProfilerALink.style.display = "none"; servProfilerALink.style.display = "none";
autolinkALink.style.display = "none"; autolinkALink.style.display = "none";
//NUKE.exe (in case you delete it lol) //NUKE.exe (in case you delete it lol)
if (Player.getHomeComputer().programs.indexOf(Programs.NukeProgram) == -1) { if (Player.getHomeComputer().programs.indexOf(Programs.NukeProgram) == -1) {
nukeALink.style.display = "inline-block"; nukeALink.style.display = "inline-block";
} }
//BruteSSH //BruteSSH
if (Player.getHomeComputer().programs.indexOf(Programs.BruteSSHProgram) == -1 && if (Player.getHomeComputer().programs.indexOf(Programs.BruteSSHProgram) == -1 &&
Player.hacking_skill >= 50) { Player.hacking_skill >= 50) {
bruteSshALink.style.display = "inline-block"; bruteSshALink.style.display = "inline-block";
} }
//FTPCrack //FTPCrack
if (Player.getHomeComputer().programs.indexOf(Programs.FTPCrackProgram) == -1 && if (Player.getHomeComputer().programs.indexOf(Programs.FTPCrackProgram) == -1 &&
@ -88,7 +91,7 @@ function displayCreateProgramContent() {
function getNumAvailableCreateProgram() { function getNumAvailableCreateProgram() {
var count = 0; var count = 0;
//PortHack.exe (in case you delete it lol) //PortHack.exe (in case you delete it lol)
if (Player.getHomeComputer().programs.indexOf(Programs.NukeProgram) == -1) { if (Player.getHomeComputer().programs.indexOf(Programs.NukeProgram) == -1) {
++count; ++count;
} }
//BruteSSH //BruteSSH
@ -131,6 +134,7 @@ function getNumAvailableCreateProgram() {
if (!Player.hasProgram(Programs.AutoLink) && Player.hacking_skill >= 25) { if (!Player.hasProgram(Programs.AutoLink) && Player.hacking_skill >= 25) {
++count; ++count;
} }
if (count > 0) {Player.firstProgramAvailable = true;}
return count; return count;
} }
@ -145,7 +149,7 @@ function initCreateProgramButtons() {
var deepscanv2ALink = document.getElementById("create-program-deepscanv2"); var deepscanv2ALink = document.getElementById("create-program-deepscanv2");
var servProfilerALink = document.getElementById("create-program-serverprofiler"); var servProfilerALink = document.getElementById("create-program-serverprofiler");
var autolinkALink = document.getElementById("create-program-autolink"); var autolinkALink = document.getElementById("create-program-autolink");
nukeALink.addEventListener("click", function() { nukeALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.NukeProgram, CONSTANTS.MillisecondsPerFiveMinutes, 1); Player.startCreateProgramWork(Programs.NukeProgram, CONSTANTS.MillisecondsPerFiveMinutes, 1);
return false; return false;
@ -185,5 +189,8 @@ function initCreateProgramButtons() {
autolinkALink.addEventListener("click", function() { autolinkALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.AutoLink, CONSTANTS.MillisecondsPerQuarterHour, 25); Player.startCreateProgramWork(Programs.AutoLink, CONSTANTS.MillisecondsPerQuarterHour, 25);
return false; return false;
}); });
} }
export {Programs, displayCreateProgramContent, getNumAvailableCreateProgram,
initCreateProgramButtons};

@ -1,3 +1,7 @@
import {CONSTANTS} from "./Constants.js";
import {Player} from "./Player.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
/* Crimes.js */ /* Crimes.js */
function commitShopliftCrime() { function commitShopliftCrime() {
Player.crimeType = CONSTANTS.CrimeShoplift; Player.crimeType = CONSTANTS.CrimeShoplift;
@ -202,3 +206,14 @@ function determineCrimeChanceHeist() {
chance *= Player.crime_success_mult; chance *= Player.crime_success_mult;
return Math.min(chance, 1); return Math.min(chance, 1);
} }
export {commitShopliftCrime, commitRobStoreCrime, commitMugCrime,
commitLarcenyCrime, commitDealDrugsCrime, commitTraffickArmsCrime,
commitHomicideCrime, commitGrandTheftAutoCrime, commitKidnapCrime,
commitAssassinationCrime, commitHeistCrime, determineCrimeSuccess,
determineCrimeChanceShoplift, determineCrimeChanceRobStore,
determineCrimeChanceMug, determineCrimeChanceLarceny,
determineCrimeChanceDealDrugs, determineCrimeChanceTraffickArms,
determineCrimeChanceHomicide, determineCrimeChanceGrandTheftAuto,
determineCrimeChanceKidnap, determineCrimeChanceAssassination,
determineCrimeChanceHeist};

@ -1,6 +1,14 @@
import {Programs} from "./CreateProgram.js";
import {Player} from "./Player.js";
import {SpecialServerIps} from "./SpecialServerIps.js";
import {post} from "./Terminal.js";
import {formatNumber} from "../utils/StringHelperFunctions.js";
/* DarkWeb.js */ /* DarkWeb.js */
//Posts a "help" message if connected to DarkWeb //Posts a "help" message if connected to DarkWeb
checkIfConnectedToDarkweb = function() { function checkIfConnectedToDarkweb() {
if (SpecialServerIps.hasOwnProperty("Darkweb Server")) { if (SpecialServerIps.hasOwnProperty("Darkweb Server")) {
var darkwebIp = SpecialServerIps["Darkweb Server"]; var darkwebIp = SpecialServerIps["Darkweb Server"];
if (!isValidIPAddress(darkwebIp)) {return;} if (!isValidIPAddress(darkwebIp)) {return;}
@ -16,7 +24,7 @@ checkIfConnectedToDarkweb = function() {
//Handler for dark web commands. The terminal's executeCommand() function will pass //Handler for dark web commands. The terminal's executeCommand() function will pass
//dark web-specific commands into this. It will pass in the raw split command array //dark web-specific commands into this. It will pass in the raw split command array
//rather than the command string //rather than the command string
executeDarkwebTerminalCommand = function(commandArray) { function executeDarkwebTerminalCommand(commandArray) {
if (commandArray.length == 0) {return;} if (commandArray.length == 0) {return;}
switch (commandArray[0]) { switch (commandArray[0]) {
case "buy": case "buy":
@ -24,6 +32,7 @@ executeDarkwebTerminalCommand = function(commandArray) {
post("Incorrect number of arguments. Usage: "); post("Incorrect number of arguments. Usage: ");
post("buy -l"); post("buy -l");
post("buy [item name]"); post("buy [item name]");
return;
} }
var arg = commandArray[1]; var arg = commandArray[1];
if (arg == "-l") { if (arg == "-l") {
@ -38,7 +47,7 @@ executeDarkwebTerminalCommand = function(commandArray) {
} }
} }
listAllDarkwebItems = function() { function listAllDarkwebItems() {
for (var item in DarkWebItems) { for (var item in DarkWebItems) {
if (DarkWebItems.hasOwnProperty(item)) { if (DarkWebItems.hasOwnProperty(item)) {
var item = DarkWebItems[item]; var item = DarkWebItems[item];
@ -76,7 +85,7 @@ listAllDarkwebItems = function() {
else {return price;} else {return price;}
} }
buyDarkwebItem = function(itemName) { function buyDarkwebItem(itemName) {
if (itemName.toLowerCase() == Programs.BruteSSHProgram.toLowerCase()) { if (itemName.toLowerCase() == Programs.BruteSSHProgram.toLowerCase()) {
var price = parseDarkwebItemPrice(DarkWebItems.BruteSSHProgram); var price = parseDarkwebItemPrice(DarkWebItems.BruteSSHProgram);
if (price > 0 && Player.money.gt(price)) { if (price > 0 && Player.money.gt(price)) {
@ -152,7 +161,7 @@ buyDarkwebItem = function(itemName) {
} }
} }
parseDarkwebItemPrice = function(itemDesc) { function parseDarkwebItemPrice(itemDesc) {
var split = itemDesc.split(" - "); var split = itemDesc.split(" - ");
if (split.length == 3) { if (split.length == 3) {
var priceString = split[1]; var priceString = split[1];
@ -173,12 +182,16 @@ parseDarkwebItemPrice = function(itemDesc) {
} }
} }
DarkWebItems = { let DarkWebItems = {
BruteSSHProgram: Programs.BruteSSHProgram + " - $500,000 - Opens up SSH Ports", BruteSSHProgram: "BruteSSH.exe - $500,000 - Opens up SSH Ports",
FTPCrackProgram: Programs.FTPCrackProgram + " - $1,500,000 - Opens up FTP Ports", FTPCrackProgram: "FTPCrack.exe - $1,500,000 - Opens up FTP Ports",
RelaySMTPProgram: Programs.RelaySMTPProgram + " - $5,000,000 - Opens up SMTP Ports", RelaySMTPProgram: "relaySMTP.exe - $5,000,000 - Opens up SMTP Ports",
HTTPWormProgram: Programs.HTTPWormProgram + " - $30,000,000 - Opens up HTTP Ports", HTTPWormProgram: "HTTPWorm.exe - $30,000,000 - Opens up HTTP Ports",
SQLInjectProgram: Programs.SQLInjectProgram + " - $250,000,000 - Opens up SQL Ports", SQLInjectProgram: "SQLInject.exe - $250,000,000 - Opens up SQL Ports",
DeepScanV1Program: Programs.DeepscanV1 + " - $500,000 - Enables 'scan-analyze' with a depth up to 5", DeepScanV1Program: "DeepscanV1.exe - $500,000 - Enables 'scan-analyze' with a depth up to 5",
DeepScanV2Program: Programs.DeepscanV2 + " - $25,000,000 - Enables 'scan-analyze' with a depth up to 10", DeepScanV2Program: "DeepscanV2.exe - $25,000,000 - Enables 'scan-analyze' with a depth up to 10",
} }
export {checkIfConnectedToDarkweb, executeDarkwebTerminalCommand,
listAllDarkwebItems, buyDarkwebItem, parseDarkwebItemPrice,
DarkWebItems};

@ -1,3 +1,23 @@
import {Augmentations, AugmentationNames,
PlayerOwnedAugmentation} from "./Augmentations.js";
import {BitNodeMultipliers} from "./BitNode.js";
import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js";
import {FactionInfo} from "./FactionInfo.js";
import {Locations} from "./Location.js";
import {Player} from "./Player.js";
import {Settings} from "./Settings.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {factionInvitationBoxCreate} from "../utils/FactionInvitationBox.js";
import {clearEventListeners} from "../utils/HelperFunctions.js";
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js";
import {formatNumber, isPositiveNumber} from "../utils/StringHelperFunctions.js";
import {yesNoBoxCreate, yesNoBoxGetYesButton,
yesNoBoxGetNoButton, yesNoBoxClose} from "../utils/YesNoBox.js";
//Netburner Faction class //Netburner Faction class
function factionInit() { function factionInit() {
$('#faction-donate-input').on('input', function() { $('#faction-donate-input').on('input', function() {
@ -97,9 +117,13 @@ Faction.fromJSON = function(value) {
Reviver.constructors.Faction = Faction; Reviver.constructors.Faction = Faction;
//Map of factions indexed by faction name //Map of factions indexed by faction name
Factions = {} let Factions = {}
AddToFactions = function(faction) { function loadFactions(saveString) {
Factions = JSON.parse(saveString, Reviver);
}
function AddToFactions(faction) {
var name = faction.name; var name = faction.name;
Factions[name] = faction; Factions[name] = faction;
} }
@ -110,7 +134,7 @@ function factionExists(name) {
//TODO Augmentation price and rep requirement mult are 1 for everything right now, //TODO Augmentation price and rep requirement mult are 1 for everything right now,
// This might change in the future for balance // This might change in the future for balance
initFactions = function() { function initFactions() {
//Endgame //Endgame
var Illuminati = new Faction("Illuminati"); var Illuminati = new Faction("Illuminati");
Illuminati.setInfo(FactionInfo.IlluminatiInfo); Illuminati.setInfo(FactionInfo.IlluminatiInfo);
@ -368,304 +392,7 @@ initFactions = function() {
AddToFactions(CyberSec); AddToFactions(CyberSec);
} }
//This function sets the requirements to join a Faction. It checks whether the Player meets function inviteToFaction(faction) {
//those requirements and will return an array of all factions that the Player should
//receive an invitation to
PlayerObject.prototype.checkForFactionInvitations = function() {
invitedFactions = []; //Array which will hold all Factions th eplayer should be invited to
var numAugmentations = this.augmentations.length;
var company = Companies[this.companyName];
var companyRep = 0;
if (company != null) {
companyRep = company.playerReputation;
}
//Illuminati
var illuminatiFac = Factions["Illuminati"];
if (!illuminatiFac.isBanned && !illuminatiFac.isMember && !illuminatiFac.alreadyInvited &&
numAugmentations >= 30 &&
this.money.gte(150000000000) &&
this.hacking_skill >= 1500 &&
this.strength >= 1200 && this.defense >= 1200 &&
this.dexterity >= 1200 && this.agility >= 1200) {
invitedFactions.push(illuminatiFac);
}
//Daedalus
var daedalusFac = Factions["Daedalus"];
if (!daedalusFac.isBanned && !daedalusFac.isMember && !daedalusFac.alreadyInvited &&
numAugmentations >= 30 &&
this.money.gte(100000000000) &&
(this.hacking_skill >= 2500 ||
(this.strength >= 1500 && this.defense >= 1500 &&
this.dexterity >= 1500 && this.agility >= 1500))) {
invitedFactions.push(daedalusFac);
}
//The Covenant
var covenantFac = Factions["The Covenant"];
if (!covenantFac.isBanned && !covenantFac.isMember && !covenantFac.alreadyInvited &&
numAugmentations >= 30 &&
this.money.gte(75000000000) &&
this.hacking_skill >= 850 &&
this.strength >= 850 &&
this.defense >= 850 &&
this.dexterity >= 850 &&
this.agility >= 850) {
invitedFactions.push(covenantFac);
}
//ECorp
var ecorpFac = Factions["ECorp"];
if (!ecorpFac.isBanned && !ecorpFac.isMember && !ecorpFac.alreadyInvited &&
this.companyName == Locations.AevumECorp && companyRep >= CONSTANTS.CorpFactionRepRequirement) {
invitedFactions.push(ecorpFac);
}
//MegaCorp
var megacorpFac = Factions["MegaCorp"];
if (!megacorpFac.isBanned && !megacorpFac.isMember && !megacorpFac.alreadyInvited &&
this.companyName == Locations.Sector12MegaCorp && companyRep >= CONSTANTS.CorpFactionRepRequirement) {
invitedFactions.push(megacorpFac);
}
//Bachman & Associates
var bachmanandassociatesFac = Factions["Bachman & Associates"];
if (!bachmanandassociatesFac.isBanned && !bachmanandassociatesFac.isMember &&
!bachmanandassociatesFac.alreadyInvited &&
this.companyName == Locations.AevumBachmanAndAssociates && companyRep >= CONSTANTS.CorpFactionRepRequirement) {
invitedFactions.push(bachmanandassociatesFac);
}
//Blade Industries
var bladeindustriesFac = Factions["Blade Industries"];
if (!bladeindustriesFac.isBanned && !bladeindustriesFac.isMember && !bladeindustriesFac.alreadyInvited &&
this.companyName == Locations.Sector12BladeIndustries && companyRep >= CONSTANTS.CorpFactionRepRequirement) {
invitedFactions.push(bladeindustriesFac);
}
//NWO
var nwoFac = Factions["NWO"];
if (!nwoFac.isBanned && !nwoFac.isMember && !nwoFac.alreadyInvited &&
this.companyName == Locations.VolhavenNWO && companyRep >= CONSTANTS.CorpFactionRepRequirement) {
invitedFactions.push(nwoFac);
}
//Clarke Incorporated
var clarkeincorporatedFac = Factions["Clarke Incorporated"];
if (!clarkeincorporatedFac.isBanned && !clarkeincorporatedFac.isMember && !clarkeincorporatedFac.alreadyInvited &&
this.companyName == Locations.AevumClarkeIncorporated && companyRep >= CONSTANTS.CorpFactionRepRequirement) {
invitedFactions.push(clarkeincorporatedFac);
}
//OmniTek Incorporated
var omnitekincorporatedFac = Factions["OmniTek Incorporated"];
if (!omnitekincorporatedFac.isBanned && !omnitekincorporatedFac.isMember && !omnitekincorporatedFac.alreadyInvited &&
this.companyName == Locations.VolhavenOmniTekIncorporated && companyRep >= CONSTANTS.CorpFactionRepRequirement) {
invitedFactions.push(omnitekincorporatedFac);
}
//Four Sigma
var foursigmaFac = Factions["Four Sigma"];
if (!foursigmaFac.isBanned && !foursigmaFac.isMember && !foursigmaFac.alreadyInvited &&
this.companyName == Locations.Sector12FourSigma && companyRep >= CONSTANTS.CorpFactionRepRequirement) {
invitedFactions.push(foursigmaFac);
}
//KuaiGong International
var kuaigonginternationalFac = Factions["KuaiGong International"];
if (!kuaigonginternationalFac.isBanned && !kuaigonginternationalFac.isMember &&
!kuaigonginternationalFac.alreadyInvited &&
this.companyName == Locations.ChongqingKuaiGongInternational && companyRep >= CONSTANTS.CorpFactionRepRequirement) {
invitedFactions.push(kuaigonginternationalFac);
}
//Fulcrum Secret Technologies - If u've unlocked fulcrum secret technolgoies server and have a high rep with the company
var fulcrumsecrettechonologiesFac = Factions["Fulcrum Secret Technologies"];
var fulcrumSecretServer = AllServers[SpecialServerIps[SpecialServerNames.FulcrumSecretTechnologies]];
if (fulcrumSecretServer == null) {
console.log("ERROR: Could not find Fulcrum Secret Technologies Server");
} else {
if (!fulcrumsecrettechonologiesFac.isBanned && !fulcrumsecrettechonologiesFac.isMember &&
!fulcrumsecrettechonologiesFac.alreadyInvited &&
fulcrumSecretServer.manuallyHacked &&
this.companyName == Locations.AevumFulcrumTechnologies && companyRep >= 250000) {
invitedFactions.push(fulcrumsecrettechonologiesFac);
}
}
//BitRunners
var bitrunnersFac = Factions["BitRunners"];
var homeComp = this.getHomeComputer();
var bitrunnersServer = AllServers[SpecialServerIps[SpecialServerNames.BitRunnersServer]];
if (bitrunnersServer == null) {
console.log("ERROR: Could not find BitRunners Server");
} else if (!bitrunnersFac.isBanned && !bitrunnersFac.isMember && bitrunnersServer.manuallyHacked &&
!bitrunnersFac.alreadyInvited && this.hacking_skill >= 500 && homeComp.maxRam >= 128) {
invitedFactions.push(bitrunnersFac);
}
//The Black Hand
var theblackhandFac = Factions["The Black Hand"];
var blackhandServer = AllServers[SpecialServerIps[SpecialServerNames.TheBlackHandServer]];
if (blackhandServer == null) {
console.log("ERROR: Could not find The Black Hand Server");
} else if (!theblackhandFac.isBanned && !theblackhandFac.isMember && blackhandServer.manuallyHacked &&
!theblackhandFac.alreadyInvited && this.hacking_skill >= 350 && homeComp.maxRam >= 64) {
invitedFactions.push(theblackhandFac);
}
//NiteSec
var nitesecFac = Factions["NiteSec"];
var nitesecServer = AllServers[SpecialServerIps[SpecialServerNames.NiteSecServer]];
if (nitesecServer == null) {
console.log("ERROR: Could not find NiteSec Server");
} else if (!nitesecFac.isBanned && !nitesecFac.isMember && nitesecServer.manuallyHacked &&
!nitesecFac.alreadyInvited && this.hacking_skill >= 200 && homeComp.maxRam >= 32) {
invitedFactions.push(nitesecFac);
}
//Chongqing
var chongqingFac = Factions["Chongqing"];
if (!chongqingFac.isBanned && !chongqingFac.isMember && !chongqingFac.alreadyInvited &&
this.money.gte(20000000) && this.city == Locations.Chongqing) {
invitedFactions.push(chongqingFac);
}
//Sector-12
var sector12Fac = Factions["Sector-12"];
if (!sector12Fac.isBanned && !sector12Fac.isMember && !sector12Fac.alreadyInvited &&
this.money.gte(15000000) && this.city == Locations.Sector12) {
invitedFactions.push(sector12Fac);
}
//New Tokyo
var newtokyoFac = Factions["New Tokyo"];
if (!newtokyoFac.isBanned && !newtokyoFac.isMember && !newtokyoFac.alreadyInvited &&
this.money.gte(20000000) && this.city == Locations.NewTokyo) {
invitedFactions.push(newtokyoFac);
}
//Aevum
var aevumFac = Factions["Aevum"];
if (!aevumFac.isBanned && !aevumFac.isMember && !aevumFac.alreadyInvited &&
this.money.gte(40000000) && this.city == Locations.Aevum) {
invitedFactions.push(aevumFac);
}
//Ishima
var ishimaFac = Factions["Ishima"];
if (!ishimaFac.isBanned && !ishimaFac.isMember && !ishimaFac.alreadyInvited &&
this.money.gte(30000000) && this.city == Locations.Ishima) {
invitedFactions.push(ishimaFac);
}
//Volhaven
var volhavenFac = Factions["Volhaven"];
if (!volhavenFac.isBanned && !volhavenFac.isMember && !volhavenFac.alreadyInvited &&
this.money.gte(50000000) && this.city == Locations.Volhaven) {
invitedFactions.push(volhavenFac);
}
//Speakers for the Dead
var speakersforthedeadFac = Factions["Speakers for the Dead"];
if (!speakersforthedeadFac.isBanned && !speakersforthedeadFac.isMember && !speakersforthedeadFac.alreadyInvited &&
this.hacking_skill >= 100 && this.strength >= 300 && this.defense >= 300 &&
this.dexterity >= 300 && this.agility >= 300 && this.numPeopleKilled >= 30 &&
this.karma <= -45 && this.companyName != Locations.Sector12CIA &&
this.companyName != Locations.Sector12NSA) {
invitedFactions.push(speakersforthedeadFac);
}
//The Dark Army
var thedarkarmyFac = Factions["The Dark Army"];
if (!thedarkarmyFac.isBanned && !thedarkarmyFac.isMember && !thedarkarmyFac.alreadyInvited &&
this.hacking_skill >= 300 && this.strength >= 300 && this.defense >= 300 &&
this.dexterity >= 300 && this.agility >= 300 && this.city == Locations.Chongqing &&
this.numPeopleKilled >= 5 && this.karma <= -45 && this.companyName != Locations.Sector12CIA &&
this.companyName != Locations.Sector12NSA) {
invitedFactions.push(thedarkarmyFac);
}
//The Syndicate
var thesyndicateFac = Factions["The Syndicate"];
if (!thesyndicateFac.isBanned && !thesyndicateFac.isMember && !thesyndicateFac.alreadyInvited &&
this.hacking_skill >= 200 && this.strength >= 200 && this.defense >= 200 &&
this.dexterity >= 200 && this.agility >= 200 &&
(this.city == Locations.Aevum || this.city == Locations.Sector12) &&
this.money.gte(10000000) && this.karma <= -90 &&
this.companyName != Locations.Sector12CIA && this.companyName != Locations.Sector12NSA) {
invitedFactions.push(thesyndicateFac);
}
//Silhouette
var silhouetteFac = Factions["Silhouette"];
if (!silhouetteFac.isBanned && !silhouetteFac.isMember && !silhouetteFac.alreadyInvited &&
(this.companyPosition.positionName == CompanyPositions.CTO.positionName ||
this.companyPosition.positionName == CompanyPositions.CFO.positionName ||
this.companyPosition.positionName == CompanyPositions.CEO.positionName) &&
this.money.gte(15000000) && this.karma <= -22) {
invitedFactions.push(silhouetteFac);
}
//Tetrads
var tetradsFac = Factions["Tetrads"];
if (!tetradsFac.isBanned && !tetradsFac.isMember && !tetradsFac.alreadyInvited &&
(this.city == Locations.Chongqing || this.city == Locations.NewTokyo ||
this.city == Locations.Ishima) && this.strength >= 75 && this.defense >= 75 &&
this.dexterity >= 75 && this.agility >= 75 && this.karma <= -18) {
invitedFactions.push(tetradsFac);
}
//SlumSnakes
var slumsnakesFac = Factions["Slum Snakes"];
if (!slumsnakesFac.isBanned && !slumsnakesFac.isMember && !slumsnakesFac.alreadyInvited &&
this.strength >= 30 && this.defense >= 30 && this.dexterity >= 30 &&
this.agility >= 30 && this.karma <= -9 && this.money.gte(1000000)) {
invitedFactions.push(slumsnakesFac);
}
//Netburners
var netburnersFac = Factions["Netburners"];
var totalHacknetRam = 0;
var totalHacknetCores = 0;
var totalHacknetLevels = 0;
for (var i = 0; i < Player.hacknetNodes.length; ++i) {
totalHacknetLevels += Player.hacknetNodes[i].level;
totalHacknetRam += Player.hacknetNodes[i].ram;
totalHacknetCores += Player.hacknetNodes[i].cores;
}
if (!netburnersFac.isBanned && !netburnersFac.isMember && !netburnersFac.alreadyInvited &&
this.hacking_skill >= 80 && totalHacknetRam >= 8 &&
totalHacknetCores >= 4 && totalHacknetLevels >= 100) {
invitedFactions.push(netburnersFac);
}
//Tian Di Hui
var tiandihuiFac = Factions["Tian Di Hui"];
if (!tiandihuiFac.isBanned && !tiandihuiFac.isMember && !tiandihuiFac.alreadyInvited &&
this.money.gte(1000000) && this.hacking_skill >= 50 &&
(this.city == Locations.Chongqing || this.city == Locations.NewTokyo ||
this.city == Locations.Ishima)) {
invitedFactions.push(tiandihuiFac);
}
//CyberSec
var cybersecFac = Factions["CyberSec"];
var cybersecServer = AllServers[SpecialServerIps[SpecialServerNames.CyberSecServer]];
if (cybersecServer == null) {
console.log("ERROR: Could not find CyberSec Server");
} else if (!cybersecFac.isBanned && !cybersecFac.isMember && cybersecServer.manuallyHacked &&
!cybersecFac.alreadyInvited && this.hacking_skill >= 50) {
invitedFactions.push(cybersecFac);
}
return invitedFactions;
}
inviteToFaction = function(faction) {
if (Settings.SuppressFactionInvites) { if (Settings.SuppressFactionInvites) {
faction.alreadyInvited = true; faction.alreadyInvited = true;
Player.factionInvitations.push(faction.name); Player.factionInvitations.push(faction.name);
@ -674,7 +401,7 @@ inviteToFaction = function(faction) {
} }
} }
joinFaction = function(faction) { function joinFaction(faction) {
faction.isMember = true; faction.isMember = true;
Player.factions.push(faction.name); Player.factions.push(faction.name);
@ -710,47 +437,8 @@ joinFaction = function(faction) {
} }
} }
leaveFaction = function(faction) {
faction.isMember = false;
var i = Player.factions.indexOf(faction.name);
if (i > -1) {
Player.factions.splice(i, 1);
}
//Unban from faction
if (faction.name == "Chongqing") {
Factions["Sector-12"].isBanned = false;
Factions["Aevum"].isBanned = false;
Factions["Volhaven"].isBanned = false;
} else if (faction.name == "Sector-12") {
Factions["Chongqing"].isBanned = false;
Factions["New Tokyo"].isBanned = false;
Factions["Ishima"].isBanned = false;
Factions["Volhaven"].isBanned = false;
} else if (faction.name == "New Tokyo") {
Factions["Sector-12"].isBanned = false;
Factions["Aevum"].isBanned = false;
Factions["Volhaven"].isBanned = false;
} else if (faction.name == "Aevum") {
Factions["Chongqing"].isBanned = false;
Factions["New Tokyo"].isBanned = false;
Factions["Ishima"].isBanned = false;
Factions["Volhaven"].isBanned = false;
} else if (faction.name == "Ishima") {
Factions["Sector-12"].isBanned = false;
Factions["Aevum"].isBanned = false;
Factions["Volhaven"].isBanned = false;
} else if (faction.name == "Volhaven") {
Factions["Chongqing"].isBanned = false;
Factions["Sector-12"].isBanned = false;
Factions["New Tokyo"].isBanned = false;
Factions["Aevum"].isBanned = false;
Factions["Ishima"].isBanned = false;
}
}
//Displays the HTML content for a specific faction //Displays the HTML content for a specific faction
displayFactionContent = function(factionName) { function displayFactionContent(factionName) {
var faction = Factions[factionName]; var faction = Factions[factionName];
document.getElementById("faction-name").innerHTML = factionName; document.getElementById("faction-name").innerHTML = factionName;
document.getElementById("faction-info").innerHTML = "<i>" + faction.info + "</i>"; document.getElementById("faction-info").innerHTML = "<i>" + faction.info + "</i>";
@ -882,8 +570,8 @@ displayFactionContent = function(factionName) {
noBtn.innerHTML = "Cancel"; noBtn.innerHTML = "Cancel";
yesBtn.addEventListener("click", () => { yesBtn.addEventListener("click", () => {
var hacking = false; var hacking = false;
if (factionName == "NiteSec" || factionName == "The Black Hand") {hacking = true;} if (factionName === "NiteSec" || factionName === "The Black Hand") {hacking = true;}
Player.gang = new Gang(factionName, hacking); Player.startGang(factionName, hacking);
Engine.loadGangContent(); Engine.loadGangContent();
yesNoBoxClose(); yesNoBoxClose();
}); });
@ -1077,7 +765,7 @@ displayFactionContent = function(factionName) {
} }
} }
displayFactionAugmentations = function(factionName) { function displayFactionAugmentations(factionName) {
document.getElementById("faction-augmentations-page-desc").innerHTML = "Lists all augmentations that are available to purchase from " + factionName; document.getElementById("faction-augmentations-page-desc").innerHTML = "Lists all augmentations that are available to purchase from " + factionName;
var faction = Factions[factionName]; var faction = Factions[factionName];
@ -1150,87 +838,12 @@ displayFactionAugmentations = function(factionName) {
} }
} }
purchaseAugmentationBoxCreate = function(aug, fac) { function purchaseAugmentationBoxCreate(aug, fac) {
var yesBtn = yesNoBoxGetYesButton(), noBtn = yesNoBoxGetNoButton(); var yesBtn = yesNoBoxGetYesButton(), noBtn = yesNoBoxGetNoButton();
yesBtn.innerHTML = "Purchase"; yesBtn.innerHTML = "Purchase";
noBtn.innerHTML = "Cancel"; noBtn.innerHTML = "Cancel";
yesBtn.addEventListener("click", function() { yesBtn.addEventListener("click", function() {
//TODO Requirements for specific augmentations (e.g Embedded Netburner Module b4 its upgrades) purchaseAugmentation(aug, fac);
if (aug.name == AugmentationNames.Targeting2 &&
Augmentations[AugmentationNames.Targeting1].owned == false) {
dialogBoxCreate("You must first install Augmented Targeting I before you can upgrade it to Augmented Targeting II");
} else if (aug.name == AugmentationNames.Targeting3 &&
Augmentations[AugmentationNames.Targeting2].owned == false) {
dialogBoxCreate("You must first install Augmented Targeting II before you can upgrade it to Augmented Targeting III");
} else if (aug.name == AugmentationNames.CombatRib2 &&
Augmentations[AugmentationNames.CombatRib1].owned == false) {
dialogBoxCreate("You must first install Combat Rib I before you can upgrade it to Combat Rib II");
} else if (aug.name == AugmentationNames.CombatRib3 &&
Augmentations[AugmentationNames.CombatRib2].owned == false) {
dialogBoxCreate("You must first install Combat Rib II before you can upgrade it to Combat Rib III");
} else if (aug.name == AugmentationNames.GrapheneBionicSpine &&
Augmentations[AugmentationNames.BionicSpine].owned == false) {
dialogBoxCreate("You must first install a Bionic Spine before you can upgrade it to a Graphene Bionic Spine");
} else if (aug.name == AugmentationNames.GrapheneBionicLegs &&
Augmentations[AugmentationNames.BionicLegs].owned == false) {
dialogBoxCreate("You must first install Bionic Legs before you can upgrade it to Graphene Bionic Legs");
} else if (aug.name == AugmentationNames.ENMCoreV2 &&
Augmentations[AugmentationNames.ENMCore].owned == false) {
dialogBoxCreate("You must first install Embedded Netburner Module Core Implant before you can upgrade it to V2");
} else if (aug.name == AugmentationNames.ENMCoreV3 &&
Augmentations[AugmentationNames.ENMCoreV2].owned == false) {
dialogBoxCreate("You must first install Embedded Netburner Module Core V2 Upgrade before you can upgrade it to V3");
} else if ((aug.name == AugmentationNames.ENMCore ||
aug.name == AugmentationNames.ENMAnalyzeEngine ||
aug.name == AugmentationNames.ENMDMA) &&
Augmentations[AugmentationNames.ENM].owned == false) {
dialogBoxCreate("You must first install the Embedded Netburner Module before installing any upgrades to it");
} else if ((aug.name == AugmentationNames.PCDNIOptimizer ||
aug.name == AugmentationNames.PCDNINeuralNetwork) &&
Augmentations[AugmentationNames.PCDNI].owned == false) {
dialogBoxCreate("You must first install the Pc Direct-Neural Interface before installing this upgrade");
} else if (aug.name == AugmentationNames.GrapheneBrachiBlades &&
Augmentations[AugmentationNames.BrachiBlades].owned == false) {
dialogBoxCreate("You must first install the Brachi Blades augmentation before installing this upgrade");
} else if (aug.name == AugmentationNames.GrapheneBionicArms &&
Augmentations[AugmentationNames.BionicArms].owned == false) {
dialogBoxCreate("You must first install the Bionic Arms augmentation before installing this upgrade");
} else if (Player.money.gte(aug.baseCost * fac.augmentationPriceMult)) {
var queuedAugmentation = new PlayerOwnedAugmentation(aug.name);
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
queuedAugmentation.level = getNextNeurofluxLevel();
}
Player.queuedAugmentations.push(queuedAugmentation);
Player.loseMoney((aug.baseCost * fac.augmentationPriceMult));
dialogBoxCreate("You purchased " + aug.name + ". It's enhancements will not take " +
"effect until they are installed. To install your augmentations, go to the " +
"'Augmentations' tab on the left-hand navigation menu. Purchasing additional " +
"augmentations will now be more expensive.");
//If you just purchased Neuroflux Governor, recalculate the cost
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
var nextLevel = getNextNeurofluxLevel();
--nextLevel;
var mult = Math.pow(CONSTANTS.NeuroFluxGovernorLevelMult, nextLevel);
aug.setRequirements(500 * mult, 750000 * mult);
for (var i = 0; i < Player.queuedAugmentations.length-1; ++i) {
aug.baseCost *= CONSTANTS.MultipleAugMultiplier;
}
}
for (var name in Augmentations) {
if (Augmentations.hasOwnProperty(name)) {
Augmentations[name].baseCost *= CONSTANTS.MultipleAugMultiplier;
}
}
displayFactionAugmentations(fac.name);
} else {
dialogBoxCreate("You don't have enough money to purchase this Augmentation!");
}
yesNoBoxClose();
}); });
noBtn.addEventListener("click", function() { noBtn.addEventListener("click", function() {
yesNoBoxClose(); yesNoBoxClose();
@ -1242,6 +855,107 @@ purchaseAugmentationBoxCreate = function(aug, fac) {
formatNumber(aug.baseCost * fac.augmentationPriceMult, 2) + "?"); formatNumber(aug.baseCost * fac.augmentationPriceMult, 2) + "?");
} }
function purchaseAugmentation(aug, fac, sing=false) {
if (aug.name == AugmentationNames.Targeting2 &&
Augmentations[AugmentationNames.Targeting1].owned == false) {
var txt = "You must first install Augmented Targeting I before you can upgrade it to Augmented Targeting II";
if (sing) {return txt;} else {dialogBoxCreate(txt);}
} else if (aug.name == AugmentationNames.Targeting3 &&
Augmentations[AugmentationNames.Targeting2].owned == false) {
var txt = "You must first install Augmented Targeting II before you can upgrade it to Augmented Targeting III";
if (sing) {return txt;} else {dialogBoxCreate(txt);}
} else if (aug.name == AugmentationNames.CombatRib2 &&
Augmentations[AugmentationNames.CombatRib1].owned == false) {
var txt = "You must first install Combat Rib I before you can upgrade it to Combat Rib II";
if (sing) {return txt;} else {dialogBoxCreate(txt);}
} else if (aug.name == AugmentationNames.CombatRib3 &&
Augmentations[AugmentationNames.CombatRib2].owned == false) {
var txt = "You must first install Combat Rib II before you can upgrade it to Combat Rib III";
if (sing) {return txt;} else {dialogBoxCreate(txt);}
} else if (aug.name == AugmentationNames.GrapheneBionicSpine &&
Augmentations[AugmentationNames.BionicSpine].owned == false) {
var txt = "You must first install a Bionic Spine before you can upgrade it to a Graphene Bionic Spine";
if (sing) {return txt;} else {dialogBoxCreate(txt);}
} else if (aug.name == AugmentationNames.GrapheneBionicLegs &&
Augmentations[AugmentationNames.BionicLegs].owned == false) {
var txt = "You must first install Bionic Legs before you can upgrade it to Graphene Bionic Legs";
if (sing) {return txt;} else {dialogBoxCreate(txt);}
} else if (aug.name == AugmentationNames.ENMCoreV2 &&
Augmentations[AugmentationNames.ENMCore].owned == false) {
var txt = "You must first install Embedded Netburner Module Core Implant before you can upgrade it to V2";
if (sing) {return txt;} else {dialogBoxCreate(txt);}
} else if (aug.name == AugmentationNames.ENMCoreV3 &&
Augmentations[AugmentationNames.ENMCoreV2].owned == false) {
var txt = "You must first install Embedded Netburner Module Core V2 Upgrade before you can upgrade it to V3";
if (sing) {return txt;} else {dialogBoxCreate(txt);}
} else if ((aug.name == AugmentationNames.ENMCore ||
aug.name == AugmentationNames.ENMAnalyzeEngine ||
aug.name == AugmentationNames.ENMDMA) &&
Augmentations[AugmentationNames.ENM].owned == false) {
var txt = "You must first install the Embedded Netburner Module before installing any upgrades to it";
if (sing) {return txt;} else {dialogBoxCreate(txt);}
} else if ((aug.name == AugmentationNames.PCDNIOptimizer ||
aug.name == AugmentationNames.PCDNINeuralNetwork) &&
Augmentations[AugmentationNames.PCDNI].owned == false) {
var txt = "You must first install the Pc Direct-Neural Interface before installing this upgrade";
if (sing) {return txt;} else {dialogBoxCreate(txt);}
} else if (aug.name == AugmentationNames.GrapheneBrachiBlades &&
Augmentations[AugmentationNames.BrachiBlades].owned == false) {
var txt = "You must first install the Brachi Blades augmentation before installing this upgrade";
if (sing) {return txt;} else {dialogBoxCreate(txt);}
} else if (aug.name == AugmentationNames.GrapheneBionicArms &&
Augmentations[AugmentationNames.BionicArms].owned == false) {
var txt = "You must first install the Bionic Arms augmentation before installing this upgrade";
if (sing) {return txt;} else {dialogBoxCreate(txt);}
} else if (Player.money.gte(aug.baseCost * fac.augmentationPriceMult)) {
Player.firstAugPurchased = true;
var queuedAugmentation = new PlayerOwnedAugmentation(aug.name);
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
queuedAugmentation.level = getNextNeurofluxLevel();
}
Player.queuedAugmentations.push(queuedAugmentation);
Player.loseMoney((aug.baseCost * fac.augmentationPriceMult));
//If you just purchased Neuroflux Governor, recalculate the cost
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
var nextLevel = getNextNeurofluxLevel();
--nextLevel;
var mult = Math.pow(CONSTANTS.NeuroFluxGovernorLevelMult, nextLevel);
aug.setRequirements(500 * mult, 750000 * mult);
for (var i = 0; i < Player.queuedAugmentations.length-1; ++i) {
aug.baseCost *= CONSTANTS.MultipleAugMultiplier;
}
}
for (var name in Augmentations) {
if (Augmentations.hasOwnProperty(name)) {
Augmentations[name].baseCost *= CONSTANTS.MultipleAugMultiplier;
}
}
if (sing) {
return "You purchased " + aug.name;
} else {
dialogBoxCreate("You purchased " + aug.name + ". It's enhancements will not take " +
"effect until they are installed. To install your augmentations, go to the " +
"'Augmentations' tab on the left-hand navigation menu. Purchasing additional " +
"augmentations will now be more expensive.");
}
displayFactionAugmentations(fac.name);
} else {
if (sing) {
return "You don't have enough money to purchase " + aug.name;
} else {
dialogBoxCreate("You don't have enough money to purchase this Augmentation!");
}
}
yesNoBoxClose();
}
function getNextNeurofluxLevel() { function getNextNeurofluxLevel() {
var aug = Augmentations[AugmentationNames.NeuroFluxGovernor]; var aug = Augmentations[AugmentationNames.NeuroFluxGovernor];
if (aug == null) { if (aug == null) {
@ -1277,3 +991,7 @@ function processPassiveFactionRepGain(numCycles) {
} }
} }
} }
export {getNextNeurofluxLevel, Factions, initFactions, inviteToFaction,
joinFaction, displayFactionContent, processPassiveFactionRepGain,
loadFactions, Faction, purchaseAugmentation, factionExists};

@ -1,45 +1,45 @@
//Contains the "information" property for all the Factions, which is just a description //Contains the "information" property for all the Factions, which is just a description
//of each faction //of each faction
FactionInfo = { let FactionInfo = {
//Endgame //Endgame
IlluminatiInfo: "Humanity never changes. No matter how civilized society becomes, it will eventually fall back " + IlluminatiInfo: "Humanity never changes. No matter how civilized society becomes, it will eventually fall back " +
"into chaos. And from this chaos, we are the Invisible hand that guides them to order. ", "into chaos. And from this chaos, we are the Invisible hand that guides them to order. ",
DaedalusInfo: "Yesterday we obeyed kings and bent our necks to emperors. Today we kneel only to truth.", DaedalusInfo: "Yesterday we obeyed kings and bent our necks to emperors. Today we kneel only to truth.",
CovenantInfo: "Surrender yourself. Give up your empty individuality to become part of something great, something eternal. " + CovenantInfo: "Surrender yourself. Give up your empty individuality to become part of something great, something eternal. " +
"Become a slave. Submit your mind, body, and soul. Only then can you set yourself free.<br><br> " + "Become a slave. Submit your mind, body, and soul. Only then can you set yourself free.<br><br> " +
"Only then can you discover immortality.", "Only then can you discover immortality.",
//Megacorporations, each forms its own faction //Megacorporations, each forms its own faction
ECorpInfo: "ECorp's mission is simple: to connect the world of today with the technology of tomorrow. " + ECorpInfo: "ECorp's mission is simple: to connect the world of today with the technology of tomorrow. " +
"With our wide range of Internet-related software and commercial hardware, ECorp makes the world's " + "With our wide range of Internet-related software and commercial hardware, ECorp makes the world's " +
"information universally accessible.", "information universally accessible.",
MegaCorpInfo: "MegaCorp does things that others don't. We imagine. We create. We invent. We build things that " + MegaCorpInfo: "MegaCorp does things that others don't. We imagine. We create. We invent. We build things that " +
"others have never even dreamed of. Our work fills the world's needs for food, water, power, and " + "others have never even dreamed of. Our work fills the world's needs for food, water, power, and " +
"transporation on an unprecendented scale, in ways that no other company can.<br><br>" + "transporation on an unprecendented scale, in ways that no other company can.<br><br>" +
"In our labs and factories and on the ground with customers, MegaCorp is ushering in a new era for the world.", "In our labs and factories and on the ground with customers, MegaCorp is ushering in a new era for the world.",
BachmanAndAssociatesInfo: "Where Law and Business meet - thats where we are. <br><br>" + BachmanAndAssociatesInfo: "Where Law and Business meet - thats where we are. <br><br>" +
"Legal Insight - Business Instinct - Experience Innovation", "Legal Insight - Business Instinct - Experience Innovation",
BladeIndustriesInfo: "Augmentation is salvation", BladeIndustriesInfo: "Augmentation is salvation",
NWOInfo: "The human being created civilization not because of willingness but of a need to be assimilated into higher orders of structure and meaning.", NWOInfo: "The human being created civilization not because of willingness but of a need to be assimilated into higher orders of structure and meaning.",
ClarkeIncorporatedInfo: "Unlocking the power of the genome", ClarkeIncorporatedInfo: "Unlocking the power of the genome",
OmniTekIncorporatedInfo: "Simply put, our mission is to design and build robots that make a difference", OmniTekIncorporatedInfo: "Simply put, our mission is to design and build robots that make a difference",
FourSigmaInfo: "The scientific method is the best way to approach investing. Big strategies backed up with big data. Driven by " + FourSigmaInfo: "The scientific method is the best way to approach investing. Big strategies backed up with big data. Driven by " +
"deep learning and innovative ideas. And improved by iteration. That's Four Sigma.", "deep learning and innovative ideas. And improved by iteration. That's Four Sigma.",
KuaiGongInternationalInfo: "Dream big. Work hard. Make history.", KuaiGongInternationalInfo: "Dream big. Work hard. Make history.",
//Other Corporations //Other Corporations
FulcrumSecretTechnologiesInfo: "TODO", FulcrumSecretTechnologiesInfo: "TODO",
//Hacker groups //Hacker groups
BitRunnersInfo: "Our entire lives are controlled by bits. All of our actions, our thoughts, our personal information. "+ BitRunnersInfo: "Our entire lives are controlled by bits. All of our actions, our thoughts, our personal information. "+
"It's all transformed into bits, stored in bits, communicated through bits. Its impossible for any person " + "It's all transformed into bits, stored in bits, communicated through bits. Its impossible for any person " +
@ -47,14 +47,14 @@ FactionInfo = {
"And when a person moves, lives, and operates, they leave behind their bits, mere traces of seemingly " + "And when a person moves, lives, and operates, they leave behind their bits, mere traces of seemingly " +
"meaningless fragments of information. But these bits can be reconstructed. Transformed. Used.<br><br>" + "meaningless fragments of information. But these bits can be reconstructed. Transformed. Used.<br><br>" +
"Those who run the bits, run the world", "Those who run the bits, run the world",
BlackHandInfo: "The world, so afraid of strong government, now has no government. Only power - Digital power. Financial power. " + BlackHandInfo: "The world, so afraid of strong government, now has no government. Only power - Digital power. Financial power. " +
"Technological power. " + "Technological power. " +
"And those at the top rule with an invisible hand. They built a society where the rich get richer, " + "And those at the top rule with an invisible hand. They built a society where the rich get richer, " +
"and everyone else suffers.<br><br>" + "and everyone else suffers.<br><br>" +
"So much pain. So many lives. Their darkness must end.", "So much pain. So many lives. Their darkness must end.",
NiteSecInfo: NiteSecInfo:
" __..__ <br>" + " __..__ <br>" +
" _.nITESECNIt. <br>" + " _.nITESECNIt. <br>" +
@ -91,7 +91,7 @@ FactionInfo = {
" d .dNITESEC $ | <br>" + " d .dNITESEC $ | <br>" +
" :bp.__.gNITESEC$$ :$ ; <br>" + " :bp.__.gNITESEC$$ :$ ; <br>" +
" NITESECNITESECNIT $$b : <br>", " NITESECNITESECNIT $$b : <br>",
//City factions, essentially governments //City factions, essentially governments
ChongqingInfo: "Serve the people", ChongqingInfo: "Serve the people",
Sector12Info: "The City of the Future", Sector12Info: "The City of the Future",
@ -99,32 +99,34 @@ FactionInfo = {
AevumInfo: "The Silicon City", AevumInfo: "The Silicon City",
IshimaInfo: "The East Asian Order of the Future", IshimaInfo: "The East Asian Order of the Future",
VolhavenInfo: "Benefit, Honour, and Glory", VolhavenInfo: "Benefit, Honour, and Glory",
//Criminal Organizations/Gangs //Criminal Organizations/Gangs
SpeakersForTheDeadInfo: "It is better to reign in hell than to serve in heaven.", SpeakersForTheDeadInfo: "It is better to reign in hell than to serve in heaven.",
DarkArmyInfo: "The World doesn't care about right or wrong. It's all about power.", DarkArmyInfo: "The World doesn't care about right or wrong. It's all about power.",
TheSyndicateInfo: "Honor holds you back", TheSyndicateInfo: "Honor holds you back",
SilhouetteInfo: "Corporations have filled the void of power left behind by the collapse of Western government. The issue is they've become so big " + SilhouetteInfo: "Corporations have filled the void of power left behind by the collapse of Western government. The issue is they've become so big " +
"that you don't know who they're working for. And if you're employed at one of these corporations, you don't even know who you're working " + "that you don't know who they're working for. And if you're employed at one of these corporations, you don't even know who you're working " +
"for. <br><br>" + "for. <br><br>" +
"That's terror. Terror, fear, and corruption. All born into the system, all propagated by the system.", "That's terror. Terror, fear, and corruption. All born into the system, all propagated by the system.",
TetradsInfo: "Following the Mandate of Heaven and Carrying out the Way", TetradsInfo: "Following the Mandate of Heaven and Carrying out the Way",
SlumSnakesInfo: "Slum Snakes rule!", SlumSnakesInfo: "Slum Snakes rule!",
//Earlygame factions - factions the player will prestige with early on that don't //Earlygame factions - factions the player will prestige with early on that don't
//belong in other categories //belong in other categories
NetburnersInfo: "~~//*>H4CK|\|3T 8URN3R5**>?>\\~~", NetburnersInfo: "~~//*>H4CK|\|3T 8URN3R5**>?>\\~~",
TianDiHuiInfo: "Obey Heaven and Work Righteousness", TianDiHuiInfo: "Obey Heaven and Work Righteousness",
CyberSecInfo: "The Internet is the first thing that humanity has built that humanity doesnt understand, " + CyberSecInfo: "The Internet is the first thing that humanity has built that humanity doesnt understand, " +
"the largest experiment in anarchy that we have ever had. And as the world becomes increasingly " + "the largest experiment in anarchy that we have ever had. And as the world becomes increasingly " +
"dominated by the internet, society approaches the brink of total chaos. " + "dominated by the internet, society approaches the brink of total chaos. " +
"We serve only to protect society, to protect humanity, to protect the world from its imminent collapse.", "We serve only to protect society, to protect humanity, to protect the world from its imminent collapse.",
} }
export {FactionInfo};

@ -1,3 +1,20 @@
import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js";
import {Faction, Factions} from "./Faction.js";
import {Locations} from "./Location.js";
import {Player} from "./Player.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js";
import {getRandomInt} from "../utils/HelperFunctions.js";
import numeral from "../utils/numeral.min.js";
import {formatNumber} from "../utils/StringHelperFunctions.js";
import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
yesNoBoxGetYesButton, yesNoBoxGetNoButton,
yesNoTxtInpBoxGetYesButton, yesNoTxtInpBoxGetNoButton,
yesNoTxtInpBoxGetInput, yesNoBoxClose,
yesNoTxtInpBoxClose, yesNoBoxOpen} from "../utils/YesNoBox.js";
/* Gang.js */ /* Gang.js */
//Switch between territory and management screen with 1 and 2 //Switch between territory and management screen with 1 and 2
$(document).keydown(function(event) { $(document).keydown(function(event) {
@ -29,11 +46,11 @@ $(document).mousedown(function(event) {
} }
}); });
GangNames = ["Slum Snakes", "Tetrads", "The Syndicate", "The Dark Army", "Speakers for the Dead", let GangNames = ["Slum Snakes", "Tetrads", "The Syndicate", "The Dark Army", "Speakers for the Dead",
"NiteSec", "The Black Hand"]; "NiteSec", "The Black Hand"];
GangLocations = [Locations.Aevum, Locations.Chongqing, Locations.Sector12, Locations.NewTokyo, let GangLocations = [Locations.Aevum, Locations.Chongqing, Locations.Sector12, Locations.NewTokyo,
Locations.Ishima, Locations.Volhaven]; Locations.Ishima, Locations.Volhaven];
AllGangs = { let AllGangs = {
"Slum Snakes" : { "Slum Snakes" : {
power: 1, power: 1,
territory: 1/7, territory: 1/7,
@ -64,8 +81,12 @@ AllGangs = {
}, },
} }
function loadAllGangs(saveString) {
AllGangs = JSON.parse(saveString, Reviver);
}
//Power is an estimate of a gang's ability to gain/defend territory //Power is an estimate of a gang's ability to gain/defend territory
gangStoredPowerCycles = 0; let gangStoredPowerCycles = 0;
function processAllGangPowerGains(numCycles=1) { function processAllGangPowerGains(numCycles=1) {
if (!Player.inGang()) {return;} if (!Player.inGang()) {return;}
gangStoredPowerCycles += numCycles; gangStoredPowerCycles += numCycles;
@ -85,7 +106,7 @@ function processAllGangPowerGains(numCycles=1) {
gangStoredPowerCycles -= 150; gangStoredPowerCycles -= 150;
} }
gangStoredTerritoryCycles = 0; let gangStoredTerritoryCycles = 0;
function processAllGangTerritory(numCycles=1) { function processAllGangTerritory(numCycles=1) {
if (!Player.inGang()) {return;} if (!Player.inGang()) {return;}
gangStoredTerritoryCycles += numCycles; gangStoredTerritoryCycles += numCycles;
@ -118,12 +139,6 @@ function processAllGangTerritory(numCycles=1) {
gangStoredTerritoryCycles -= CONSTANTS.GangTerritoryUpdateTimer; gangStoredTerritoryCycles -= CONSTANTS.GangTerritoryUpdateTimer;
} }
//Returns true if Player is in a gang and false otherwise
PlayerObject.prototype.inGang = function() {
if (this.gang == null || this.gang == undefined) {return false;}
return (this.gang instanceof Gang);
}
/* faction - Name of corresponding faction /* faction - Name of corresponding faction
hacking - Boolean indicating whether its a hacking gang or not hacking - Boolean indicating whether its a hacking gang or not
*/ */
@ -230,7 +245,6 @@ Gang.fromJSON = function(value) {
Reviver.constructors.Gang = Gang; Reviver.constructors.Gang = Gang;
/*** Gang Member object ***/ /*** Gang Member object ***/
function GangMember(name) { function GangMember(name) {
this.name = name; this.name = name;
@ -405,7 +419,7 @@ GangMemberTask.fromJSON = function(value) {
Reviver.constructors.GangMemberTask = GangMemberTask; Reviver.constructors.GangMemberTask = GangMemberTask;
//TODO Human trafficking and an equivalent hacking crime //TODO Human trafficking and an equivalent hacking crime
GangMemberTasks = { let GangMemberTasks = {
"Ransomware" : new GangMemberTask( "Ransomware" : new GangMemberTask(
"Ransomware", "Ransomware",
"Assign this gang member to create and distribute ransomware<br><br>" + "Assign this gang member to create and distribute ransomware<br><br>" +
@ -674,7 +688,7 @@ GangMemberUpgrade.fromJSON = function(value) {
Reviver.constructors.GangMemberUpgrade = GangMemberUpgrade; Reviver.constructors.GangMemberUpgrade = GangMemberUpgrade;
GangMemberUpgrades = { let GangMemberUpgrades = {
"Baseball Bat" : new GangMemberUpgrade("Baseball Bat", "Baseball Bat" : new GangMemberUpgrade("Baseball Bat",
"Increases strength and defense by 10%", 1000000, "w"), "Increases strength and defense by 10%", 1000000, "w"),
"Katana" : new GangMemberUpgrade("Katana", "Katana" : new GangMemberUpgrade("Katana",
@ -716,7 +730,7 @@ GangMemberUpgrades = {
} }
//Create a pop-up box that lets player purchase upgrades //Create a pop-up box that lets player purchase upgrades
var gangMemberUpgradeBoxOpened = false; let gangMemberUpgradeBoxOpened = false;
function createGangMemberUpgradeBox(memberObj) { function createGangMemberUpgradeBox(memberObj) {
console.log("Creating gang member upgrade box for " + memberObj.name); console.log("Creating gang member upgrade box for " + memberObj.name);
var container = document.getElementById("gang-purchase-upgrade-container"); var container = document.getElementById("gang-purchase-upgrade-container");
@ -838,7 +852,7 @@ function createGangMemberUpgradeButtons(memberObj, upgNames, memberUpgrade, cont
} }
} }
var gangContentCreated = false; let gangContentCreated = false;
function displayGangContent() { function displayGangContent() {
if (!gangContentCreated) { if (!gangContentCreated) {
gangContentCreated = true; gangContentCreated = true;
@ -1084,7 +1098,7 @@ function setGangMemberClickHandlers() {
console.log("ERROR: Could not find Active Scripts server panels"); console.log("ERROR: Could not find Active Scripts server panels");
return; return;
} }
for (i = 0; i < gangMemberHdrs.length; ++i) { for (let i = 0; i < gangMemberHdrs.length; ++i) {
gangMemberHdrs[i].onclick = function() { gangMemberHdrs[i].onclick = function() {
this.classList.toggle("active"); this.classList.toggle("active");
@ -1168,7 +1182,7 @@ function createGangMemberDisplayElement(memberObj) {
if (memberObj.task instanceof GangMemberTask) { if (memberObj.task instanceof GangMemberTask) {
var taskName = memberObj.task.name; var taskName = memberObj.task.name;
var taskIndex = 0; var taskIndex = 0;
for (i = 0; i < tasks.length; ++i) { for (let i = 0; i < tasks.length; ++i) {
if (taskName == tasks[i]) { if (taskName == tasks[i]) {
taskIndex = i; taskIndex = i;
break; break;
@ -1247,3 +1261,5 @@ function setGangMemberTaskDescription(memberObj, taskName) {
taskDesc.innerHTML = desc; taskDesc.innerHTML = desc;
} }
} }
export {Gang, displayGangContent, updateGangContent, loadAllGangs, AllGangs};

@ -1,3 +1,15 @@
import {BitNodeMultipliers} from "./BitNode.js";
import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js";
import {iTutorialSteps, iTutorialNextStep,
iTutorialIsRunning, currITutorialStep} from "./InteractiveTutorial.js";
import {Player} from "./Player.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {clearEventListeners} from "../utils/HelperFunctions.js";
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js";
import {formatNumber} from "../utils/StringHelperFunctions.js";
/* HacknetNode.js */ /* HacknetNode.js */
function hacknetNodesInit() { function hacknetNodesInit() {
var mult1x = document.getElementById("hacknet-nodes-1x-multiplier"); var mult1x = document.getElementById("hacknet-nodes-1x-multiplier");
@ -50,7 +62,9 @@ HacknetNode.prototype.updateMoneyGainRate = function() {
this.moneyGainRatePerSecond = (this.level * gainPerLevel) * this.moneyGainRatePerSecond = (this.level * gainPerLevel) *
Math.pow(1.035, this.ram-1) * Math.pow(1.035, this.ram-1) *
((this.cores + 5) / 6) * Player.hacknet_node_money_mult; ((this.cores + 5) / 6) *
Player.hacknet_node_money_mult *
BitNodeMultipliers.HacknetNodeMoney;
if (isNaN(this.moneyGainRatePerSecond)) { if (isNaN(this.moneyGainRatePerSecond)) {
this.moneyGainRatePerSecond = 0; this.moneyGainRatePerSecond = 0;
dialogBoxCreate("Error in calculating Hacknet Node production. Please report to game developer"); dialogBoxCreate("Error in calculating Hacknet Node production. Please report to game developer");
@ -165,7 +179,7 @@ HacknetNode.fromJSON = function(value) {
Reviver.constructors.HacknetNode = HacknetNode; Reviver.constructors.HacknetNode = HacknetNode;
purchaseHacknet = function() { function purchaseHacknet() {
/* INTERACTIVE TUTORIAL */ /* INTERACTIVE TUTORIAL */
if (iTutorialIsRunning) { if (iTutorialIsRunning) {
if (currITutorialStep == iTutorialSteps.HacknetNodesIntroduction) { if (currITutorialStep == iTutorialSteps.HacknetNodesIntroduction) {
@ -199,7 +213,7 @@ purchaseHacknet = function() {
} }
//Calculates the total production from all HacknetNodes //Calculates the total production from all HacknetNodes
updateTotalHacknetProduction = function() { function updateTotalHacknetProduction() {
var total = 0; var total = 0;
for (var i = 0; i < Player.hacknetNodes.length; ++i) { for (var i = 0; i < Player.hacknetNodes.length; ++i) {
total += Player.hacknetNodes[i].moneyGainRatePerSecond; total += Player.hacknetNodes[i].moneyGainRatePerSecond;
@ -207,7 +221,7 @@ updateTotalHacknetProduction = function() {
Player.totalHacknetNodeProduction = total; Player.totalHacknetNodeProduction = total;
} }
getCostOfNextHacknetNode = function() { function getCostOfNextHacknetNode() {
//Cost increases exponentially based on how many you own //Cost increases exponentially based on how many you own
var numOwned = Player.hacknetNodes.length; var numOwned = Player.hacknetNodes.length;
var mult = CONSTANTS.HacknetNodePurchaseNextMult; var mult = CONSTANTS.HacknetNodePurchaseNextMult;
@ -215,7 +229,7 @@ getCostOfNextHacknetNode = function() {
} }
var hacknetNodePurchaseMultiplier = 1; var hacknetNodePurchaseMultiplier = 1;
updateHacknetNodesMultiplierButtons = function() { function updateHacknetNodesMultiplierButtons() {
var mult1x = document.getElementById("hacknet-nodes-1x-multiplier"); var mult1x = document.getElementById("hacknet-nodes-1x-multiplier");
var mult5x = document.getElementById("hacknet-nodes-5x-multiplier"); var mult5x = document.getElementById("hacknet-nodes-5x-multiplier");
var mult10x = document.getElementById("hacknet-nodes-10x-multiplier"); var mult10x = document.getElementById("hacknet-nodes-10x-multiplier");
@ -242,7 +256,7 @@ updateHacknetNodesMultiplierButtons = function() {
//Calculate the maximum number of times the Player can afford to upgrade //Calculate the maximum number of times the Player can afford to upgrade
//a Hacknet Node's level" //a Hacknet Node's level"
getMaxNumberLevelUpgrades = function(nodeObj) { function getMaxNumberLevelUpgrades(nodeObj) {
if (Player.money.lt(nodeObj.calculateLevelUpgradeCost(1))) {return 0;} if (Player.money.lt(nodeObj.calculateLevelUpgradeCost(1))) {return 0;}
var min = 1; var min = 1;
var max = CONSTANTS.HacknetNodeMaxLevel-1; var max = CONSTANTS.HacknetNodeMaxLevel-1;
@ -268,7 +282,7 @@ getMaxNumberLevelUpgrades = function(nodeObj) {
} }
//Creates Hacknet Node DOM elements when the page is opened //Creates Hacknet Node DOM elements when the page is opened
displayHacknetNodesContent = function() { function displayHacknetNodesContent() {
//Update Hacknet Nodes button //Update Hacknet Nodes button
var newPurchaseButton = clearEventListeners("hacknet-nodes-purchase-button"); var newPurchaseButton = clearEventListeners("hacknet-nodes-purchase-button");
@ -294,7 +308,7 @@ displayHacknetNodesContent = function() {
} }
//Update information on all Hacknet Node DOM elements //Update information on all Hacknet Node DOM elements
updateHacknetNodesContent = function() { function updateHacknetNodesContent() {
//Set purchase button to inactive if not enough money, and update its price display //Set purchase button to inactive if not enough money, and update its price display
var cost = getCostOfNextHacknetNode(); var cost = getCostOfNextHacknetNode();
var purchaseButton = document.getElementById("hacknet-nodes-purchase-button"); var purchaseButton = document.getElementById("hacknet-nodes-purchase-button");
@ -317,7 +331,7 @@ updateHacknetNodesContent = function() {
} }
//Creates a single Hacknet Node DOM element //Creates a single Hacknet Node DOM element
createHacknetNodeDomElement = function(nodeObj) { function createHacknetNodeDomElement(nodeObj) {
var nodeName = nodeObj.name; var nodeName = nodeObj.name;
var listItem = document.createElement("li"); var listItem = document.createElement("li");
@ -383,7 +397,7 @@ createHacknetNodeDomElement = function(nodeObj) {
} }
//Updates information on a single hacknet node DOM element //Updates information on a single hacknet node DOM element
updateHacknetNodeDomElement = function(nodeObj) { function updateHacknetNodeDomElement(nodeObj) {
var nodeName = nodeObj.name; var nodeName = nodeObj.name;
var txt = document.getElementById("hacknet-node-text-" + nodeName); var txt = document.getElementById("hacknet-node-text-" + nodeName);
if (txt == null) {throw new Error("Cannot find text element");} if (txt == null) {throw new Error("Cannot find text element");}
@ -453,7 +467,7 @@ updateHacknetNodeDomElement = function(nodeObj) {
} }
} }
processAllHacknetNodeEarnings = function(numCycles) { function processAllHacknetNodeEarnings(numCycles) {
var total = 0; var total = 0;
for (var i = 0; i < Player.hacknetNodes.length; ++i) { for (var i = 0; i < Player.hacknetNodes.length; ++i) {
total += processSingleHacknetNodeEarnings(numCycles, Player.hacknetNodes[i]); total += processSingleHacknetNodeEarnings(numCycles, Player.hacknetNodes[i]);
@ -461,7 +475,7 @@ processAllHacknetNodeEarnings = function(numCycles) {
return total; return total;
} }
processSingleHacknetNodeEarnings = function(numCycles, nodeObj) { function processSingleHacknetNodeEarnings(numCycles, nodeObj) {
var cyclesPerSecond = 1000 / Engine._idleSpeed; var cyclesPerSecond = 1000 / Engine._idleSpeed;
var earningPerCycle = nodeObj.moneyGainRatePerSecond / cyclesPerSecond; var earningPerCycle = nodeObj.moneyGainRatePerSecond / cyclesPerSecond;
if (isNaN(earningPerCycle)) {throw new Error("Calculated Earnings is not a number");} if (isNaN(earningPerCycle)) {throw new Error("Calculated Earnings is not a number");}
@ -472,7 +486,7 @@ processSingleHacknetNodeEarnings = function(numCycles, nodeObj) {
return totalEarnings; return totalEarnings;
} }
getHacknetNode = function(name) { function getHacknetNode(name) {
for (var i = 0; i < Player.hacknetNodes.length; ++i) { for (var i = 0; i < Player.hacknetNodes.length; ++i) {
if (Player.hacknetNodes[i].name == name) { if (Player.hacknetNodes[i].name == name) {
return Player.hacknetNodes[i]; return Player.hacknetNodes[i];
@ -480,3 +494,8 @@ getHacknetNode = function(name) {
} }
return null; return null;
} }
export {hacknetNodesInit, HacknetNode, purchaseHacknet, updateTotalHacknetProduction,
getCostOfNextHacknetNode, updateHacknetNodesMultiplierButtons, getMaxNumberLevelUpgrades,
displayHacknetNodesContent, updateHacknetNodesContent, processAllHacknetNodeEarnings,
getHacknetNode};

@ -1,8 +1,9 @@
/* HelpText.js */ /* HelpText.js */
TerminalHelpText = let TerminalHelpText =
"Type 'help name' to learn more about the command 'name'<br><br>" + "Type 'help name' to learn more about the command 'name'<br><br>" +
'alias [-g] [name="value"] Create or display Terminal aliases<br>' + 'alias [-g] [name="value"] Create or display Terminal aliases<br>' +
"analyze Get information about the current machine <br>" + "analyze Get information about the current machine <br>" +
"buy [-l/program] Purchase a program through the Dark Web<br>" +
"cat [file] Display a .msg or .lit file<br>" + "cat [file] Display a .msg or .lit file<br>" +
"check [script] [args...] Print a script's logs to Terminal<br>" + "check [script] [args...] Print a script's logs to Terminal<br>" +
"clear Clear all text on the terminal <br>" + "clear Clear all text on the terminal <br>" +
@ -31,7 +32,7 @@ TerminalHelpText =
"top Displays all running scripts and their RAM usage<br>" + "top Displays all running scripts and their RAM usage<br>" +
'unalias "[alias name]" Deletes the specified alias<br>'; 'unalias "[alias name]" Deletes the specified alias<br>';
HelpTexts = { let HelpTexts = {
alias: 'alias [-g] [name="value"] <br>' + alias: 'alias [-g] [name="value"] <br>' +
"Create or display aliases. An alias enables a replacement of a word with another string. " + "Create or display aliases. An alias enables a replacement of a word with another string. " +
"It can be used to abbreviate a commonly used command, or commonly used parts of a command. The NAME " + "It can be used to abbreviate a commonly used command, or commonly used parts of a command. The NAME " +
@ -56,6 +57,11 @@ HelpTexts = {
"server details such as the hostname, whether the player has root access, what ports are opened/closed, and also " + "server details such as the hostname, whether the player has root access, what ports are opened/closed, and also " +
"hacking-related information such as an estimated chance to successfully hack, an estimate of how much money is " + "hacking-related information such as an estimated chance to successfully hack, an estimate of how much money is " +
"available on the server, etc.", "available on the server, etc.",
buy: "buy [-l / program]<br>" +
"Purchase a program through the Dark Web. Requires a TOR router to use.<br><br>" +
"If this command is ran with the '-l' flag, it will display a list of all programs that can be bought through the " +
"dark web to the Terminal, as well as their costs.<br><br>" +
"Otherwise, the name of the program must be passed in as a parameter. This is name is NOT case-sensitive.",
cat: "cat [file]<br>" + cat: "cat [file]<br>" +
"Display message files, which are files ending with the '.msg' extension, or a literature file, which " + "Display message files, which are files ending with the '.msg' extension, or a literature file, which " +
"are files ending with the '.lit' extension. Examples:<br><br>" + "are files ending with the '.lit' extension. Examples:<br><br>" +
@ -159,7 +165,7 @@ HelpTexts = {
"it has", "it has",
scp: "scp [filename] [target server]<br>" + scp: "scp [filename] [target server]<br>" +
"Copies the specified file from the current server to the target server. " + "Copies the specified file from the current server to the target server. " +
"This command only works for script files (.script extension) and literature files (.lit extension). " + "This command only works for script files (.script extension) and literature files (.lit extension). " +
"The second argument passed in must be the hostname or IP of the target server.", "The second argument passed in must be the hostname or IP of the target server.",
sudov: "sudov<br>" + sudov: "sudov<br>" +
"Prints whether or not you have root access to the current machine", "Prints whether or not you have root access to the current machine",
@ -193,3 +199,5 @@ HelpTexts = {
"It is not necessary to differentiate between global and non-global aliases when using 'unalias'", "It is not necessary to differentiate between global and non-global aliases when using 'unalias'",
} }
export {TerminalHelpText, HelpTexts};

@ -1,3 +1,11 @@
import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js";
import {Player} from "./Player.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {clearEventListeners, getRandomInt} from "../utils/HelperFunctions.js";
import {infiltrationBoxCreate} from "../utils/InfiltrationBox.js";
import {formatNumber} from "../utils/StringHelperFunctions.js";
/* Infiltration.js /* Infiltration.js
* *
* Kill * Kill
@ -16,7 +24,7 @@
* Escape * Escape
*/ */
InfiltrationScenarios = { let InfiltrationScenarios = {
Guards: "You see an armed security guard patrolling the area.", Guards: "You see an armed security guard patrolling the area.",
TechOnly: "The area is equipped with a state-of-the-art security system: cameras, laser tripwires, and sentry turrets.", TechOnly: "The area is equipped with a state-of-the-art security system: cameras, laser tripwires, and sentry turrets.",
TechOrLockedDoor: "The area is equipped with a state-of-the-art security system. There is a locked door on the side of the " + TechOrLockedDoor: "The area is equipped with a state-of-the-art security system. There is a locked door on the side of the " +
@ -71,8 +79,6 @@ InfiltrationInstance.prototype.gainCharismaExp = function(amt) {
this.chaExpGained += amt; this.chaExpGained += amt;
} }
function beginInfiltration(companyName, startLevel, val, maxClearance, diff) { function beginInfiltration(companyName, startLevel, val, maxClearance, diff) {
var inst = new InfiltrationInstance(companyName, startLevel, val, maxClearance, diff); var inst = new InfiltrationInstance(companyName, startLevel, val, maxClearance, diff);
clearInfiltrationStatusText(); clearInfiltrationStatusText();
@ -796,3 +802,5 @@ function getInfiltrationEscapeChance(inst) {
(2 * Player.agility + (2 * Player.agility +
Player.dexterity) / lvl); Player.dexterity) / lvl);
} }
export {beginInfiltration};

@ -1,5 +1,9 @@
import {Engine} from "./engine.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {clearEventListeners} from "../utils/HelperFunctions.js";
/* InteractiveTutorial.js */ /* InteractiveTutorial.js */
iTutorialSteps = { let iTutorialSteps = {
Start: "Start", Start: "Start",
GoToCharacterPage: "Click on the Character page menu link", GoToCharacterPage: "Click on the Character page menu link",
CharacterPage: "Introduction to Character page", CharacterPage: "Introduction to Character page",
@ -652,3 +656,6 @@ function iTutorialSetText(txt) {
textBox.innerHTML = txt; textBox.innerHTML = txt;
textBox.parentElement.scrollTop = 0; // this resets scroll position textBox.parentElement.scrollTop = 0; // this resets scroll position
} }
export {iTutorialSteps, iTutorialEnd, iTutorialStart, iTutorialNextStep, currITutorialStep,
iTutorialIsRunning};

@ -1,3 +1,5 @@
import {dialogBoxCreate} from "../utils/DialogBox.js";
/* Literature.js /* Literature.js
* Lore / world building literature that can be found on servers * Lore / world building literature that can be found on servers
*/ */
@ -15,7 +17,7 @@ function showLiterature(fn) {
dialogBoxCreate(txt); dialogBoxCreate(txt);
} }
Literatures = {} let Literatures = {}
function initLiterature() { function initLiterature() {
var title, fn, txt; var title, fn, txt;
@ -125,7 +127,7 @@ function initLiterature() {
"Soon the cries rose everywhere, with revolt and riot<br>Until one day, finally, all was quiet<br>" + "Soon the cries rose everywhere, with revolt and riot<br>Until one day, finally, all was quiet<br>" +
"From the ashes rose a new order, corporatocracy was its name<br>" + "From the ashes rose a new order, corporatocracy was its name<br>" +
"Rome, Mongol, Byzantine, all of history is just the same<br>" + "Rome, Mongol, Byzantine, all of history is just the same<br>" +
"For man will never change in a fundamental way<br>" "For man will never change in a fundamental way<br>" +
"And now democracy is dead, in the USA"; "And now democracy is dead, in the USA";
Literatures[fn] = new Literature(title, fn, txt); Literatures[fn] = new Literature(title, fn, txt);
@ -265,7 +267,7 @@ function initLiterature() {
title = "The Hidden World"; title = "The Hidden World";
fn = "the-hidden-world.lit"; fn = "the-hidden-world.lit";
txt = "WAKE UP SHEEPLE<br><br>" txt = "WAKE UP SHEEPLE<br><br>" +
"THE GOVERNMENT DOES NOT EXIST. CORPORATIONS DO NOT RUN SOCIETY<br><br>" + "THE GOVERNMENT DOES NOT EXIST. CORPORATIONS DO NOT RUN SOCIETY<br><br>" +
"THE ILLUMINATI ARE THE SECRET RULERS OF THE WORLD!<br><br>" + "THE ILLUMINATI ARE THE SECRET RULERS OF THE WORLD!<br><br>" +
"Yes, the Illuminati of legends. The ancient secret society that controls the entire " + "Yes, the Illuminati of legends. The ancient secret society that controls the entire " +
@ -317,3 +319,5 @@ function initLiterature() {
txt = "" txt = ""
Literatures[fn] = new Literature(title, fn, txt); Literatures[fn] = new Literature(title, fn, txt);
} }
export {Literatures, initLiterature, showLiterature};

@ -1,7 +1,36 @@
import {CompanyPositions, initCompanies,
Companies, getJobRequirementText} from "./Company.js";
import {CONSTANTS} from "./Constants.js";
import {commitShopliftCrime, commitRobStoreCrime, commitMugCrime,
commitLarcenyCrime, commitDealDrugsCrime, commitTraffickArmsCrime,
commitHomicideCrime, commitGrandTheftAutoCrime, commitKidnapCrime,
commitAssassinationCrime, commitHeistCrime, determineCrimeSuccess,
determineCrimeChanceShoplift, determineCrimeChanceRobStore,
determineCrimeChanceMug, determineCrimeChanceLarceny,
determineCrimeChanceDealDrugs, determineCrimeChanceTraffickArms,
determineCrimeChanceHomicide, determineCrimeChanceGrandTheftAuto,
determineCrimeChanceKidnap, determineCrimeChanceAssassination,
determineCrimeChanceHeist} from "./Crimes.js";
import {Engine} from "./engine.js";
import {beginInfiltration} from "./Infiltration.js";
import {Player} from "./Player.js";
import {Server, AllServers, AddToAllServers} from "./Server.js";
import {purchaseServer,
purchaseRamForHomeComputer} from "./ServerPurchases.js";
import {SpecialServerNames, SpecialServerIps} from "./SpecialServerIps.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {clearEventListeners} from "../utils/HelperFunctions.js";
import {createRandomIp} from "../utils/IPAddress.js";
import {formatNumber} from "../utils/StringHelperFunctions.js";
import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
yesNoBoxGetYesButton, yesNoBoxGetNoButton,
yesNoTxtInpBoxGetYesButton, yesNoTxtInpBoxGetNoButton,
yesNoTxtInpBoxGetInput, yesNoBoxClose,
yesNoTxtInpBoxClose} from "../utils/YesNoBox.js";
/* Display Location Content when visiting somewhere in the World*/ /* Display Location Content when visiting somewhere in the World*/
let Locations = {
Locations = {
//Cities //Cities
Aevum: "Aevum", Aevum: "Aevum",
//AevumDesc: "" //AevumDesc: ""
@ -86,7 +115,7 @@ Locations = {
WorldStockExchange: "World Stock Exchange", WorldStockExchange: "World Stock Exchange",
} }
displayLocationContent = function() { function displayLocationContent() {
if (Engine.debug) { if (Engine.debug) {
console.log("displayLocationContent() called with location " + Player.location) console.log("displayLocationContent() called with location " + Player.location)
} }
@ -1058,458 +1087,457 @@ displayLocationContent = function() {
} }
} }
initLocationButtons = function() { function initLocationButtons() {
//Buttons to travel to different locations in World //Buttons to travel to different locations in World
aevumTravelAgency = document.getElementById("aevum-travelagency"); let aevumTravelAgency = document.getElementById("aevum-travelagency");
aevumTravelAgency.addEventListener("click", function() { aevumTravelAgency.addEventListener("click", function() {
Player.location = Locations.AevumTravelAgency; Player.location = Locations.AevumTravelAgency;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumHospital = document.getElementById("aevum-hospital"); let aevumHospital = document.getElementById("aevum-hospital");
aevumHospital.addEventListener("click", function() { aevumHospital.addEventListener("click", function() {
Player.location = Locations.Hospital; Player.location = Locations.Hospital;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumSummitUniversity = document.getElementById("aevum-summituniversity"); let aevumSummitUniversity = document.getElementById("aevum-summituniversity");
aevumSummitUniversity.addEventListener("click", function() { aevumSummitUniversity.addEventListener("click", function() {
Player.location = Locations.AevumSummitUniversity; Player.location = Locations.AevumSummitUniversity;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumECorp = document.getElementById("aevum-ecorp"); let aevumECorp = document.getElementById("aevum-ecorp");
aevumECorp.addEventListener("click", function() { aevumECorp.addEventListener("click", function() {
Player.location = Locations.AevumECorp; Player.location = Locations.AevumECorp;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumBachmanAndAssociates = document.getElementById("aevum-bachmanandassociates"); let aevumBachmanAndAssociates = document.getElementById("aevum-bachmanandassociates");
aevumBachmanAndAssociates.addEventListener("click", function() { aevumBachmanAndAssociates.addEventListener("click", function() {
Player.location = Locations.AevumBachmanAndAssociates; Player.location = Locations.AevumBachmanAndAssociates;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumClarkeIncorporated = document.getElementById("aevum-clarkeincorporated"); let aevumClarkeIncorporated = document.getElementById("aevum-clarkeincorporated");
aevumClarkeIncorporated.addEventListener("click", function() { aevumClarkeIncorporated.addEventListener("click", function() {
Player.location = Locations.AevumClarkeIncorporated; Player.location = Locations.AevumClarkeIncorporated;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumFulcrumTechnologies = document.getElementById("aevum-fulcrumtechnologies"); let aevumFulcrumTechnologies = document.getElementById("aevum-fulcrumtechnologies");
aevumFulcrumTechnologies.addEventListener("click", function() { aevumFulcrumTechnologies.addEventListener("click", function() {
Player.location = Locations.AevumFulcrumTechnologies; Player.location = Locations.AevumFulcrumTechnologies;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumAeroCorp = document.getElementById("aevum-aerocorp"); let aevumAeroCorp = document.getElementById("aevum-aerocorp");
aevumAeroCorp.addEventListener("click", function() { aevumAeroCorp.addEventListener("click", function() {
Player.location = Locations.AevumAeroCorp; Player.location = Locations.AevumAeroCorp;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumGalacticCybersystems = document.getElementById("aevum-galacticcybersystems"); let aevumGalacticCybersystems = document.getElementById("aevum-galacticcybersystems");
aevumGalacticCybersystems.addEventListener("click", function() { aevumGalacticCybersystems.addEventListener("click", function() {
Player.location = Locations.AevumGalacticCybersystems; Player.location = Locations.AevumGalacticCybersystems;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumWatchdogSecurity = document.getElementById("aevum-watchdogsecurity"); let aevumWatchdogSecurity = document.getElementById("aevum-watchdogsecurity");
aevumWatchdogSecurity.addEventListener("click", function() { aevumWatchdogSecurity.addEventListener("click", function() {
Player.location = Locations.AevumWatchdogSecurity; Player.location = Locations.AevumWatchdogSecurity;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumRhoConstruction = document.getElementById("aevum-rhoconstruction"); let aevumRhoConstruction = document.getElementById("aevum-rhoconstruction");
aevumRhoConstruction.addEventListener("click", function() { aevumRhoConstruction.addEventListener("click", function() {
Player.location = Locations.AevumRhoConstruction; Player.location = Locations.AevumRhoConstruction;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumPolice = document.getElementById("aevum-aevumpolice"); let aevumPolice = document.getElementById("aevum-aevumpolice");
aevumPolice.addEventListener("click", function() { aevumPolice.addEventListener("click", function() {
Player.location = Locations.AevumPolice; Player.location = Locations.AevumPolice;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumNetLinkTechnologies = document.getElementById("aevum-netlinktechnologies"); let aevumNetLinkTechnologies = document.getElementById("aevum-netlinktechnologies");
aevumNetLinkTechnologies.addEventListener("click", function() { aevumNetLinkTechnologies.addEventListener("click", function() {
Player.location = Locations.AevumNetLinkTechnologies; Player.location = Locations.AevumNetLinkTechnologies;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumCrushFitnessGym = document.getElementById("aevum-crushfitnessgym"); let aevumCrushFitnessGym = document.getElementById("aevum-crushfitnessgym");
aevumCrushFitnessGym.addEventListener("click", function() { aevumCrushFitnessGym.addEventListener("click", function() {
Player.location = Locations.AevumCrushFitnessGym; Player.location = Locations.AevumCrushFitnessGym;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumSnapFitnessGym = document.getElementById("aevum-snapfitnessgym"); let aevumSnapFitnessGym = document.getElementById("aevum-snapfitnessgym");
aevumSnapFitnessGym.addEventListener("click", function() { aevumSnapFitnessGym.addEventListener("click", function() {
Player.location = Locations.AevumSnapFitnessGym; Player.location = Locations.AevumSnapFitnessGym;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
aevumSlums = document.getElementById("aevum-slums"); let aevumSlums = document.getElementById("aevum-slums");
aevumSlums.addEventListener("click", function() { aevumSlums.addEventListener("click", function() {
Player.location = Locations.AevumSlums; Player.location = Locations.AevumSlums;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
chongqingTravelAgency = document.getElementById("chongqing-travelagency"); let chongqingTravelAgency = document.getElementById("chongqing-travelagency");
chongqingTravelAgency.addEventListener("click", function() { chongqingTravelAgency.addEventListener("click", function() {
Player.location = Locations.ChongqingTravelAgency; Player.location = Locations.ChongqingTravelAgency;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
chongqingHospital = document.getElementById("chongqing-hospital"); let chongqingHospital = document.getElementById("chongqing-hospital");
chongqingHospital.addEventListener("click", function() { chongqingHospital.addEventListener("click", function() {
Player.location = Locations.Hospital; Player.location = Locations.Hospital;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
chongqingKuaiGongInternational = document.getElementById("chongqing-kuaigonginternational"); let chongqingKuaiGongInternational = document.getElementById("chongqing-kuaigonginternational");
chongqingKuaiGongInternational.addEventListener("click", function() { chongqingKuaiGongInternational.addEventListener("click", function() {
Player.location = Locations.ChongqingKuaiGongInternational; Player.location = Locations.ChongqingKuaiGongInternational;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
chongqingSolarisSpaceSystems = document.getElementById("chongqing-solarisspacesystems"); let chongqingSolarisSpaceSystems = document.getElementById("chongqing-solarisspacesystems");
chongqingSolarisSpaceSystems.addEventListener("click", function() { chongqingSolarisSpaceSystems.addEventListener("click", function() {
Player.location = Locations.ChongqingSolarisSpaceSystems; Player.location = Locations.ChongqingSolarisSpaceSystems;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
chongqingSlums = document.getElementById("chongqing-slums"); let chongqingSlums = document.getElementById("chongqing-slums");
chongqingSlums.addEventListener("click", function() { chongqingSlums.addEventListener("click", function() {
Player.location = Locations.ChongqingSlums; Player.location = Locations.ChongqingSlums;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
let sector12TravelAgency = document.getElementById("sector12-travelagency");
sector12TravelAgency = document.getElementById("sector12-travelagency");
sector12TravelAgency.addEventListener("click", function() { sector12TravelAgency.addEventListener("click", function() {
Player.location = Locations.Sector12TravelAgency; Player.location = Locations.Sector12TravelAgency;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12Hospital = document.getElementById("sector12-hospital"); let sector12Hospital = document.getElementById("sector12-hospital");
sector12Hospital.addEventListener("click", function() { sector12Hospital.addEventListener("click", function() {
Player.location = Locations.Hospital; Player.location = Locations.Hospital;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12RothmanUniversity = document.getElementById("sector12-rothmanuniversity"); let sector12RothmanUniversity = document.getElementById("sector12-rothmanuniversity");
sector12RothmanUniversity.addEventListener("click", function() { sector12RothmanUniversity.addEventListener("click", function() {
Player.location = Locations.Sector12RothmanUniversity; Player.location = Locations.Sector12RothmanUniversity;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12MegaCorp = document.getElementById("sector12-megacorp"); let sector12MegaCorp = document.getElementById("sector12-megacorp");
sector12MegaCorp.addEventListener("click", function() { sector12MegaCorp.addEventListener("click", function() {
Player.location = Locations.Sector12MegaCorp; Player.location = Locations.Sector12MegaCorp;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12BladeIndustries = document.getElementById("sector12-bladeindustries"); let sector12BladeIndustries = document.getElementById("sector12-bladeindustries");
sector12BladeIndustries.addEventListener("click", function() { sector12BladeIndustries.addEventListener("click", function() {
Player.location = Locations.Sector12BladeIndustries; Player.location = Locations.Sector12BladeIndustries;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12FourSigma = document.getElementById("sector12-foursigma"); let sector12FourSigma = document.getElementById("sector12-foursigma");
sector12FourSigma.addEventListener("click", function() { sector12FourSigma.addEventListener("click", function() {
Player.location = Locations.Sector12FourSigma; Player.location = Locations.Sector12FourSigma;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12IcarusMicrosystems = document.getElementById("sector12-icarusmicrosystems"); let sector12IcarusMicrosystems = document.getElementById("sector12-icarusmicrosystems");
sector12IcarusMicrosystems.addEventListener("click", function() { sector12IcarusMicrosystems.addEventListener("click", function() {
Player.location = Locations.Sector12IcarusMicrosystems; Player.location = Locations.Sector12IcarusMicrosystems;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12UniversalEnergy = document.getElementById("sector12-universalenergy"); let sector12UniversalEnergy = document.getElementById("sector12-universalenergy");
sector12UniversalEnergy.addEventListener("click", function() { sector12UniversalEnergy.addEventListener("click", function() {
Player.location = Locations.Sector12UniversalEnergy; Player.location = Locations.Sector12UniversalEnergy;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12DeltaOne = document.getElementById("sector12-deltaone"); let sector12DeltaOne = document.getElementById("sector12-deltaone");
sector12DeltaOne.addEventListener("click", function() { sector12DeltaOne.addEventListener("click", function() {
Player.location = Locations.Sector12DeltaOne; Player.location = Locations.Sector12DeltaOne;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12CIA = document.getElementById("sector12-cia"); let sector12CIA = document.getElementById("sector12-cia");
sector12CIA.addEventListener("click", function() { sector12CIA.addEventListener("click", function() {
Player.location = Locations.Sector12CIA; Player.location = Locations.Sector12CIA;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12NSA = document.getElementById("sector12-nsa"); let sector12NSA = document.getElementById("sector12-nsa");
sector12NSA.addEventListener("click", function() { sector12NSA.addEventListener("click", function() {
Player.location = Locations.Sector12NSA; Player.location = Locations.Sector12NSA;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12AlphaEnterprises = document.getElementById("sector12-alphaenterprises"); let sector12AlphaEnterprises = document.getElementById("sector12-alphaenterprises");
sector12AlphaEnterprises.addEventListener("click", function() { sector12AlphaEnterprises.addEventListener("click", function() {
Player.location = Locations.Sector12AlphaEnterprises; Player.location = Locations.Sector12AlphaEnterprises;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12CarmichaelSecurity = document.getElementById("sector12-carmichaelsecurity"); let sector12CarmichaelSecurity = document.getElementById("sector12-carmichaelsecurity");
sector12CarmichaelSecurity.addEventListener("click", function() { sector12CarmichaelSecurity.addEventListener("click", function() {
Player.location = Locations.Sector12CarmichaelSecurity; Player.location = Locations.Sector12CarmichaelSecurity;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12FoodNStuff = document.getElementById("sector12-foodnstuff"); let sector12FoodNStuff = document.getElementById("sector12-foodnstuff");
sector12FoodNStuff.addEventListener("click", function() { sector12FoodNStuff.addEventListener("click", function() {
Player.location = Locations.Sector12FoodNStuff; Player.location = Locations.Sector12FoodNStuff;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12JoesGuns = document.getElementById("sector12-joesguns"); let sector12JoesGuns = document.getElementById("sector12-joesguns");
sector12JoesGuns.addEventListener("click", function() { sector12JoesGuns.addEventListener("click", function() {
Player.location = Locations.Sector12JoesGuns; Player.location = Locations.Sector12JoesGuns;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12IronGym = document.getElementById("sector12-irongym"); let sector12IronGym = document.getElementById("sector12-irongym");
sector12IronGym.addEventListener("click", function() { sector12IronGym.addEventListener("click", function() {
Player.location = Locations.Sector12IronGym; Player.location = Locations.Sector12IronGym;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12PowerhouseGym = document.getElementById("sector12-powerhousegym"); let sector12PowerhouseGym = document.getElementById("sector12-powerhousegym");
sector12PowerhouseGym.addEventListener("click", function() { sector12PowerhouseGym.addEventListener("click", function() {
Player.location = Locations.Sector12PowerhouseGym; Player.location = Locations.Sector12PowerhouseGym;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
sector12Slums = document.getElementById("sector12-slums"); let sector12Slums = document.getElementById("sector12-slums");
sector12Slums.addEventListener("click", function() { sector12Slums.addEventListener("click", function() {
Player.location = Locations.Sector12Slums; Player.location = Locations.Sector12Slums;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
newTokyoTravelAgency = document.getElementById("newtokyo-travelagency"); let newTokyoTravelAgency = document.getElementById("newtokyo-travelagency");
newTokyoTravelAgency.addEventListener("click", function() { newTokyoTravelAgency.addEventListener("click", function() {
Player.location = Locations.NewTokyoTravelAgency; Player.location = Locations.NewTokyoTravelAgency;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
newTokyoHospital = document.getElementById("newtokyo-hospital"); let newTokyoHospital = document.getElementById("newtokyo-hospital");
newTokyoHospital.addEventListener("click", function() { newTokyoHospital.addEventListener("click", function() {
Player.location = Locations.Hospital; Player.location = Locations.Hospital;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
newTokyoDefComm = document.getElementById("newtokyo-defcomm"); let newTokyoDefComm = document.getElementById("newtokyo-defcomm");
newTokyoDefComm.addEventListener("click", function() { newTokyoDefComm.addEventListener("click", function() {
Player.location = Locations.NewTokyoDefComm; Player.location = Locations.NewTokyoDefComm;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
newTokyoVitaLife = document.getElementById("newtokyo-vitalife"); let newTokyoVitaLife = document.getElementById("newtokyo-vitalife");
newTokyoVitaLife.addEventListener("click", function() { newTokyoVitaLife.addEventListener("click", function() {
Player.location = Locations.NewTokyoVitaLife; Player.location = Locations.NewTokyoVitaLife;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
newTokyoGlobalPharmaceuticals = document.getElementById("newtokyo-globalpharmaceuticals"); let newTokyoGlobalPharmaceuticals = document.getElementById("newtokyo-globalpharmaceuticals");
newTokyoGlobalPharmaceuticals.addEventListener("click", function() { newTokyoGlobalPharmaceuticals.addEventListener("click", function() {
Player.location = Locations.NewTokyoGlobalPharmaceuticals; Player.location = Locations.NewTokyoGlobalPharmaceuticals;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
newTokyoNoodleBar = document.getElementById("newtokyo-noodlebar"); let newTokyoNoodleBar = document.getElementById("newtokyo-noodlebar");
newTokyoNoodleBar.addEventListener("click", function() { newTokyoNoodleBar.addEventListener("click", function() {
Player.location = Locations.NewTokyoNoodleBar; Player.location = Locations.NewTokyoNoodleBar;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
newTokyoSlums = document.getElementById("newtokyo-slums"); let newTokyoSlums = document.getElementById("newtokyo-slums");
newTokyoSlums.addEventListener("click", function() { newTokyoSlums.addEventListener("click", function() {
Player.location = Locations.NewTokyoSlums; Player.location = Locations.NewTokyoSlums;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
ishimaTravelAgency = document.getElementById("ishima-travelagency"); let ishimaTravelAgency = document.getElementById("ishima-travelagency");
ishimaTravelAgency.addEventListener("click", function() { ishimaTravelAgency.addEventListener("click", function() {
Player.location = Locations.IshimaTravelAgency; Player.location = Locations.IshimaTravelAgency;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
ishimaHospital = document.getElementById("ishima-hospital"); let ishimaHospital = document.getElementById("ishima-hospital");
ishimaHospital.addEventListener("click", function() { ishimaHospital.addEventListener("click", function() {
Player.location = Locations.Hospital; Player.location = Locations.Hospital;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
ishimaStormTechnologies = document.getElementById("ishima-stormtechnologies"); let ishimaStormTechnologies = document.getElementById("ishima-stormtechnologies");
ishimaStormTechnologies.addEventListener("click", function() { ishimaStormTechnologies.addEventListener("click", function() {
Player.location = Locations.IshimaStormTechnologies; Player.location = Locations.IshimaStormTechnologies;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
ishimaNovaMedical = document.getElementById("ishima-novamedical"); let ishimaNovaMedical = document.getElementById("ishima-novamedical");
ishimaNovaMedical.addEventListener("click", function() { ishimaNovaMedical.addEventListener("click", function() {
Player.location = Locations.IshimaNovaMedical; Player.location = Locations.IshimaNovaMedical;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
ishimaOmegaSoftware = document.getElementById("ishima-omegasoftware"); let ishimaOmegaSoftware = document.getElementById("ishima-omegasoftware");
ishimaOmegaSoftware.addEventListener("click", function() { ishimaOmegaSoftware.addEventListener("click", function() {
Player.location = Locations.IshimaOmegaSoftware; Player.location = Locations.IshimaOmegaSoftware;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
ishimaSlums = document.getElementById("ishima-slums"); let ishimaSlums = document.getElementById("ishima-slums");
ishimaSlums.addEventListener("click", function() { ishimaSlums.addEventListener("click", function() {
Player.location = Locations.IshimaSlums; Player.location = Locations.IshimaSlums;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
volhavenTravelAgency = document.getElementById("volhaven-travelagency"); let volhavenTravelAgency = document.getElementById("volhaven-travelagency");
volhavenTravelAgency.addEventListener("click", function() { volhavenTravelAgency.addEventListener("click", function() {
Player.location = Locations.VolhavenTravelAgency; Player.location = Locations.VolhavenTravelAgency;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
volhavenHospital = document.getElementById("volhaven-hospital"); let volhavenHospital = document.getElementById("volhaven-hospital");
volhavenHospital.addEventListener("click", function() { volhavenHospital.addEventListener("click", function() {
Player.location = Locations.Hospital; Player.location = Locations.Hospital;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
volhavenZBInstituteOfTechnology = document.getElementById("volhaven-zbinstituteoftechnology"); let volhavenZBInstituteOfTechnology = document.getElementById("volhaven-zbinstituteoftechnology");
volhavenZBInstituteOfTechnology.addEventListener("click", function() { volhavenZBInstituteOfTechnology.addEventListener("click", function() {
Player.location = Locations.VolhavenZBInstituteOfTechnology; Player.location = Locations.VolhavenZBInstituteOfTechnology;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
volhavenOmniTekIncorporated = document.getElementById("volhaven-omnitekincorporated"); let volhavenOmniTekIncorporated = document.getElementById("volhaven-omnitekincorporated");
volhavenOmniTekIncorporated.addEventListener("click", function() { volhavenOmniTekIncorporated.addEventListener("click", function() {
Player.location = Locations.VolhavenOmniTekIncorporated; Player.location = Locations.VolhavenOmniTekIncorporated;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
volhavenNWO = document.getElementById("volhaven-nwo"); let volhavenNWO = document.getElementById("volhaven-nwo");
volhavenNWO.addEventListener("click", function() { volhavenNWO.addEventListener("click", function() {
Player.location = Locations.VolhavenNWO; Player.location = Locations.VolhavenNWO;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
volhavenHeliosLabs = document.getElementById("volhaven-helioslabs"); let volhavenHeliosLabs = document.getElementById("volhaven-helioslabs");
volhavenHeliosLabs.addEventListener("click", function() { volhavenHeliosLabs.addEventListener("click", function() {
Player.location = Locations.VolhavenHeliosLabs; Player.location = Locations.VolhavenHeliosLabs;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
volhavenOmniaCybersystems = document.getElementById("volhaven-omniacybersystems"); let volhavenOmniaCybersystems = document.getElementById("volhaven-omniacybersystems");
volhavenOmniaCybersystems.addEventListener("click", function() { volhavenOmniaCybersystems.addEventListener("click", function() {
Player.location = Locations.VolhavenOmniaCybersystems; Player.location = Locations.VolhavenOmniaCybersystems;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
volhavenLexoCorp = document.getElementById("volhaven-lexocorp"); let volhavenLexoCorp = document.getElementById("volhaven-lexocorp");
volhavenLexoCorp.addEventListener("click", function() { volhavenLexoCorp.addEventListener("click", function() {
Player.location = Locations.VolhavenLexoCorp; Player.location = Locations.VolhavenLexoCorp;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
volhavenSysCoreSecurities = document.getElementById("volhaven-syscoresecurities"); let volhavenSysCoreSecurities = document.getElementById("volhaven-syscoresecurities");
volhavenSysCoreSecurities.addEventListener("click", function() { volhavenSysCoreSecurities.addEventListener("click", function() {
Player.location = Locations.VolhavenSysCoreSecurities; Player.location = Locations.VolhavenSysCoreSecurities;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
volhavenCompuTek = document.getElementById("volhaven-computek"); let volhavenCompuTek = document.getElementById("volhaven-computek");
volhavenCompuTek.addEventListener("click", function() { volhavenCompuTek.addEventListener("click", function() {
Player.location = Locations.VolhavenCompuTek; Player.location = Locations.VolhavenCompuTek;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
volhavenMilleniumFitnessGym = document.getElementById("volhaven-milleniumfitnessgym"); let volhavenMilleniumFitnessGym = document.getElementById("volhaven-milleniumfitnessgym");
volhavenMilleniumFitnessGym.addEventListener("click", function() { volhavenMilleniumFitnessGym.addEventListener("click", function() {
Player.location = Locations.VolhavenMilleniumFitnessGym; Player.location = Locations.VolhavenMilleniumFitnessGym;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
volhavenSlums = document.getElementById("volhaven-slums"); let volhavenSlums = document.getElementById("volhaven-slums");
volhavenSlums.addEventListener("click", function() { volhavenSlums.addEventListener("click", function() {
Player.location = Locations.VolhavenSlums; Player.location = Locations.VolhavenSlums;
Engine.loadLocationContent(); Engine.loadLocationContent();
return false; return false;
}); });
worldStockExchange = document.getElementById("generic-location-wse"); let worldStockExchange = document.getElementById("generic-location-wse");
worldStockExchange.addEventListener("click", function() { worldStockExchange.addEventListener("click", function() {
Player.location = Locations.WorldStockExchange; Player.location = Locations.WorldStockExchange;
Engine.loadStockMarketContent(); Engine.loadStockMarketContent();
@ -1811,7 +1839,8 @@ initLocationButtons = function() {
}); });
} }
travelToCity = function(destCityName, cost) { function travelToCity(destCityName, cost) {
Player.firstTimeTraveled = true;
if (Player.money.lt(cost)) { if (Player.money.lt(cost)) {
dialogBoxCreate("You cannot afford to travel to " + destCityName); dialogBoxCreate("You cannot afford to travel to " + destCityName);
return; return;
@ -1823,7 +1852,7 @@ travelToCity = function(destCityName, cost) {
Engine.loadWorldContent(); Engine.loadWorldContent();
} }
purchaseTorRouter = function() { function purchaseTorRouter() {
if (Player.money.lt(CONSTANTS.TorRouterCost)) { if (Player.money.lt(CONSTANTS.TorRouterCost)) {
dialogBoxCreate("You cannot afford to purchase the Tor router"); dialogBoxCreate("You cannot afford to purchase the Tor router");
return; return;
@ -1841,7 +1870,7 @@ purchaseTorRouter = function() {
dialogBoxCreate("You have purchased a Tor router!<br>You now have access to the dark web from your home computer<br>Use the scan/netstat commands to search for the dark web connection."); dialogBoxCreate("You have purchased a Tor router!<br>You now have access to the dark web from your home computer<br>Use the scan/netstat commands to search for the dark web connection.");
} }
displayUniversityLocationContent = function(costMult) { function displayUniversityLocationContent(costMult) {
var studyComputerScienceButton = document.getElementById("location-study-computer-science"); var studyComputerScienceButton = document.getElementById("location-study-computer-science");
var classDataStructuresButton = document.getElementById("location-data-structures-class"); var classDataStructuresButton = document.getElementById("location-data-structures-class");
var classNetworksButton = document.getElementById("location-networks-class"); var classNetworksButton = document.getElementById("location-networks-class");
@ -1870,7 +1899,7 @@ displayUniversityLocationContent = function(costMult) {
classLeadershipButton.innerHTML = "Take Leadership course ($" + leadershipCost + " / sec)"; classLeadershipButton.innerHTML = "Take Leadership course ($" + leadershipCost + " / sec)";
} }
setUniversityLocationButtons = function(costMult, expMult) { function setUniversityLocationButtons(costMult, expMult) {
var newStudyCS = clearEventListeners("location-study-computer-science"); var newStudyCS = clearEventListeners("location-study-computer-science");
newStudyCS.addEventListener("click", function() { newStudyCS.addEventListener("click", function() {
Player.startClass(costMult, expMult, CONSTANTS.ClassStudyComputerScience); Player.startClass(costMult, expMult, CONSTANTS.ClassStudyComputerScience);
@ -1908,7 +1937,7 @@ setUniversityLocationButtons = function(costMult, expMult) {
}); });
} }
displayGymLocationContent = function(costMult) { function displayGymLocationContent(costMult) {
var gymStrButton = document.getElementById("location-gym-train-str"); var gymStrButton = document.getElementById("location-gym-train-str");
var gymDefButton = document.getElementById("location-gym-train-def"); var gymDefButton = document.getElementById("location-gym-train-def");
var gymDexButton = document.getElementById("location-gym-train-dex"); var gymDexButton = document.getElementById("location-gym-train-dex");
@ -1928,7 +1957,7 @@ displayGymLocationContent = function(costMult) {
gymAgiButton.innerHTML = "Train Agility ($" + cost + " / sec)"; gymAgiButton.innerHTML = "Train Agility ($" + cost + " / sec)";
} }
setGymLocationButtons = function(costMult, expMult) { function setGymLocationButtons(costMult, expMult) {
var gymStr = clearEventListeners("location-gym-train-str"); var gymStr = clearEventListeners("location-gym-train-str");
gymStr.addEventListener("click", function() { gymStr.addEventListener("click", function() {
Player.startClass(costMult, expMult, CONSTANTS.ClassGymStrength); Player.startClass(costMult, expMult, CONSTANTS.ClassGymStrength);
@ -1954,7 +1983,7 @@ setGymLocationButtons = function(costMult, expMult) {
}); });
} }
setInfiltrateButton = function(btn, companyName, startLevel, val, maxClearance, difficulty) { function setInfiltrateButton(btn, companyName, startLevel, val, maxClearance, difficulty) {
btn.style.display = "block"; btn.style.display = "block";
btn.addEventListener("click", function() { btn.addEventListener("click", function() {
Engine.loadInfiltrationContent(); Engine.loadInfiltrationContent();
@ -2008,3 +2037,5 @@ function purchaseServerBoxCreate(ram, cost) {
"GB of RAM for $" + formatNumber(cost, 2) + "?<br><br>" + "GB of RAM for $" + formatNumber(cost, 2) + "?<br><br>" +
"Please enter the server hostname below:<br>"); "Please enter the server hostname below:<br>");
} }
export {Locations, displayLocationContent, initLocationButtons};

@ -1,3 +1,13 @@
import {Augmentations, Augmentation,
AugmentationNames} from "./Augmentations.js";
import {Programs} from "./CreateProgram.js";
import {Player} from "./Player.js";
import {GetServerByHostname} from "./Server.js";
import {Settings} from "./Settings.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js";
/* Message.js */ /* Message.js */
function Message(filename="", msg="") { function Message(filename="", msg="") {
this.filename = filename; this.filename = filename;
@ -56,6 +66,11 @@ function checkForMessagesToSend() {
var bitrunnersTest = Messages[MessageFilenames.BitRunnersTest]; var bitrunnersTest = Messages[MessageFilenames.BitRunnersTest];
var redpill = Messages[MessageFilenames.RedPill]; var redpill = Messages[MessageFilenames.RedPill];
var redpillOwned = false;
if (Augmentations[AugmentationNames.TheRedPill].owned) {
redpillOwned = true;
}
if (jumper0 && !jumper0.recvd && Player.hacking_skill >= 25) { if (jumper0 && !jumper0.recvd && Player.hacking_skill >= 25) {
sendMessage(jumper0); sendMessage(jumper0);
} else if (jumper1 && !jumper1.recvd && Player.hacking_skill >= 40) { } else if (jumper1 && !jumper1.recvd && Player.hacking_skill >= 40) {
@ -75,7 +90,7 @@ function checkForMessagesToSend() {
} else if (jumper5 && !jumper5.recvd && Player.hacking_skill >= 1000) { } else if (jumper5 && !jumper5.recvd && Player.hacking_skill >= 1000) {
sendMessage(jumper5); sendMessage(jumper5);
Player.getHomeComputer().programs.push(Programs.Flight); Player.getHomeComputer().programs.push(Programs.Flight);
} else if (redpill && !redpill.recvd && Player.hacking_skill >= 2000) { } else if (redpill && !redpill.recvd && Player.hacking_skill >= 2000 && redpillOwned) {
sendMessage(redpill); sendMessage(redpill);
} }
} }
@ -84,9 +99,13 @@ function AddToAllMessages(msg) {
Messages[msg.filename] = msg; Messages[msg.filename] = msg;
} }
Messages = {} let Messages = {}
MessageFilenames = { function loadMessages(saveString) {
Messages = JSON.parse(saveString, Reviver);
}
let MessageFilenames = {
Jumper0: "j0.msg", Jumper0: "j0.msg",
Jumper1: "j1.msg", Jumper1: "j1.msg",
Jumper2: "j2.msg", Jumper2: "j2.msg",
@ -160,3 +179,6 @@ function initMessages() {
"@_#(%_@#M(BDSPOMB__THE-CAVE_#)$(*@#$)@#BNBEGB<br>" + "@_#(%_@#M(BDSPOMB__THE-CAVE_#)$(*@#$)@#BNBEGB<br>" +
"DFLSMFVMV)#@($*)@#*$MV)@#(*$V)M#(*$)M@(#*VM$)")); "DFLSMFVMV)#@($*)@#*$MV)@#(*$V)M#(*$)M@(#*VM$)"));
} }
export {Messages, checkForMessagesToSend, sendMessage, showMessage, loadMessages,
initMessages, Message};

@ -1,5 +1,6 @@
import {NetscriptFunctions} from "./NetscriptFunctions.js";
/* Environment /* Environment
* NetScript program environment * NetScript program environment
*/ */
function Environment(workerScript,parent) { function Environment(workerScript,parent) {
if (parent){ if (parent){
@ -16,7 +17,7 @@ Environment.prototype = {
extend: function() { extend: function() {
return new Environment(this); return new Environment(this);
}, },
//Finds the scope where the variable with the given name is defined //Finds the scope where the variable with the given name is defined
lookup: function(name) { lookup: function(name) {
var scope = this; var scope = this;
@ -26,7 +27,7 @@ Environment.prototype = {
scope = scope.parent; scope = scope.parent;
} }
}, },
//Get the current value of a variable //Get the current value of a variable
get: function(name) { get: function(name) {
if (name in this.vars) { if (name in this.vars) {
@ -34,7 +35,7 @@ Environment.prototype = {
} }
throw new Error("Undefined variable " + name); throw new Error("Undefined variable " + name);
}, },
//Sets the value of a variable in any scope //Sets the value of a variable in any scope
set: function(name, value) { set: function(name, value) {
var scope = this.lookup(name); var scope = this.lookup(name);
@ -48,7 +49,7 @@ Environment.prototype = {
} }
return (scope || this).vars[name] = value; return (scope || this).vars[name] = value;
}, },
setArrayElement: function(name, idx, value) { setArrayElement: function(name, idx, value) {
var scope = this.lookup(name); var scope = this.lookup(name);
if (!scope && this.parent) { if (!scope && this.parent) {
@ -61,9 +62,11 @@ Environment.prototype = {
} }
return (scope || this).vars[name][idx] = value; return (scope || this).vars[name][idx] = value;
}, },
//Creates (or overwrites) a variable in the current scope //Creates (or overwrites) a variable in the current scope
def: function(name, value) { def: function(name, value) {
return this.vars[name] = value; return this.vars[name] = value;
} }
}; };
export {Environment};

@ -1,3 +1,17 @@
import {BitNodeMultipliers} from "./BitNode.js";
import {CONSTANTS} from "./Constants.js";
import {Player} from "./Player.js";
import {Environment} from "./NetscriptEnvironment.js";
import {WorkerScript, addWorkerScript} from "./NetscriptWorker.js";
import {Server} from "./Server.js";
import {Settings} from "./Settings.js";
import {Script, findRunningScript,
RunningScript} from "./Script.js";
import {printArray} from "../utils/HelperFunctions.js";
import {isValidIPAddress} from "../utils/IPAddress.js";
import {isString} from "../utils/StringHelperFunctions.js";
/* Evaluator /* Evaluator
* Evaluates the Abstract Syntax Tree for Netscript * Evaluates the Abstract Syntax Tree for Netscript
* generated by the Parser class * generated by the Parser class
@ -20,7 +34,7 @@ function evaluate(exp, workerScript) {
evaluateProgPromise.then(function(w) { evaluateProgPromise.then(function(w) {
resolve(workerScript); resolve(workerScript);
}, function(e) { }, function(e) {
if (typeof e === 'string' || e instanceof String) { if (isString(e)) {
workerScript.errorMessage = e; workerScript.errorMessage = e;
reject(workerScript); reject(workerScript);
} else if (e instanceof WorkerScript) { } else if (e instanceof WorkerScript) {
@ -35,7 +49,7 @@ function evaluate(exp, workerScript) {
break; break;
case "Identifier": case "Identifier":
if (!(exp.name in env.vars)){ if (!(exp.name in env.vars)){
reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.name + " not definied")); reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.name + " not defined"));
} }
resolve(env.get(exp.name)) resolve(env.get(exp.name))
break; break;
@ -172,7 +186,7 @@ function evaluate(exp, workerScript) {
} }
resolve(env.get(exp.argument.name)) resolve(env.get(exp.argument.name))
} else { } else {
reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.argument.name + " not definied")); reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.argument.name + " not defined"));
} }
} else { } else {
reject(makeRuntimeRejectMsg(workerScript, "argument must be an identifier")); reject(makeRuntimeRejectMsg(workerScript, "argument must be an identifier"));
@ -336,7 +350,7 @@ function evalAssignment(exp, workerScript) {
} }
if (exp.operator !== "=" && !(exp.left.name in env.vars)){ if (exp.operator !== "=" && !(exp.left.name in env.vars)){
return reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.left.name + " not definied")); return reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.left.name + " not defined"));
} }
var expRightPromise = evaluate(exp.right, workerScript); var expRightPromise = evaluate(exp.right, workerScript);
@ -347,7 +361,7 @@ function evalAssignment(exp, workerScript) {
//Index designated by exp.left.property //Index designated by exp.left.property
var name = exp.left.object.name; var name = exp.left.object.name;
if (!(name in env.vars)){ if (!(name in env.vars)){
reject(makeRuntimeRejectMsg(workerScript, "variable " + name + " not definied")); reject(makeRuntimeRejectMsg(workerScript, "variable " + name + " not defined"));
} }
var arr = env.get(name); var arr = env.get(name);
if (arr.constructor === Array || arr instanceof Array) { if (arr.constructor === Array || arr instanceof Array) {
@ -631,7 +645,8 @@ function runScriptFromScript(server, scriptname, args, workerScript, threads=1)
} }
function isScriptErrorMessage(msg) { function isScriptErrorMessage(msg) {
splitMsg = msg.split("|"); if (!isString(msg)) {return false;}
let splitMsg = msg.split("|");
if (splitMsg.length != 4){ if (splitMsg.length != 4){
return false; return false;
} }
@ -666,7 +681,7 @@ function scriptCalculateExpGain(server) {
if (server.baseDifficulty == null) { if (server.baseDifficulty == null) {
server.baseDifficulty = server.hackDifficulty; server.baseDifficulty = server.hackDifficulty;
} }
return (server.baseDifficulty * Player.hacking_exp_mult * 0.3 + 3); return (server.baseDifficulty * Player.hacking_exp_mult * 0.3 + 3) * BitNodeMultipliers.HackExpGain;
} }
//The same as Player's calculatePercentMoneyHacked() function but takes in the server as an argument //The same as Player's calculatePercentMoneyHacked() function but takes in the server as an argument
@ -676,7 +691,7 @@ function scriptCalculatePercentMoneyHacked(server) {
var percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / 240; var percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / 240;
if (percentMoneyHacked < 0) {return 0;} if (percentMoneyHacked < 0) {return 0;}
if (percentMoneyHacked > 1) {return 1;} if (percentMoneyHacked > 1) {return 1;}
return percentMoneyHacked; return percentMoneyHacked * BitNodeMultipliers.ScriptHackMoney;
} }
//Amount of time to execute grow() in milliseconds //Amount of time to execute grow() in milliseconds
@ -694,3 +709,9 @@ function scriptCalculateWeakenTime(server) {
var weakenTime = 20 * skillFactor / Player.hacking_speed_mult; //This is in seconds var weakenTime = 20 * skillFactor / Player.hacking_speed_mult; //This is in seconds
return weakenTime * 1000; return weakenTime * 1000;
} }
export {makeRuntimeRejectMsg, netscriptDelay, runScriptFromScript,
scriptCalculateHackingChance, scriptCalculateHackingTime,
scriptCalculateExpGain, scriptCalculatePercentMoneyHacked,
scriptCalculateGrowTime, scriptCalculateWeakenTime, evaluate,
isScriptErrorMessage};

@ -1,3 +1,55 @@
import {Augmentations, Augmentation,
augmentationExists, installAugmentations} from "./Augmentations.js";
import {Companies, Company, CompanyPosition,
CompanyPositions, companyExists} from "./Company.js";
import {CONSTANTS} from "./Constants.js";
import {Programs} from "./CreateProgram.js";
import {parseDarkwebItemPrice, DarkWebItems} from "./DarkWeb.js";
import {Engine} from "./engine.js";
import {Factions, Faction, joinFaction,
factionExists, purchaseAugmentation} from "./Faction.js";
import {getCostOfNextHacknetNode,
purchaseHacknet} from "./HacknetNode.js";
import {Locations} from "./Location.js";
import {Player} from "./Player.js";
import {Script, findRunningScript, RunningScript} from "./Script.js";
import {Server, getServer, AddToAllServers,
AllServers, processSingleServerGrowth,
GetServerByHostname} from "./Server.js";
import {Settings} from "./Settings.js";
import {SpecialServerIps} from "./SpecialServerIps.js";
import {StockMarket, StockSymbols, SymbolToStockMap, initStockSymbols,
initStockMarket, initSymbolToStockMap, stockMarketCycle, buyStock,
sellStock, updateStockPrices, displayStockMarketContent,
updateStockTicker, updateStockPlayerPosition,
Stock} from "./StockMarket.js";
import {post} from "./Terminal.js";
import {WorkerScript, workerScripts,
killWorkerScript, NetscriptPorts} from "./NetscriptWorker.js";
import {makeRuntimeRejectMsg, netscriptDelay, runScriptFromScript,
scriptCalculateHackingChance, scriptCalculateHackingTime,
scriptCalculateExpGain, scriptCalculatePercentMoneyHacked,
scriptCalculateGrowTime, scriptCalculateWeakenTime} from "./NetscriptEvaluator.js";
import {Environment} from "./NetscriptEnvironment.js";
import Decimal from '../utils/decimal.js';
import {printArray, powerOfTwo} from "../utils/HelperFunctions.js";
import {createRandomIp} from "../utils/IPAddress.js";
import {formatNumber, isString} from "../utils/StringHelperFunctions.js";
var hasSingularitySF = false;
var singularitySFLvl = 1;
function initSingularitySFFlags() {
for (var i = 0; i < Player.sourceFiles.length; ++i) {
if (Player.sourceFiles[i].n === 4) {
hasSingularitySF = true;
singularitySFLvl = Player.sourceFiles[i].lvl;
}
}
}
function NetscriptFunctions(workerScript) { function NetscriptFunctions(workerScript) {
return { return {
hacknetnodes : Player.hacknetNodes, hacknetnodes : Player.hacknetNodes,
@ -172,6 +224,12 @@ function NetscriptFunctions(workerScript) {
} }
workerScript.scriptRef.log(args.toString()); workerScript.scriptRef.log(args.toString());
}, },
tprint : function(args) {
if (args === undefined || args === null) {
throw makeRuntimeRejectMsg(workerScript, "tprint() call has incorrect number of arguments. Takes 1 argument");
}
post(workerScript.scriptRef.filename + ": " + args.toString());
},
clearLog : function() { clearLog : function() {
workerScript.scriptRef.clearLog(); workerScript.scriptRef.clearLog();
}, },
@ -208,6 +266,7 @@ function NetscriptFunctions(workerScript) {
throw makeRuntimeRejectMsg(workerScript, "Cannot call brutessh(). Invalid IP or hostname passed in: " + ip); throw makeRuntimeRejectMsg(workerScript, "Cannot call brutessh(). Invalid IP or hostname passed in: " + ip);
} }
if (!Player.hasProgram(Programs.BruteSSHProgram)) { if (!Player.hasProgram(Programs.BruteSSHProgram)) {
workerScript.scriptRef.log("You do not have the BruteSSH.exe program!");
throw makeRuntimeRejectMsg(workerScript, "You do not have the BruteSSH.exe program!"); throw makeRuntimeRejectMsg(workerScript, "You do not have the BruteSSH.exe program!");
} }
if (!server.sshPortOpen) { if (!server.sshPortOpen) {
@ -864,7 +923,784 @@ function NetscriptFunctions(workerScript) {
throw makeRuntimeRejectMsg(workerScript, "getWeakenTime() failed. Invalid IP or hostname passed in: " + ip); throw makeRuntimeRejectMsg(workerScript, "getWeakenTime() failed. Invalid IP or hostname passed in: " + ip);
} }
return scriptCalculateWeakenTime(server) / 1000; //Returns seconds return scriptCalculateWeakenTime(server) / 1000; //Returns seconds
} },
/* Singularity Functions */
universityCourse(universityName, className) {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 1)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run universityCourse(). It is a Singularity Function and requires SourceFile-4 (level 1) to run.");
return false;
}
}
if (Player.isWorking) {
var txt = Player.singularityStopWork();
workerScript.scriptRef.log(txt);
}
var costMult, expMult;
switch(universityName.toLowerCase()) {
case Locations.AevumSummitUniversity.toLowerCase():
if (Player.city != Locations.Aevum) {
workerScript.scriptRef.log("ERROR: You cannot study at Summit University because you are not in Aevum. universityCourse() failed");
return false;
}
costMult = 4;
expMult = 3;
break;
case Locations.Sector12RothmanUniversity.toLowerCase():
if (Player.city != Locations.Sector12) {
workerScript.scriptRef.log("ERROR: You cannot study at Rothman University because you are not in Sector-12. universityCourse() failed");
return false;
}
costMult = 3;
expMult = 2;
break;
case Locations.VolhavenZBInstituteOfTechnology.toLowerCase():
if (Player.city != Locations.Volhaven) {
workerScript.scriptRef.log("ERROR: You cannot study at ZB Institute of Technology because you are not in Volhaven. universityCourse() failed");
return false;
}
costMult = 5;
expMult = 4;
break;
default:
workerScript.scriptRef.log("Invalid university name: " + universityName + ". universityCourse() failed");
return false;
}
var task;
switch(className.toLowerCase()) {
case "Study Computer Science".toLowerCase():
task = CONSTANTS.ClassStudyComputerScience;
break;
case "Data Structures".toLowerCase():
task = CONSTANTS.ClassDataStructures;
break;
case "Networks".toLowerCase():
task = CONSTANTS.ClassNetworks;
break;
case "Algorithms".toLowerCase():
task = CONSTANTS.ClassAlgorithms;
break;
case "Management".toLowerCase():
task = CONSTANTS.ClassManagement;
break;
case "Leadership".toLowerCase():
task = CONSTANTS.ClassLeadership;
break;
default:
workerScript.scriptRef.log("Invalid class name: " + className + ". universityCourse() failed");
return false;
}
Player.startClass(costMult, expMult, task);
workerScript.scriptRef.log("Started " + task + " at " + universityName);
return true;
},
gymWorkout(gymName, stat) {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 1)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run gymWorkout(). It is a Singularity Function and requires SourceFile-4 (level 1) to run.");
return false;
}
}
if (Player.isWorking) {
var txt = Player.singularityStopWork();
workerScript.scriptRef.log(txt);
}
var costMult, expMult;
switch(gymName.toLowerCase()) {
case Locations.AevumCrushFitnessGym.toLowerCase():
if (Player.city != Locations.Aevum) {
workerScript.scriptRef.log("ERROR: You cannot workout at Crush Fitness because you are not in Aevum. gymWorkout() failed");
return false;
}
costMult = 2;
expMult = 1.5;
break;
case Locations.AevumSnapFitnessGym.toLowerCase():
if (Player.city != Locations.Aevum) {
workerScript.scriptRef.log("ERROR: You cannot workout at Snap Fitness because you are not in Aevum. gymWorkout() failed");
return false;
}
costMult = 6;
expMult = 4;
break;
case Locations.Sector12IronGym.toLowerCase():
if (Player.city != Locations.Sector12) {
workerScript.scriptRef.log("ERROR: You cannot workout at Iron Gym because you are not in Sector-12. gymWorkout() failed");
return false;
}
costMult = 1;
expMult = 1;
break;
case Locations.Sector12PowerhouseGym.toLowerCase():
if (Player.city != Locations.Sector12) {
workerScript.scriptRef.log("ERROR: You cannot workout at Powerhouse Gym because you are not in Sector-12. gymWorkout() failed");
return false;
}
costMult = 10;
expMult = 7.5;
break;
case Locations.VolhavenMilleniumFitnessGym:
if (Player.city != Locations.Volhaven) {
workerScript.scriptRef.log("ERROR: You cannot workout at Millenium Fitness Gym because you are not in Volhaven. gymWorkout() failed");
return false;
}
costMult = 3;
expMult = 2.5;
break;
default:
workerScript.scriptRef.log("Invalid gym name: " + gymName + ". gymWorkout() failed");
return false;
}
switch(stat.toLowerCase()) {
case "strength".toLowerCase():
case "str".toLowerCase():
Player.startClass(costMult, expMult, CONSTANTS.ClassGymStrength);
break;
case "defense".toLowerCase():
case "def".toLowerCase():
Player.startClass(costMult, expMult, CONSTANTS.ClassGymDefense);
break;
case "dexterity".toLowerCase():
case "dex".toLowerCase():
Player.startClass(costMult, expMult, CONSTANTS.ClassGymDexterity);
break;
case "agility".toLowerCase():
case "agi".toLowerCase():
Player.startClass(costMult, expMult, CONSTANTS.ClassGymAgility);
break;
default:
workerScript.scriptRef.log("Invalid stat: " + stat + ". gymWorkout() failed");
return false;
}
workerScript.scriptRef.log("Started training " + stat + " at " + gymName);
return true;
},
travelToCity(cityname) {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 1)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run travelToCity(). It is a Singularity Function and requires SourceFile-4 (level 1) to run.");
return false;
}
}
switch(cityname) {
case Locations.Aevum:
case Locations.Chongqing:
case Locations.Sector12:
case Locations.NewTokyo:
case Locations.Ishima:
case Locations.Volhaven:
Player.loseMoney(200000);
Player.city = cityname;
workerScript.scriptRef.log("Traveled to " + cityname);
return true;
default:
workerScript.scriptRef.log("ERROR: Invalid city name passed into travelToCity().");
return false;
}
},
purchaseTor() {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 1)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run purchaseTor(). It is a Singularity Function and requires SourceFile-4 (level 1) to run.");
return false;
}
}
if (SpecialServerIps["Darkweb Server"] != null) {
workerScript.scriptRef.log("You already have a TOR router! purchaseTor() failed");
return false;
}
if (Player.money.lt(CONSTANTS.TorRouterCost)) {
workerScript.scriptRef.log("ERROR: You cannot afford to purchase a Tor router. purchaseTor() failed");
return false;
}
Player.loseMoney(CONSTANTS.TorRouterCost);
var darkweb = new Server(createRandomIp(), "darkweb", "", false, false, false, 1);
AddToAllServers(darkweb);
SpecialServerIps.addIp("Darkweb Server", darkweb.ip);
document.getElementById("location-purchase-tor").setAttribute("class", "a-link-button-inactive");
Player.getHomeComputer().serversOnNetwork.push(darkweb.ip);
darkweb.serversOnNetwork.push(Player.getHomeComputer().ip);
workerScript.scriptRef.log("You have purchased a Tor router!");
return true;
},
purchaseProgram(programName) {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 1)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run purchaseProgram(). It is a Singularity Function and requires SourceFile-4 (level 1) to run.");
return false;
}
}
if (SpecialServerIps["Darkweb Server"] == null) {
workerScript.scriptRef.log("ERROR: You do not have TOR router. purchaseProgram() failed.");
return false;
}
switch(programName.toLowerCase()) {
case Programs.BruteSSHProgram.toLowerCase():
var price = parseDarkwebItemPrice(DarkWebItems.BruteSSHProgram);
if (price > 0 && Player.money.gt(price)) {
Player.loseMoney(price);
Player.getHomeComputer().programs.push(Programs.BruteSSHProgram);
workerScript.scriptRef.log("You have purchased the BruteSSH.exe program. The new program " +
"can be found on your home computer.");
} else {
workerScript.scriptRef.log("Not enough money to purchase " + programName);
}
return true;
case Programs.FTPCrackProgram.toLowerCase():
var price = parseDarkwebItemPrice(DarkWebItems.FTPCrackProgram);
if (price > 0 && Player.money.gt(price)) {
Player.loseMoney(price);
Player.getHomeComputer().programs.push(Programs.FTPCrackProgram);
workerScript.scriptRef.log("You have purchased the FTPCrack.exe program. The new program " +
"can be found on your home computer.");
} else {
workerScript.scriptRef.log("Not enough money to purchase " + itemName);
}
return true;
case Programs.RelaySMTPProgram.toLowerCase():
var price = parseDarkwebItemPrice(DarkWebItems.RelaySMTPProgram);
if (price > 0 && Player.money.gt(price)) {
Player.loseMoney(price);
Player.getHomeComputer().programs.push(Programs.RelaySMTPProgram);
workerScript.scriptRef.log("You have purchased the relaySMTP.exe program. The new program " +
"can be found on your home computer.");
} else {
workerScript.scriptRef.log("Not enough money to purchase " + itemName);
}
return true;
case Programs.HTTPWormProgram.toLowerCase():
var price = parseDarkwebItemPrice(DarkWebItems.HTTPWormProgram);
if (price > 0 && Player.money.gt(price)) {
Player.loseMoney(price);
Player.getHomeComputer().programs.push(Programs.HTTPWormProgram);
workerScript.scriptRef.log("You have purchased the HTTPWorm.exe program. The new program " +
"can be found on your home computer.");
} else {
workerScript.scriptRef.log("Not enough money to purchase " + itemName);
}
return true;
case Programs.SQLInjectProgram.toLowerCase():
var price = parseDarkwebItemPrice(DarkWebItems.SQLInjectProgram);
if (price > 0 && Player.money.gt(price)) {
Player.loseMoney(price);
Player.getHomeComputer().programs.push(Programs.SQLInjectProgram);
workerScript.scriptRef.log("You have purchased the SQLInject.exe program. The new program " +
"can be found on your home computer.");
} else {
workerScript.scriptRef.log("Not enough money to purchase " + itemName);
}
return true;
case Programs.DeepscanV1.toLowerCase():
var price = parseDarkwebItemPrice(DarkWebItems.DeepScanV1Program);
if (price > 0 && Player.money.gt(price)) {
Player.loseMoney(price);
Player.getHomeComputer().programs.push(Programs.DeepscanV1);
workerScript.scriptRef.log("You have purchased the DeepscanV1.exe program. The new program " +
"can be found on your home computer.");
} else {
workerScript.scriptRef.log("Not enough money to purchase " + itemName);
}
return true;
case Programs.DeepscanV2.toLowerCase():
var price = parseDarkwebItemPrice(DarkWebItems.DeepScanV2Program);
if (price > 0 && Player.money.gt(price)) {
Player.loseMoney(price);
Player.getHomeComputer().programs.push(Programs.DeepscanV2);
workerScript.scriptRef.log("You have purchased the DeepscanV2.exe program. The new program " +
"can be found on your home computer.");
} else {
workerScript.scriptRef.log("Not enough money to purchase " + itemName);
}
return true;
default:
workerScript.scriptRef.log("ERROR: Invalid program passed into purchaseProgram().");
return false;
}
return true;
},
upgradeHomeRam() {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 2)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run upgradeHomeRam(). It is a Singularity Function and requires SourceFile-4 (level 2) to run.");
return false;
}
}
//Calculate how many times ram has been upgraded (doubled)
var currentRam = Player.getHomeComputer().maxRam;
var numUpgrades = Math.log2(currentRam);
//Calculate cost
//Have cost increase by some percentage each time RAM has been upgraded
var cost = currentRam * CONSTANTS.BaseCostFor1GBOfRamHome;
var mult = Math.pow(1.55, numUpgrades);
cost = cost * mult;
if (Player.money.lt(cost)) {
workerScript.scriptRef.log("ERROR: upgradeHomeRam() failed because you don't have enough money");
return false;
}
var homeComputer = Player.getHomeComputer();
homeComputer.maxRam *= 2;
Player.loseMoney(cost);
workerScript.scriptRef.log("Purchased additional RAM for home computer! It now has " + homeComputer.maxRam + "GB of RAM.");
return true;
},
getUpgradeHomeRamCost() {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 2)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run getUpgradeHomeRamCost(). It is a Singularity Function and requires SourceFile-4 (level 2) to run.");
return false;
}
}
//Calculate how many times ram has been upgraded (doubled)
var currentRam = Player.getHomeComputer().maxRam;
var numUpgrades = Math.log2(currentRam);
//Calculate cost
//Have cost increase by some percentage each time RAM has been upgraded
var cost = currentRam * CONSTANTS.BaseCostFor1GBOfRamHome;
var mult = Math.pow(1.55, numUpgrades);
return cost * mult;
},
workForCompany() {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 2)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run workForCompany(). It is a Singularity Function and requires SourceFile-4 (level 2) to run.");
return false;
}
}
if (Player.companyPosition == "" || !(Player.companyPosition instanceof CompanyPosition)) {
workerScript.scriptRef.log("ERROR: workForCompany() failed because you do not have a job");
return false;
}
if (Player.isWorking) {
var txt = Player.singularityStopWork();
workerScript.scriptRef.log(txt);
}
if (Player.companyPosition.isPartTimeJob()) {
Player.startWorkPartTime();
} else {
Player.startWork();
}
workerScript.scriptRef.log("Began working at " + Player.companyName + " as a " + Player.companyPosition.positionName);
return true;
},
applyToCompany(companyName, field) {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 2)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run applyToCompany(). It is a Singularity Function and requires SourceFile-4 (level 2) to run.");
return false;
}
}
if (!companyExists(companyName)) {
workerScript.scriptRef.log("ERROR: applyToCompany() failed because specified company " + companyName + " does not exist.");
return false;
}
Player.location = companyName;
var res;
switch (field.toLowerCase()) {
case "software":
res = Player.applyForSoftwareJob(true);
break;
case "software consultant":
res = Player.applyForSoftwareConsultantJob(true);
break;
case "it":
res = Player.applyForItJob(true);
break;
case "security engineer":
res = Player.applyForSecurityEngineerJob(true);
break;
case "network engineer":
res = Player.applyForNetworkEngineerJob(true);
break;
case "business":
res = Player.applyForBusinessJob(true);
break;
case "business consultant":
res = Player.applyForBusinessConsultantJob(true);
break;
case "security":
res = Player.applyForSecurityJob(true);
break;
case "agent":
res = Player.applyForAgentJob(true);
break;
case "employee":
res = Player.applyForEmployeeJob(true);
break;
case "part-time employee":
res = Player.applyForPartTimeEmployeeJob(true);
break;
case "waiter":
res = Player.applyForWaiterJob(true);
break;
case "part-time waiter":
res = Player.applyForPartTimeWaiterJob(true);
break;
default:
workerScript.scriptRef.log("ERROR: Invalid job passed into applyToCompany: " + field + ". applyToCompany() failed");
return false;
}
//The Player object's applyForJob function can return string with special error messages
if (isString(res)) {
workerScript.scriptRef.log(res);
return false;
}
if (res) {
workerScript.scriptRef.log("You were offered a new job at " + companyName + " as a " + Player.companyPosition.positionName);
} else {
workerScript.scriptRef.log("You failed to get a new job/promotion at " + companyName + " in the " + field + " field.");
}
return res;
},
getCompanyRep(companyName) {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 2)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run getCompanyRep(). It is a Singularity Function and requires SourceFile-4 (level 2) to run.");
return false;
}
}
var company = Companies[companyName];
if (company === null || !(company instanceof Company)) {
workerScript.scriptRef.log("ERROR: Invalid companyName passed into getCompanyRep(): " + companyName);
return -1;
}
return company.playerReputation;
},
checkFactionInvitations() {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 2)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run checkFactionInvitations(). It is a Singularity Function and requires SourceFile-4 (level 2) to run.");
return false;
}
}
//Make a copy of Player.factionInvitations
return Player.factionInvitations.slice();
},
joinFaction(name) {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 2)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run joinFaction(). It is a Singularity Function and requires SourceFile-4 (level 2) to run.");
return false;
}
}
if (!factionExists(name)) {
workerScript.scriptRef.log("ERROR: Faction specified in joinFaction() does not exist.");
return false;
}
if (!Player.factionInvitations.includes(name)) {
workerScript.scriptRef.log("ERROR: Cannot join " + name + " Faction because you have not been invited. joinFaction() failed");
return false;
}
var index = Player.factionInvitations.indexOf(name);
if (index === -1) {
//Redundant and should never happen...
workerScript.scriptRef.log("ERROR: Cannot join " + name + " Faction because you have not been invited. joinFaction() failed");
return false;
}
Player.factionInvitations.splice(index, 1);
var fac = Factions[name];
joinFaction(fac);
workerScript.scriptRef.log("Joined the " + name + " faction.");
return true;
},
workForFaction(name, type) {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 2)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run workForFaction(). It is a Singularity Function and requires SourceFile-4 (level 2) to run.");
return false;
}
}
if (!factionExists(name)) {
workerScript.scriptRef.log("ERROR: Faction specified in workForFaction() does not exist.");
return false;
}
if (!Player.factions.includes(name)) {
workerScript.scriptRef.log("ERROR: workForFaction() failed because you are not a member of " + name);
return false;
}
if (Player.isWorking) {
var txt = Player.singularityStopWork();
workerScript.scriptRef.log(txt);
}
var fac = Factions[name];
//Arrays listing factions that allow each time of work
var hackAvailable = ["Illuminati", "Daedalus", "The Covenant", "ECorp", "MegaCorp",
"Bachman & Associates", "Blade Industries", "NWO", "Clarke Incorporated",
"OmniTek Incorporated", "Four Sigma", "KuaiGong International",
"Fulcrum Secret Technologies", "BitRunners", "The Black Hand",
"NiteSec", "Chongqing", "Sector-12", "New Tokyo", "Aevum",
"Ishima", "Volhaven", "Speakers for the Dead", "The Dark Army",
"The Syndicate", "Silhouette", "Netburners", "Tian Di Hui", "CyberSec"];
var fdWkAvailable = ["Illuminati", "Daedalus", "The Covenant", "ECorp", "MegaCorp",
"Bachman & Associates", "Blade Industries", "NWO", "Clarke Incorporated",
"OmniTek Incorporated", "Four Sigma", "KuaiGong International",
"The Black Hand", "Chongqing", "Sector-12", "New Tokyo", "Aevum",
"Ishima", "Volhaven", "Speakers for the Dead", "The Dark Army",
"The Syndicate", "Silhouette", "Tetrads", "Slum Snakes"];
var scWkAvailable = ["ECorp", "MegaCorp",
"Bachman & Associates", "Blade Industries", "NWO", "Clarke Incorporated",
"OmniTek Incorporated", "Four Sigma", "KuaiGong International",
"Fulcrum Secret Technologies", "Chongqing", "Sector-12", "New Tokyo", "Aevum",
"Ishima", "Volhaven", "Speakers for the Dead",
"The Syndicate", "Tetrads", "Slum Snakes", "Tian Di Hui"];
switch (type.toLowerCase()) {
case "hacking":
case "hacking contracts":
case "hackingcontracts":
if (!hackAvailable.includes(fac.name)) {
workerScript.scriptRef.log("ERROR: Cannot carry out hacking contracts for " + fac.name + ". workForFaction() failed");
return false;
}
Player.startFactionHackWork(fac);
workerScript.scriptRef.log("Started carrying out hacking contracts for " + fac.name);
return true;
case "field":
case "fieldwork":
case "field work":
if (!fdWkAvailable.includes(fac.name)) {
workerScript.scriptRef.log("ERROR: Cannot carry out field missions for " + fac.name + ". workForFaction() failed");
return false;
}
Player.startFactionFieldWork(fac);
workerScript.scriptRef.log("Started carrying out field missions for " + fac.name);
return true;
case "security":
case "securitywork":
case "security work":
if (!scWkAvailable.includes(fac.name)) {
workerScript.scriptRef.log("ERROR: Cannot serve as security detail for " + fac.name + ". workForFaction() failed");
return false;
}
Player.startFactionSecurityWork(fac);
workerScript.scriptRef.log("Started serving as security details for " + fac.name);
return true;
default:
workerScript.scriptRef.log("ERROR: Invalid work type passed into workForFaction(): " + type);
}
return true;
},
getFactionRep(name) {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 2)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run getFactionRep(). It is a Singularity Function and requires SourceFile-4 (level 2) to run.");
return -1;
}
}
if (!factionExists(name)) {
workerScript.scriptRef.log("ERROR: Faction specified in getFactionRep() does not exist.");
return -1;
}
return Factions[name].playerReputation;
},
createProgram(name) {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 3)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run createProgram(). It is a Singularity Function and requires SourceFile-4 (level 3) to run.");
return false;
}
}
if (Player.isWorking) {
var txt = Player.singularityStopWork();
workerScript.scriptRef.log(txt);
}
switch(name.toLowerCase()) {
case Programs.NukeProgram.toLowerCase():
Player.startCreateProgramWork(Programs.NukeProgram, CONSTANTS.MillisecondsPerFiveMinutes, 1);
break;
case Programs.BruteSSHProgram.toLowerCase():
if (Player.hacking_skill < 50) {
workerScript.scriptRef.log("ERROR: createProgram() failed because hacking level is too low to create BruteSSH (level 50 req)");
return false;
}
Player.startCreateProgramWork(Programs.BruteSSHProgram, CONSTANTS.MillisecondsPerFiveMinutes * 2, 50);
break;
case Programs.FTPCrackProgram.toLowerCase():
if (Player.hacking_skill < 100) {
workerScript.scriptRef.log("ERROR: createProgram() failed because hacking level is too low to create FTPCrack (level 100 req)");
return false;
}
Player.startCreateProgramWork(Programs.FTPCrackProgram, CONSTANTS.MillisecondsPerHalfHour, 100);
break;
case Programs.RelaySMTPProgram.toLowerCase():
if (Player.hacking_skill < 250) {
workerScript.scriptRef.log("ERROR: createProgram() failed because hacking level is too low to create relaySMTP (level 250 req)");
return false;
}
Player.startCreateProgramWork(Programs.RelaySMTPProgram, CONSTANTS.MillisecondsPer2Hours, 250);
break;
case Programs.HTTPWormProgram.toLowerCase():
if (Player.hacking_skill < 500) {
workerScript.scriptRef.log("ERROR: createProgram() failed because hacking level is too low to create HTTPWorm (level 500 req)");
return false;
}
Player.startCreateProgramWork(Programs.HTTPWormProgram, CONSTANTS.MillisecondsPer4Hours, 500);
break;
case Programs.SQLInjectProgram.toLowerCase():
if (Player.hacking_skill < 750) {
workerScript.scriptRef.log("ERROR: createProgram() failed because hacking level is too low to create SQLInject (level 750 req)");
return false;
}
Player.startCreateProgramWork(Programs.SQLInjectProgram, CONSTANTS.MillisecondsPer8Hours, 750);
break;
case Programs.DeepscanV1.toLowerCase():
if (Player.hacking_skill < 75) {
workerScript.scriptRef.log("ERROR: createProgram() failed because hacking level is too low to create DeepscanV1 (level 75 req)");
return false;
}
Player.startCreateProgramWork(Programs.DeepscanV1, CONSTANTS.MillisecondsPerQuarterHour, 75);
break;
case Programs.DeepscanV2.toLowerCase():
if (Player.hacking_skill < 400) {
workerScript.scriptRef.log("ERROR: createProgram() failed because hacking level is too low to create DeepscanV2 (level 400 req)");
return false;
}
Player.startCreateProgramWork(Programs.DeepscanV2, CONSTANTS.MillisecondsPer2Hours, 400);
break;
case Programs.ServerProfiler.toLowerCase():
if (Player.hacking_skill < 75) {
workerScript.scriptRef.log("ERROR: createProgram() failed because hacking level is too low to create ServerProfiler (level 75 req)");
return false;
}
Player.startCreateProgramWork(Programs.ServerProfiler, CONSTANTS.MillisecondsPerHalfHour, 75);
break;
case Programs.AutoLink.toLowerCase():
if (Player.hacking_skill < 25) {
workerScript.scriptRef.log("ERROR: createProgram() failed because hacking level is too low to create AutoLink (level 25 req)");
return false;
}
Player.startCreateProgramWork(Programs.AutoLink, CONSTANTS.MillisecondsPerQuarterHour, 25);
break;
default:
workerScript.scriptRef.log("ERROR: createProgram() failed because the specified program does not exist: " + name);
return false;
}
workerScript.scriptRef.log("Began creating program: " + name);
return true;
},
getAugmentationCost(name) {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 3)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run getAugmentationCost(). It is a Singularity Function and requires SourceFile-4 (level 3) to run.");
return false;
}
}
if (!augmentationExists(name)) {
workerScript.scriptRef.log("ERROR: getAugmentationCost() failed. Invalid Augmentation name passed in (note: this is case-sensitive): " + name);
return [-1, -1];
}
var aug = Augmentations[name];
return [aug.baseRepRequirement, aug.baseCost];
},
purchaseAugmentation(faction, name) {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 3)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run purchaseAugmentation(). It is a Singularity Function and requires SourceFile-4 (level 3) to run.");
return false;
}
}
var fac = Factions[faction];
if (fac === null || !(fac instanceof Faction)) {
workerScript.scriptRef.log("ERROR: purchaseAugmentation() failed because of invalid faction name: " + faction);
return false;
}
if (!fac.augmentations.includes(name)) {
workerScript.scriptRef.log("ERROR: purchaseAugmentation() failed because the faction " + faction + " does not contain the " + name + " augmentation");
return false;
}
var aug = Augmentations[name];
if (aug === null || !(aug instanceof Augmentation)) {
workerScript.scriptRef.log("ERROR: purchaseAugmentation() failed because of invalid augmentation name: " + name);
return false;
}
for (var j = 0; j < Player.queuedAugmentations.length; ++j) {
if (Player.queuedAugmentations[j].name === aug.name) {
workerScript.scriptRef.log("ERROR: purchaseAugmentation() failed because you already have " + name);
return false;
}
}
for (var j = 0; j < Player.augmentations.length; ++j) {
if (Player.augmentations[j].name === aug.name) {
workerScript.scriptRef.log("ERROR: purchaseAugmentation() failed because you already have " + name);
return false;
}
}
if (fac.playerReputation < aug.baseRepRequirement) {
workerScript.scriptRef.log("ERROR: purchaseAugmentation() failed because you do not have enough reputation with " + fac.name);
return false;
}
var res = purchaseAugmentation(aug, fac, true);
workerScript.scriptRef.log(res);
if (isString(res) && res.startsWith("You purchased")) {
return true;
} else {
return false;
}
},
installAugmentations() {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 3)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run installAugmentations(). It is a Singularity Function and requires SourceFile-4 (level 3) to run.");
return false;
}
}
if (Player.queuedAugmentations.length === 0) {
workerScript.scriptRef.log("ERROR: installAugmentations() failed because you do not have any Augmentations to be installed");
return false;
}
workerScript.scriptRef.log("Installing Augmentations. This will cause this script to be killed");
installAugmentations();
return true;
}
} }
} }
export {NetscriptFunctions, initSingularitySFFlags, hasSingularitySF};

@ -1,8 +1,18 @@
/* Worker code, contains Netscript scripts that are actually running */ import {addActiveScriptsItem,
deleteActiveScriptsItem,
updateActiveScriptsItems} from "./ActiveScriptsUI.js";
import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js";
import {Environment} from "./NetscriptEnvironment.js";
import {evaluate, isScriptErrorMessage} from "./NetscriptEvaluator.js";
import {AllServers} from "./Server.js";
import {Settings} from "./Settings.js";
import {parse} from "../utils/acorn.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {compareArrays, printArray} from "../utils/HelperFunctions.js";
//TODO Tested For and while and generic call statements. Have not tested if statements
/* Actual Worker Code */
function WorkerScript(runningScriptObj) { function WorkerScript(runningScriptObj) {
this.name = runningScriptObj.filename; this.name = runningScriptObj.filename;
this.running = false; this.running = false;
@ -23,9 +33,9 @@ WorkerScript.prototype.getServer = function() {
} }
//Array containing all scripts that are running across all servers, to easily run them all //Array containing all scripts that are running across all servers, to easily run them all
var workerScripts = []; let workerScripts = [];
var NetscriptPorts = { let NetscriptPorts = {
Port1: [], Port1: [],
Port2: [], Port2: [],
Port3: [], Port3: [],
@ -38,6 +48,14 @@ var NetscriptPorts = {
Port10: [], Port10: [],
} }
function prestigeWorkerScripts() {
for (var i = 0; i < workerScripts.length; ++i) {
deleteActiveScriptsItem(workerScripts[i]);
workerScripts[i].env.stopFlag = true;
}
workerScripts.length = 0;
}
//Loop through workerScripts and run every script that is not currently running //Loop through workerScripts and run every script that is not currently running
function runScriptsLoop() { function runScriptsLoop() {
//Run any scripts that haven't been started //Run any scripts that haven't been started
@ -45,7 +63,7 @@ function runScriptsLoop() {
//If it isn't running, start the script //If it isn't running, start the script
if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) { if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) {
try { try {
var ast = acorn.parse(workerScripts[i].code); var ast = parse(workerScripts[i].code);
//console.log(ast); //console.log(ast);
} catch (e) { } catch (e) {
console.log("Error parsing script: " + workerScripts[i].name); console.log("Error parsing script: " + workerScripts[i].name);
@ -64,9 +82,10 @@ function runScriptsLoop() {
w.env.stopFlag = true; w.env.stopFlag = true;
w.scriptRef.log("Script finished running"); w.scriptRef.log("Script finished running");
}, function(w) { }, function(w) {
//console.log(w);
if (w instanceof Error) { if (w instanceof Error) {
dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer"); dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer");
console.log("ERROR: Evaluating workerscript returns an Error. THIS SHOULDN'T HAPPEN"); console.log("ERROR: Evaluating workerscript returns an Error. THIS SHOULDN'T HAPPEN: " + w.toString());
return; return;
} else if (w instanceof WorkerScript) { } else if (w instanceof WorkerScript) {
if (isScriptErrorMessage(w.errorMessage)) { if (isScriptErrorMessage(w.errorMessage)) {
@ -92,7 +111,7 @@ function runScriptsLoop() {
} else if (isScriptErrorMessage(w)) { } else if (isScriptErrorMessage(w)) {
dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer"); dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer");
console.log("ERROR: Evaluating workerscript returns only error message rather than WorkerScript object. THIS SHOULDN'T HAPPEN"); console.log("ERROR: Evaluating workerscript returns only error message rather than WorkerScript object. THIS SHOULDN'T HAPPEN: " + w.toString());
return; return;
} else { } else {
dialogBoxCreate("An unknown script died for an unknown reason. This is a bug please contact game dev"); dialogBoxCreate("An unknown script died for an unknown reason. This is a bug please contact game dev");
@ -182,4 +201,6 @@ function updateOnlineScriptTimes(numCycles = 1) {
} }
} }
runScriptsLoop(); export {WorkerScript, workerScripts, NetscriptPorts, runScriptsLoop,
killWorkerScript, addWorkerScript, updateOnlineScriptTimes,
prestigeWorkerScripts};

File diff suppressed because it is too large Load Diff

@ -1,113 +1,49 @@
/* Prestige functions */ import {deleteActiveScriptsItem} from "./ActiveScriptsUI.js";
import {Augmentations, augmentationExists,
initAugmentations, AugmentationNames} from "./Augmentations.js";
import {initBitNodeMultipliers} from "./BitNode.js";
import {Companies, Company, initCompanies} from "./Company.js";
import {Programs} from "./CreateProgram.js";
import {Engine} from "./engine.js";
import {Factions, Faction, initFactions,
joinFaction} from "./Faction.js";
import {Locations} from "./Location.js";
import {initMessages, Messages, Message} from "./Message.js";
import {WorkerScript, workerScripts,
prestigeWorkerScripts} from "./NetscriptWorker.js";
import {Player} from "./Player.js";
import {AllServers, AddToAllServers,
initForeignServers, Server,
prestigeAllServers,
prestigeHomeComputer} from "./Server.js";
import {SpecialServerIps, SpecialServerIpsMap,
prestigeSpecialServerIps,
SpecialServerNames} from "./SpecialServerIps.js";
import {initStockMarket, initSymbolToStockMap,
stockMarketContentCreated,
setStockMarketContentCreated} from "./StockMarket.js";
import {Terminal, postNetburnerText} from "./Terminal.js";
import Decimal from '../utils/decimal.js';
//Prestige by purchasing augmentation //Prestige by purchasing augmentation
function prestigeAugmentation() { function prestigeAugmentation() {
initBitNodeMultipliers(); initBitNodeMultipliers();
//Crime statistics Player.prestigeAugmentation();
Player.numTimesShoplifted = 0;
Player.numPeopleMugged = 0;
Player.numTimesDealtDrugs = 0;
Player.numTimesTraffickArms = 0;
Player.numPeopleKilled = 0;
Player.numTimesGrandTheftAuto = 0;
Player.numTimesKidnapped = 0;
Player.numTimesHeist = 0;
Player.karma = 0;
//Reset stats
Player.hacking_skill = 1;
Player.strength = 1;
Player.defense = 1;
Player.dexterity = 1;
Player.agility = 1;
Player.charisma = 1;
Player.hacking_exp = 0;
Player.strength_exp = 0;
Player.defense_exp = 0;
Player.dexterity_exp = 0;
Player.agility_exp = 0;
Player.charisma_exp = 0;
Player.money = new Decimal(1000);
Player.city = Locations.Sector12;
Player.location = "";
Player.companyName = "";
Player.companyPosition = "";
Player.currentServer = "";
Player.discoveredServers = [];
Player.purchasedServers = [];
Player.factions = [];
Player.factionInvitations = [];
Player.queuedAugmentations = [];
Player.startAction = false;
Player.actionTime = 0;
Player.isWorking = false;
Player.currentWorkFactionName = "";
Player.currentWorkFactionDescription = "";
this.createProgramName = "";
this.className = "";
this.crimeType = "";
Player.workHackExpGainRate = 0;
Player.workStrExpGainRate = 0;
Player.workDefExpGainRate = 0;
Player.workDexExpGainRate = 0;
Player.workAgiExpGainRate = 0;
Player.workChaExpGainRate = 0;
Player.workRepGainRate = 0;
Player.workMoneyGainRate = 0;
Player.workHackExpGained = 0;
Player.workStrExpGained = 0;
Player.workDefExpGained = 0;
Player.workDexExpGained = 0;
Player.workAgiExpGained = 0;
Player.workChaExpGained = 0;
Player.workRepGained = 0;
Player.workMoneyGained = 0;
Player.timeWorked = 0;
Player.lastUpdate = new Date().getTime();
//Delete all Worker Scripts objects //Delete all Worker Scripts objects
for (var i = 0; i < workerScripts.length; ++i) { prestigeWorkerScripts();
deleteActiveScriptsItem(workerScripts[i]);
workerScripts[i].env.stopFlag = true;
}
workerScripts.length = 0;
var homeComp = Player.getHomeComputer(); var homeComp = Player.getHomeComputer();
//Delete all servers except home computer //Delete all servers except home computer
for (var member in AllServers) { prestigeAllServers();
delete AllServers[member];
}
AllServers = {};
//Delete Special Server IPs //Delete Special Server IPs
for (var member in SpecialServerIps) { prestigeSpecialServerIps(); //Must be done before initForeignServers()
delete SpecialServerIps[member];
}
SpecialServersIps = null;
//Reset home computer (only the programs) and add to AllServers //Reset home computer (only the programs) and add to AllServers
homeComp.programs.length = 0; prestigeHomeComputer(homeComp);
homeComp.runningScripts = [];
homeComp.serversOnNetwork = [];
homeComp.isConnectedTo = true;
homeComp.ramUsed = 0;
homeComp.programs.push(Programs.NukeProgram);
if (augmentationExists(AugmentationNames.Neurolink) && if (augmentationExists(AugmentationNames.Neurolink) &&
Augmentations[AugmentationNames.Neurolink].owned) { Augmentations[AugmentationNames.Neurolink].owned) {
homeComp.programs.push(Programs.FTPCrackProgram); homeComp.programs.push(Programs.FTPCrackProgram);
@ -115,31 +51,18 @@ function prestigeAugmentation() {
} }
if (augmentationExists(AugmentationNames.CashRoot) && if (augmentationExists(AugmentationNames.CashRoot) &&
Augmentations[AugmentationNames.CashRoot].owned) { Augmentations[AugmentationNames.CashRoot].owned) {
Player.money = new Decimal(1000000); Player.setMoney(new Decimal(1000000));
homeComp.programs.push(Programs.BruteSSHProgram); homeComp.programs.push(Programs.BruteSSHProgram);
} }
Player.currentServer = homeComp.ip;
Player.homeComputer = homeComp.ip;
AddToAllServers(homeComp); AddToAllServers(homeComp);
//Re-create foreign servers //Re-create foreign servers
SpecialServerIps = new SpecialServerIpsMap(); //Must be done before initForeignServers()
initForeignServers(); initForeignServers();
//Darkweb is purchase-able //Darkweb is purchase-able
document.getElementById("location-purchase-tor").setAttribute("class", "a-link-button"); document.getElementById("location-purchase-tor").setAttribute("class", "a-link-button");
//Reset statistics of all scripts on home computer
for (var i = 0; i < homeComp.scripts.length; ++i) {
var s = homeComp.scripts[i];
}
//Delete messages on home computer
homeComp.messages.length = 0;
//Delete Hacknet Nodes
Player.hacknetNodes.length = 0;
Player.totalHacknetNodeProduction = 0;
//Gain favor for Companies //Gain favor for Companies
for (var member in Companies) { for (var member in Companies) {
if (Companies.hasOwnProperty(member)) { if (Companies.hasOwnProperty(member)) {
@ -177,7 +100,7 @@ function prestigeAugmentation() {
if (Player.hasWseAccount) { if (Player.hasWseAccount) {
initStockMarket(); initStockMarket();
initSymbolToStockMap(); initSymbolToStockMap();
stockMarketContentCreated = false; setStockMarketContentCreated(false);
var stockMarketList = document.getElementById("stock-market-list"); var stockMarketList = document.getElementById("stock-market-list");
while(stockMarketList.firstChild) { while(stockMarketList.firstChild) {
stockMarketList.removeChild(stockMarketList.firstChild); stockMarketList.removeChild(stockMarketList.firstChild);
@ -192,8 +115,6 @@ function prestigeAugmentation() {
} }
} }
Player.playtimeSinceLastAug = 0;
var mainMenu = document.getElementById("mainmenu-container"); var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible"; mainMenu.style.visibility = "visible";
Engine.loadTerminalContent(); Engine.loadTerminalContent();
@ -216,110 +137,22 @@ function prestigeSourceFile() {
initBitNodeMultipliers(); initBitNodeMultipliers();
//Crime statistics //Crime statistics
Player.numTimesShoplifted = 0; Player.prestigeSourceFile();
Player.numPeopleMugged = 0;
Player.numTimesDealtDrugs = 0;
Player.numTimesTraffickArms = 0;
Player.numPeopleKilled = 0;
Player.numTimesGrandTheftAuto = 0;
Player.numTimesKidnapped = 0;
Player.numTimesHeist = 0;
Player.karma = 0;
//Reset stats
Player.hacking_skill = 1;
Player.strength = 1;
Player.defense = 1;
Player.dexterity = 1;
Player.agility = 1;
Player.charisma = 1;
Player.hacking_exp = 0;
Player.strength_exp = 0;
Player.defense_exp = 0;
Player.dexterity_exp = 0;
Player.agility_exp = 0;
Player.charisma_exp = 0;
Player.money = new Decimal(1000);
Player.city = Locations.Sector12;
Player.location = "";
Player.companyName = "";
Player.companyPosition = "";
Player.currentServer = "";
Player.discoveredServers = [];
Player.purchasedServers = [];
Player.factions = [];
Player.factionInvitations = [];
Player.queuedAugmentations = [];
Player.augmentations = [];
Player.startAction = false;
Player.actionTime = 0;
Player.isWorking = false;
Player.currentWorkFactionName = "";
Player.currentWorkFactionDescription = "";
this.createProgramName = "";
this.className = "";
this.crimeType = "";
Player.workHackExpGainRate = 0;
Player.workStrExpGainRate = 0;
Player.workDefExpGainRate = 0;
Player.workDexExpGainRate = 0;
Player.workAgiExpGainRate = 0;
Player.workChaExpGainRate = 0;
Player.workRepGainRate = 0;
Player.workMoneyGainRate = 0;
Player.workHackExpGained = 0;
Player.workStrExpGained = 0;
Player.workDefExpGained = 0;
Player.workDexExpGained = 0;
Player.workAgiExpGained = 0;
Player.workChaExpGained = 0;
Player.workRepGained = 0;
Player.workMoneyGained = 0;
Player.timeWorked = 0;
Player.lastUpdate = new Date().getTime();
//Delete all Worker Scripts objects //Delete all Worker Scripts objects
for (var i = 0; i < workerScripts.length; ++i) { prestigeWorkerScripts();
deleteActiveScriptsItem(workerScripts[i]);
workerScripts[i].env.stopFlag = true;
}
workerScripts.length = 0;
var homeComp = Player.getHomeComputer(); var homeComp = Player.getHomeComputer();
//Delete all servers except home computer //Delete all servers except home computer
for (var member in AllServers) { prestigeAllServers(); //Must be done before initForeignServers()
delete AllServers[member];
}
AllServers = {};
//Delete Special Server IPs //Delete Special Server IPs
for (var member in SpecialServerIps) { prestigeSpecialServerIps();
delete SpecialServerIps[member];
}
SpecialServersIps = null;
//Reset home computer (only the programs) and add to AllServers //Reset home computer (only the programs) and add to AllServers
homeComp.programs.length = 0; prestigeHomeComputer(homeComp);
homeComp.runningScripts = [];
homeComp.serversOnNetwork = [];
homeComp.isConnectedTo = true;
homeComp.ramUsed = 0;
homeComp.programs.push(Programs.NukeProgram);
var srcFile1Owned = false; var srcFile1Owned = false;
for (var i = 0; i < Player.sourceFiles.length; ++i) { for (var i = 0; i < Player.sourceFiles.length; ++i) {
if (Player.sourceFiles[i].n == 1) { if (Player.sourceFiles[i].n == 1) {
@ -327,32 +160,19 @@ function prestigeSourceFile() {
} }
} }
if (srcFile1Owned) { if (srcFile1Owned) {
homeComp.maxRam = 32; homeComp.setMaxRam(32);
} else { } else {
homeComp.maxRam = 8; homeComp.setMaxRam(8);
} }
Player.currentServer = homeComp.ip;
Player.homeComputer = homeComp.ip;
AddToAllServers(homeComp); AddToAllServers(homeComp);
//Re-create foreign servers //Re-create foreign servers
SpecialServerIps = new SpecialServerIpsMap(); //Must be done before initForeignServers()
initForeignServers(); initForeignServers();
//Darkweb is purchase-able //Darkweb is purchase-able
document.getElementById("location-purchase-tor").setAttribute("class", "a-link-button"); document.getElementById("location-purchase-tor").setAttribute("class", "a-link-button");
//Reset statistics of all scripts on home computer
for (var i = 0; i < homeComp.scripts.length; ++i) {
var s = homeComp.scripts[i];
}
//Delete messages on home computer
homeComp.messages.length = 0;
//Delete Hacknet Nodes
Player.hacknetNodes.length = 0;
Player.totalHacknetNodeProduction = 0;
//Reset favor for Companies //Reset favor for Companies
for (var member in Companies) { for (var member in Companies) {
if (Companies.hasOwnProperty(member)) { if (Companies.hasOwnProperty(member)) {
@ -393,16 +213,9 @@ function prestigeSourceFile() {
//Messages //Messages
initMessages(); initMessages();
//Gang
Player.gang = null;
//Reset Stock market
Player.hasWseAccount = false;
Player.hasTixApiAccess = false;
Player.playtimeSinceLastAug = 0;
var mainMenu = document.getElementById("mainmenu-container"); var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible"; mainMenu.style.visibility = "visible";
Engine.loadTerminalContent(); Engine.loadTerminalContent();
} }
export {prestigeAugmentation, prestigeSourceFile};

@ -1,3 +1,16 @@
import {BitNode, BitNodes} from "./BitNode.js";
import {Engine} from "./engine.js";
import {Player} from "./Player.js";
import {prestigeSourceFile} from "./Prestige.js";
import {SourceFiles, SourceFile,
PlayerOwnedSourceFile} from "./SourceFile.js";
import {Terminal} from "./Terminal.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {clearEventListeners} from "../utils/HelperFunctions.js";
import {yesNoBoxCreate, yesNoBoxGetYesButton,
yesNoBoxGetNoButton, yesNoBoxClose} from "../utils/YesNoBox.js";
/* RedPill.js /* RedPill.js
* Implements what happens when you have Red Pill augmentation and then hack the world daemon */ * Implements what happens when you have Red Pill augmentation and then hack the world daemon */
@ -38,7 +51,7 @@ function writeRedPillLetter(pElem, line, i=0) {
}); });
} }
redPillFlag = false; let redPillFlag = false;
function hackWorldDaemon(currentNodeNumber) { function hackWorldDaemon(currentNodeNumber) {
redPillFlag = true; redPillFlag = true;
Engine.loadRedPillContent(); Engine.loadRedPillContent();
@ -193,7 +206,7 @@ function loadBitVerse(destroyedBitNodeNum) {
var elemId = "bitnode-" + i.toString(); var elemId = "bitnode-" + i.toString();
var elem = clearEventListeners(elemId); var elem = clearEventListeners(elemId);
if (elem == null) {return;} if (elem == null) {return;}
if (i == 1 || i == 2) { if (i === 1 || i === 2 || i === 4 || i === 11) {
elem.addEventListener("click", function() { elem.addEventListener("click", function() {
var bitNodeKey = "BitNode" + i; var bitNodeKey = "BitNode" + i;
var bitNode = BitNodes[bitNodeKey]; var bitNode = BitNodes[bitNodeKey];
@ -282,6 +295,7 @@ function createBitNodeYesNoEventListeners(newBitNode, destroyedBitNode) {
//Set new Bit Node //Set new Bit Node
Player.bitNodeN = newBitNode; Player.bitNodeN = newBitNode;
console.log("Entering Bit Node " + Player.bitNodeN);
//Reenable terminal //Reenable terminal
$("#hack-progress-bar").attr('id', "old-hack-progress-bar"); $("#hack-progress-bar").attr('id', "old-hack-progress-bar");
@ -293,7 +307,6 @@ function createBitNodeYesNoEventListeners(newBitNode, destroyedBitNode) {
prestigeSourceFile(); prestigeSourceFile();
yesNoBoxClose(); yesNoBoxClose();
//TODO Dialog box for going ot new Bit node
}); });
var noBtn = yesNoBoxGetNoButton(); var noBtn = yesNoBoxGetNoButton();
noBtn.innerHTML = "Back"; noBtn.innerHTML = "Back";
@ -302,3 +315,5 @@ function createBitNodeYesNoEventListeners(newBitNode, destroyedBitNode) {
}); });
} }
export {redPillFlag, hackWorldDaemon};

@ -1,7 +1,33 @@
import {loadAliases, loadGlobalAliases,
Aliases, GlobalAliases} from "./Alias.js";
import {loadCompanies, Companies,
CompanyPositions} from "./Company.js";
import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js";
import {loadFactions, Factions,
processPassiveFactionRepGain} from "./Faction.js";
import {loadAllGangs, AllGangs} from "./Gang.js";
import {processAllHacknetNodeEarnings} from "./HacknetNode.js";
import {loadMessages, initMessages, Messages} from "./Message.js";
import {Player, loadPlayer} from "./Player.js";
import {loadAllRunningScripts} from "./Script.js";
import {AllServers, loadAllServers} from "./Server.js";
import {loadSettings, initSettings, Settings} from "./Settings.js";
import {loadSpecialServerIps, SpecialServerIps} from "./SpecialServerIps.js";
import {loadStockMarket, StockMarket} from "./StockMarket.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {gameOptionsBoxClose} from "../utils/GameOptions.js";
import {clearEventListeners} from "../utils/HelperFunctions.js";
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js";
import {formatNumber} from "../utils/StringHelperFunctions.js";
import Decimal from '../utils/decimal.js';
/* SaveObject.js /* SaveObject.js
* Defines the object used to save/load games * Defines the object used to save/load games
*/ */
var saveObject = new BitburnerSaveObject(); let saveObject = new BitburnerSaveObject();
function BitburnerSaveObject() { function BitburnerSaveObject() {
this.PlayerSave = ""; this.PlayerSave = "";
@ -53,7 +79,7 @@ BitburnerSaveObject.prototype.saveGame = function() {
Engine.createStatusText("Game saved!"); Engine.createStatusText("Game saved!");
} }
loadGame = function(saveObj) { function loadGame(saveObj) {
if (!window.localStorage.getItem("bitburnerSave")) { if (!window.localStorage.getItem("bitburnerSave")) {
console.log("No save file to load"); console.log("No save file to load");
return false; return false;
@ -61,39 +87,33 @@ loadGame = function(saveObj) {
var saveString = decodeURIComponent(escape(atob(window.localStorage.getItem("bitburnerSave")))); var saveString = decodeURIComponent(escape(atob(window.localStorage.getItem("bitburnerSave"))));
saveObj = JSON.parse(saveString, Reviver); saveObj = JSON.parse(saveString, Reviver);
Player = JSON.parse(saveObj.PlayerSave, Reviver); loadPlayer(saveObj.PlayerSave);
loadAllServers(saveObj.AllServersSave);
//Parse Decimal.js objects loadCompanies(saveObj.CompaniesSave);
Player.money = new Decimal(Player.money); loadFactions(saveObj.FactionsSave);
Player.total_money = new Decimal(Player.total_money); loadSpecialServerIps(saveObj.SpecialServerIpsSave);
Player.lifetime_money = new Decimal(Player.lifetime_money);
AllServers = JSON.parse(saveObj.AllServersSave, Reviver);
Companies = JSON.parse(saveObj.CompaniesSave, Reviver);
Factions = JSON.parse(saveObj.FactionsSave, Reviver);
SpecialServerIps = JSON.parse(saveObj.SpecialServerIpsSave, Reviver);
if (saveObj.hasOwnProperty("AliasesSave")) { if (saveObj.hasOwnProperty("AliasesSave")) {
try { try {
Aliases = JSON.parse(saveObj.AliasesSave, Reviver); loadAliases(saveObj.AliasesSave);
} catch(e) { } catch(e) {
Aliases = {}; loadAliases("");
} }
} else { } else {
Aliases = {}; loadAliases("");
} }
if (saveObj.hasOwnProperty("GlobalAliasesSave")) { if (saveObj.hasOwnProperty("GlobalAliasesSave")) {
try { try {
GlobalAliases = JSON.parse(saveObj.GlobalAliasesSave, Reviver); loadGlobalAliases(saveObj.GlobalAliasesSave);
} catch(e) { } catch(e) {
GlobalAliases = {}; loadGlobalAliases("");
} }
} else { } else {
GlobalAliases = {}; loadGlobalAliases("");
} }
if (saveObj.hasOwnProperty("MessagesSave")) { if (saveObj.hasOwnProperty("MessagesSave")) {
try { try {
Messages = JSON.parse(saveObj.MessagesSave, Reviver); loadMessages(saveObj.MessagesSave);
} catch(e) { } catch(e) {
initMessages(); initMessages();
} }
@ -102,17 +122,18 @@ loadGame = function(saveObj) {
} }
if (saveObj.hasOwnProperty("StockMarketSave")) { if (saveObj.hasOwnProperty("StockMarketSave")) {
try { try {
StockMarket = JSON.parse(saveObj.StockMarketSave, Reviver); loadStockMarket(saveObj.StockMarketSave);
} catch(e) { } catch(e) {
StockMarket = {}; loadStockMarket("");
} }
} else { } else {
StockMarket = {}; loadStockMarket("");
} }
if (saveObj.hasOwnProperty("SettingsSave")) { if (saveObj.hasOwnProperty("SettingsSave")) {
try { try {
Settings = JSON.parse(saveObj.SettingsSave, Reviver); loadSettings(saveObj.SettingsSave);
} catch(e) { } catch(e) {
console.log("ERROR: Failed to parse Settings. Re-initing default values");
initSettings(); initSettings();
} }
} else { } else {
@ -121,13 +142,30 @@ loadGame = function(saveObj) {
if (saveObj.hasOwnProperty("VersionSave")) { if (saveObj.hasOwnProperty("VersionSave")) {
try { try {
var ver = JSON.parse(saveObj.VersionSave, Reviver); var ver = JSON.parse(saveObj.VersionSave, Reviver);
if (ver.startsWith("0.27.")) { if (Player.bitNodeN === null || Player.bitNodeN === 0) {
Player.setBitNodeNumber(1);
}
if (ver.startsWith("0.27.") || ver.startsWith("0.28.")) {
console.log("Evaluating changes needed for version compatibility"); console.log("Evaluating changes needed for version compatibility");
if (Player.bitNodeN == null || Player.bitNodeN == 0) { if (Player.augmentations.length > 0 || Player.queuedAugmentations.length > 0 ||
Player.bitNodeN = 1; Player.sourceFiles.length > 0) {
} //If you have already purchased an Aug...you are far enough in the game
if (Player.sourceFiles == null) { //that everything should be available
Player.sourceFiles = []; Player.firstFacInvRecvd = true;
Player.firstAugPurchased = true;
Player.firstJobRecvd = true;
Player.firstTimeTraveled = true;
Player.firstProgramAvailable = true;
} else {
if (Player.factions.length > 0 || Player.factionInvitations.length > 0) {
Player.firstFacInvRecvd = true;
}
if (Player.companyName !== "" || Player.companyPosition !== "") {
Player.firstJobRecvd = true;
}
if (Player.hacking_skill >= 25) {
Player.firstScriptAvailable = true;
}
} }
} }
if (ver != CONSTANTS.Version) { if (ver != CONSTANTS.Version) {
@ -141,7 +179,7 @@ loadGame = function(saveObj) {
} }
if (Player.bitNodeN == 2 && Player.inGang() && saveObj.hasOwnProperty("AllGangsSave")) { if (Player.bitNodeN == 2 && Player.inGang() && saveObj.hasOwnProperty("AllGangsSave")) {
try { try {
AllGangs = JSON.parse(saveObj.AllGangsSave, Reviver); loadAllGangs(saveObj.AllGangsSave);
} catch(e) { } catch(e) {
console.log("ERROR: Failed to parse AllGangsSave: " + e); console.log("ERROR: Failed to parse AllGangsSave: " + e);
} }
@ -150,24 +188,26 @@ loadGame = function(saveObj) {
return true; return true;
} }
loadImportedGame = function(saveObj, saveString) { function loadImportedGame(saveObj, saveString) {
var tempSaveObj = null; var tempSaveObj = null;
var tempPlayer = null; var tempPlayer = null;
var tempAllServers = null; var tempAllServers = null;
var tempCompanies = null; var tempCompanies = null;
var tempFactions = null; var tempFactions = null;
var tempSpecialServerIps = null; var tempSpecialServerIps = null;
var tempAugmentations = null;
var tempAliases = null; var tempAliases = null;
var tempGlobalAliases = null; var tempGlobalAliases = null;
var tempMessages = null; var tempMessages = null;
var tempStockMarket = null; var tempStockMarket = null;
try {
saveString = decodeURIComponent(escape(atob(saveString)));
tempSaveObj = new BitburnerSaveObject();
tempSaveObj = JSON.parse(saveString, Reviver);
tempPlayer = JSON.parse(tempSaveObj.PlayerSave, Reviver); //Check to see if the imported save file can be parsed. If any
//errors are caught it will fail
try {
var decodedSaveString = decodeURIComponent(escape(atob(saveString)));
tempSaveObj = new BitburnerSaveObject();
tempSaveObj = JSON.parse(decodedSaveString, Reviver);
tempPlayer = JSON.parse(tempSaveObj.PlayerSave, Reviver);
//Parse Decimal.js objects //Parse Decimal.js objects
tempPlayer.money = new Decimal(tempPlayer.money); tempPlayer.money = new Decimal(tempPlayer.money);
@ -178,11 +218,11 @@ loadImportedGame = function(saveObj, saveString) {
tempCompanies = JSON.parse(tempSaveObj.CompaniesSave, Reviver); tempCompanies = JSON.parse(tempSaveObj.CompaniesSave, Reviver);
tempFactions = JSON.parse(tempSaveObj.FactionsSave, Reviver); tempFactions = JSON.parse(tempSaveObj.FactionsSave, Reviver);
tempSpecialServerIps = JSON.parse(tempSaveObj.SpecialServerIpsSave, Reviver); tempSpecialServerIps = JSON.parse(tempSaveObj.SpecialServerIpsSave, Reviver);
tempAugmentations = JSON.parse(tempSaveObj.AugmentationsSave, Reviver);
if (tempSaveObj.hasOwnProperty("AliasesSave")) { if (tempSaveObj.hasOwnProperty("AliasesSave")) {
try { try {
tempAliases = JSON.parse(tempSaveObj.AliasesSave, Reviver); tempAliases = JSON.parse(tempSaveObj.AliasesSave, Reviver);
} catch(e) { } catch(e) {
console.log("Parsing Aliases save failed: " + e);
tempAliases = {}; tempAliases = {};
} }
} else { } else {
@ -192,6 +232,7 @@ loadImportedGame = function(saveObj, saveString) {
try { try {
tempGlobalAliases = JSON.parse(tempSaveObj.AliasesSave, Reviver); tempGlobalAliases = JSON.parse(tempSaveObj.AliasesSave, Reviver);
} catch(e) { } catch(e) {
console.log("Parsing Global Aliases save failed: " + e);
tempGlobalAliases = {}; tempGlobalAliases = {};
} }
} else { } else {
@ -201,6 +242,7 @@ loadImportedGame = function(saveObj, saveString) {
try { try {
tempMessages = JSON.parse(tempSaveObj.MessagesSave, Reviver); tempMessages = JSON.parse(tempSaveObj.MessagesSave, Reviver);
} catch(e) { } catch(e) {
console.log("Parsing Messages save failed: " + e);
initMessages(); initMessages();
} }
} else { } else {
@ -210,6 +252,7 @@ loadImportedGame = function(saveObj, saveString) {
try { try {
tempStockMarket = JSON.parse(saveObj.StockMarketSave, Reviver); tempStockMarket = JSON.parse(saveObj.StockMarketSave, Reviver);
} catch(e) { } catch(e) {
console.log("Parsing StockMarket save failed: " + e);
tempStockMarket = {}; tempStockMarket = {};
} }
} else { } else {
@ -218,7 +261,7 @@ loadImportedGame = function(saveObj, saveString) {
if (tempSaveObj.hasOwnProperty("VersionSave")) { if (tempSaveObj.hasOwnProperty("VersionSave")) {
try { try {
var ver = JSON.parse(tempSaveObj.VersionSave, Reviver); var ver = JSON.parse(tempSaveObj.VersionSave, Reviver);
if (ver == "0.27.0" || ver == "0.27.1") { if (ver.startsWith("0.27.") || ver.startsWith("0.28.")) {
if (tempPlayer.bitNodeN == null || tempPlayer.bitNodeN == 0) { if (tempPlayer.bitNodeN == null || tempPlayer.bitNodeN == 0) {
tempPlayer.bitNodeN = 1; tempPlayer.bitNodeN = 1;
} }
@ -227,13 +270,14 @@ loadImportedGame = function(saveObj, saveString) {
} }
} }
if (ver != CONSTANTS.Version) { if (ver != CONSTANTS.Version) {
createNewUpdateText(); //createNewUpdateText();
} }
} catch(e) { } catch(e) {
createNewUpdateText(); console.log("Parsing Version save failed: " + e);
//createNewUpdateText();
} }
} else { } else {
createNewUpdateText(); //createNewUpdateText();
} }
if (tempPlayer.bitNodeN == 2 && tempPlayer.inGang() && saveObj.hasOwnProperty("AllGangsSave")) { if (tempPlayer.bitNodeN == 2 && tempPlayer.inGang() && saveObj.hasOwnProperty("AllGangsSave")) {
try { try {
@ -243,31 +287,110 @@ loadImportedGame = function(saveObj, saveString) {
} }
} }
} catch(e) { } catch(e) {
dialogBoxCreate("Error importing game"); dialogBoxCreate("Error importing game: " + e.toString());
return false; return false;
} }
saveObj = tempSaveObj; //Since the save file is valid, load everything for real
Player = tempPlayer; saveString = decodeURIComponent(escape(atob(saveString)));
AllServers = tempAllServers; saveObj = JSON.parse(saveString, Reviver);
Companies = tempCompanies;
Factions = tempFactions;
SpecialServerIps = tempSpecialServerIps;
Augmentations = tempAugmentations;
if (tempAliases) {
Aliases = tempAliases;
}
if (tempGlobalAliases) { loadPlayer(saveObj.PlayerSave);
GlobalAliases = tempGlobalAliases; loadAllServers(saveObj.AllServersSave);
} loadCompanies(saveObj.CompaniesSave);
loadFactions(saveObj.FactionsSave);
loadSpecialServerIps(saveObj.SpecialServerIpsSave);
if (tempMessages) { if (saveObj.hasOwnProperty("AliasesSave")) {
Messages = tempMessages; try {
loadAliases(saveObj.AliasesSave);
} catch(e) {
loadAliases("");
}
} else {
loadAliases("");
} }
if (saveObj.hasOwnProperty("GlobalAliasesSave")) {
try {
loadGlobalAliases(saveObj.GlobalAliasesSave);
} catch(e) {
loadGlobalAliases("");
}
} else {
loadGlobalAliases("");
}
if (saveObj.hasOwnProperty("MessagesSave")) {
try {
loadMessages(saveObj.MessagesSave);
} catch(e) {
initMessages();
}
} else {
initMessages();
}
if (saveObj.hasOwnProperty("StockMarketSave")) {
try {
loadStockMarket(saveObj.StockMarketSave);
} catch(e) {
loadStockMarket("");
}
} else {
loadStockMarket("");
}
if (saveObj.hasOwnProperty("SettingsSave")) {
try {
loadSettings(saveObj.SettingsSave);
} catch(e) {
initSettings();
}
} else {
initSettings();
}
if (saveObj.hasOwnProperty("VersionSave")) {
try {
var ver = JSON.parse(saveObj.VersionSave, Reviver);
if (Player.bitNodeN == null || Player.bitNodeN == 0) {
Player.setBitNodeNumber(1);
if (tempStockMarket) { }
StockMarket = tempStockMarket; if (ver.startsWith("0.27.") || ver.startsWith("0.28.")) {
console.log("Evaluating changes needed for version compatibility");
if (Player.augmentations.length > 0 || Player.queuedAugmentations.length > 0 ||
Player.sourceFiles.length > 0) {
//If you have already purchased an Aug...you are far enough in the game
//that everything should be available
Player.firstFacInvRecvd = true;
Player.firstAugPurchased = true;
Player.firstJobRecvd = true;
Player.firstTimeTraveled = true;
Player.firstProgramAvailable = true;
} else {
if (Player.factions.length > 0 || Player.factionInvitations.length > 0) {
Player.firstFacInvRecvd = true;
}
if (Player.companyName !== "" || Player.companyPosition !== "") {
Player.firstJobRecvd = true;
}
if (Player.hacking_skill >= 25) {
Player.firstScriptAvailable = true;
}
}
}
if (ver != CONSTANTS.Version) {
createNewUpdateText();
}
} catch(e) {
createNewUpdateText();
}
} else {
createNewUpdateText();
}
if (Player.bitNodeN == 2 && Player.inGang() && saveObj.hasOwnProperty("AllGangsSave")) {
try {
loadAllGangs(saveObj.AllGangsSave);
} catch(e) {
console.log("ERROR: Failed to parse AllGangsSave: " + e);
}
} }
dialogBoxCreate("Imported game! I would suggest saving the game and then reloading the page " + dialogBoxCreate("Imported game! I would suggest saving the game and then reloading the page " +
@ -337,7 +460,6 @@ BitburnerSaveObject.prototype.exportGame = function() {
this.CompaniesSave = JSON.stringify(Companies); this.CompaniesSave = JSON.stringify(Companies);
this.FactionsSave = JSON.stringify(Factions); this.FactionsSave = JSON.stringify(Factions);
this.SpecialServerIpsSave = JSON.stringify(SpecialServerIps); this.SpecialServerIpsSave = JSON.stringify(SpecialServerIps);
this.AugmentationsSave = JSON.stringify(Augmentations);
this.AliasesSave = JSON.stringify(Aliases); this.AliasesSave = JSON.stringify(Aliases);
this.GlobalAliasesSave = JSON.stringify(GlobalAliases); this.GlobalAliasesSave = JSON.stringify(GlobalAliases);
this.MessagesSave = JSON.stringify(Messages); this.MessagesSave = JSON.stringify(Messages);
@ -380,7 +502,7 @@ BitburnerSaveObject.prototype.deleteGame = function() {
Engine.createStatusText("Game deleted!"); Engine.createStatusText("Game deleted!");
} }
createNewUpdateText = function() { function createNewUpdateText() {
dialogBoxCreate("New update!<br>" + dialogBoxCreate("New update!<br>" +
"Please report any bugs/issues through the github repository " + "Please report any bugs/issues through the github repository " +
"or the Bitburner subreddit (reddit.com/r/bitburner).<br><br>" + "or the Bitburner subreddit (reddit.com/r/bitburner).<br><br>" +
@ -414,3 +536,5 @@ function openImportFileHandler(evt) {
}; };
reader.readAsText(file); reader.readAsText(file);
} }
export {saveObject, loadGame};

@ -1,6 +1,22 @@
/* Script.js var ace = require('brace');
* Script object require('brace/mode/javascript');
*/ require('brace/theme/monokai');
import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js";
import {iTutorialSteps, iTutorialNextStep,
iTutorialIsRunning, currITutorialStep} from "./InteractiveTutorial.js";
import {addWorkerScript, killWorkerScript} from "./NetscriptWorker.js";
import {Player} from "./Player.js";
import {AllServers, processSingleServerGrowth} from "./Server.js";
import {Settings} from "./Settings.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js";
import {compareArrays} from "../utils/HelperFunctions.js";
import {formatNumber, numOccurrences,
numNetscriptOperators} from "../utils/StringHelperFunctions.js";
function scriptEditorInit() { function scriptEditorInit() {
//Initialize save and close button //Initialize save and close button
@ -22,7 +38,7 @@ function scriptEditorInit() {
var end = this.selectionEnd; var end = this.selectionEnd;
//Set textarea value to: text before caret + four spaces + text after caret //Set textarea value to: text before caret + four spaces + text after caret
spaces = " "; let spaces = " ";
this.value = this.value.substring(0, start) + spaces + this.value.substring(end); this.value = this.value.substring(0, start) + spaces + this.value.substring(end);
//Put caret at after the four spaces //Put caret at after the four spaces
@ -34,15 +50,13 @@ function scriptEditorInit() {
document.addEventListener("DOMContentLoaded", scriptEditorInit, false); document.addEventListener("DOMContentLoaded", scriptEditorInit, false);
//Updates line number and RAM usage in script //Updates line number and RAM usage in script
function upgradeScriptEditorContent() { function updateScriptEditorContent() {
var txt = $("#script-editor-text")[0]; var editor = ace.edit('javascript-editor');
var lineNum = txt.value.substr(0, txt.selectionStart).split("\n").length; var code = editor.getValue();
var code = document.getElementById("script-editor-text").value;
var codeCopy = code.repeat(1); var codeCopy = code.repeat(1);
var ramUsage = calculateRamUsage(codeCopy); var ramUsage = calculateRamUsage(codeCopy);
document.getElementById("script-editor-status-text").innerText = document.getElementById("script-editor-status-text").innerText =
"Line Number: " + lineNum + ", RAM: " + formatNumber(ramUsage, 2).toString() + "GB"; "RAM: " + formatNumber(ramUsage, 2).toString() + "GB";
} }
//Define key commands in script editor (ctrl o to save + close, etc.) //Define key commands in script editor (ctrl o to save + close, etc.)
@ -63,7 +77,8 @@ function saveAndCloseScriptEditor() {
dialogBoxCreate("Leave the script name as 'foodnstuff'!"); dialogBoxCreate("Leave the script name as 'foodnstuff'!");
return; return;
} }
var code = document.getElementById("script-editor-text").value; var editor = ace.edit('javascript-editor');
var code = editor.getValue();
code = code.replace(/\s/g, ""); code = code.replace(/\s/g, "");
if (code.indexOf("while(true){hack('foodnstuff');}") == -1) { if (code.indexOf("while(true){hack('foodnstuff');}") == -1) {
dialogBoxCreate("Please copy and paste the code from the tutorial!"); dialogBoxCreate("Please copy and paste the code from the tutorial!");
@ -122,7 +137,8 @@ function Script() {
Script.prototype.saveScript = function() { Script.prototype.saveScript = function() {
if (Engine.currentPage == Engine.Page.ScriptEditor) { if (Engine.currentPage == Engine.Page.ScriptEditor) {
//Update code and filename //Update code and filename
var code = document.getElementById("script-editor-text").value; var editor = ace.edit('javascript-editor');
var code = editor.getValue();
this.code = code.replace(/^\s+|\s+$/g, ''); this.code = code.replace(/^\s+|\s+$/g, '');
var filename = document.getElementById("script-editor-filename").value + ".script"; var filename = document.getElementById("script-editor-filename").value + ".script";
@ -200,6 +216,30 @@ function calculateRamUsage(codeCopy) {
var getHackTimeCount = numOccurrences(codeCopy, "getHackTime(") + var getHackTimeCount = numOccurrences(codeCopy, "getHackTime(") +
numOccurrences(codeCopy, "getGrowTime(") + numOccurrences(codeCopy, "getGrowTime(") +
numOccurrences(codeCopy, "getWeakenTime("); numOccurrences(codeCopy, "getWeakenTime(");
var singFn1Count = numOccurrences(codeCopy, "universityCourse(") +
numOccurrences(codeCopy, "gymWorkout(") +
numOccurrences(codeCopy, "travelToCity(") +
numOccurrences(codeCopy, "purchaseTor(") +
numOccurrences(codeCopy, "purchaseProgram(");
var singFn2Count = numOccurrences(codeCopy, "upgradeHomeRam(") +
numOccurrences(codeCopy, "getUpgradeHomeRamCost(") +
numOccurrences(codeCopy, "workForCompany(") +
numOccurrences(codeCopy, "applyToCompany(") +
numOccurrences(codeCopy, "getCompanyRep(") +
numOccurrences(codeCopy, "checkFactionInvitations(") +
numOccurrences(codeCopy, "joinFaction(") +
numOccurrences(codeCopy, "workForFaction(") +
numOccurrences(codeCopy, "getFactionRep(");
var singFn3Count = numOccurrences(codeCopy, "createProgram(") +
numOccurrences(codeCopy, "getAugmentationCost(") +
numOccurrences(codeCopy, "purchaseAugmentation(") +
numOccurrences(codeCopy, "installAugmentations(");
if (Player.bitNodeN != 4) {
singFn1Count *= 10;
singFn2Count *= 10;
singFn3Count *= 10;
}
return baseRam + return baseRam +
((whileCount * CONSTANTS.ScriptWhileRamCost) + ((whileCount * CONSTANTS.ScriptWhileRamCost) +
@ -238,8 +278,11 @@ function calculateRamUsage(codeCopy) {
(scriptWriteCount * CONSTANTS.ScriptReadWriteRamCost) + (scriptWriteCount * CONSTANTS.ScriptReadWriteRamCost) +
(scriptReadCount * CONSTANTS.ScriptReadWriteRamCost) + (scriptReadCount * CONSTANTS.ScriptReadWriteRamCost) +
(arbScriptCount * CONSTANTS.ScriptArbScriptRamCost) + (arbScriptCount * CONSTANTS.ScriptArbScriptRamCost) +
(getScriptCount * CONSTANTS.ScriptGetScriptCost) + (getScriptCount * CONSTANTS.ScriptGetScriptRamCost) +
(getHackTimeCount * CONSTANTS.ScriptGetHackTimeCost)); (getHackTimeCount * CONSTANTS.ScriptGetHackTimeRamCost) +
(singFn1Count * CONSTANTS.ScriptSingularityFn1RamCost) +
(singFn2Count * CONSTANTS.ScriptSingularityFn2RamCost) +
(singFn3Count * CONSTANTS.ScriptSingularityFn3RamCost));
} }
Script.prototype.toJSON = function() { Script.prototype.toJSON = function() {
@ -255,7 +298,7 @@ Reviver.constructors.Script = Script;
//Called when the game is loaded. Loads all running scripts (from all servers) //Called when the game is loaded. Loads all running scripts (from all servers)
//into worker scripts so that they will start running //into worker scripts so that they will start running
loadAllRunningScripts = function() { function loadAllRunningScripts() {
var count = 0; var count = 0;
var total = 0; var total = 0;
for (var property in AllServers) { for (var property in AllServers) {
@ -278,7 +321,7 @@ loadAllRunningScripts = function() {
console.log("Loaded " + count.toString() + " running scripts"); console.log("Loaded " + count.toString() + " running scripts");
} }
scriptCalculateOfflineProduction = function(runningScriptObj) { function scriptCalculateOfflineProduction(runningScriptObj) {
//The Player object stores the last update time from when we were online //The Player object stores the last update time from when we were online
var thisUpdate = new Date().getTime(); var thisUpdate = new Date().getTime();
var lastUpdate = Player.lastUpdate; var lastUpdate = Player.lastUpdate;
@ -473,6 +516,8 @@ RunningScript.fromJSON = function(value) {
return Generic_fromJSON(RunningScript, value.data); return Generic_fromJSON(RunningScript, value.data);
} }
Reviver.constructors.RunningScript = RunningScript;
//Creates an object that creates a map/dictionary with the IP of each existing server as //Creates an object that creates a map/dictionary with the IP of each existing server as
//a key. Initializes every key with a specified value that can either by a number or an array //a key. Initializes every key with a specified value that can either by a number or an array
function AllServersMap(arr=false) { function AllServersMap(arr=false) {
@ -517,3 +562,6 @@ AllServersMap.fromJSON = function(value) {
} }
Reviver.constructors.AllServersMap = AllServersMap; Reviver.constructors.AllServersMap = AllServersMap;
export {updateScriptEditorContent, loadAllRunningScripts, findRunningScript,
RunningScript, Script, AllServersMap};

@ -1,6 +1,14 @@
//Netburner Server class import {BitNodeMultipliers} from "./BitNode.js";
//TODO Make a map of all IPS in the game so far so that we don't accidentally import {CONSTANTS} from "./Constants.js";
// get duplicate IPs..however unlikely it is import {Programs} from "./CreateProgram.js";
import {Player} from "./Player.js";
import {RunningScript, Script} from "./Script.js";
import {SpecialServerNames, SpecialServerIps} from "./SpecialServerIps.js";
import {getRandomInt} from "../utils/HelperFunctions.js";
import {createRandomIp, isValidIPAddress, ipExists} from "../utils/IPAddress.js";
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js";
function Server(ip=createRandomIp(), hostname="", organizationName="", function Server(ip=createRandomIp(), hostname="", organizationName="",
isConnectedTo=false, adminRights=false, purchasedByPlayer=false, maxRam=0) { isConnectedTo=false, adminRights=false, purchasedByPlayer=false, maxRam=0) {
/* Properties */ /* Properties */
@ -67,9 +75,9 @@ Server.prototype.setHackingParameters = function(requiredHackingSkill, moneyAvai
if (isNaN(moneyAvailable)) { if (isNaN(moneyAvailable)) {
this.moneyAvailable = 1000000; this.moneyAvailable = 1000000;
} else { } else {
this.moneyAvailable = moneyAvailable; this.moneyAvailable = moneyAvailable * BitNodeMultipliers.ServerStartingMoney;
} }
this.moneyMax = 25 * moneyAvailable * BitNodeMultipliers.ServerMaxMoney; this.moneyMax = 25 * this.moneyAvailable * BitNodeMultipliers.ServerMaxMoney;
this.hackDifficulty = hackDifficulty; this.hackDifficulty = hackDifficulty;
this.baseDifficulty = hackDifficulty; this.baseDifficulty = hackDifficulty;
this.minDifficulty = Math.max(1, Math.round(hackDifficulty / 3)); this.minDifficulty = Math.max(1, Math.round(hackDifficulty / 3));
@ -82,6 +90,10 @@ Server.prototype.setPortProperties = function(numOpenPortsReq) {
this.numOpenPortsRequired = numOpenPortsReq; this.numOpenPortsRequired = numOpenPortsReq;
} }
Server.prototype.setMaxRam = function(ram) {
this.maxRam = ram;
}
//The serverOnNetwork array holds the IP of all the servers. This function //The serverOnNetwork array holds the IP of all the servers. This function
//returns the actual Server objects //returns the actual Server objects
Server.prototype.getServerOnNetwork = function(i) { Server.prototype.getServerOnNetwork = function(i) {
@ -110,7 +122,7 @@ Server.prototype.fortify = function(amt) {
} }
Server.prototype.weaken = function(amt) { Server.prototype.weaken = function(amt) {
this.hackDifficulty -= amt; this.hackDifficulty -= (amt * BitNodeMultipliers.ServerWeakenRate);
if (this.hackDifficulty < this.minDifficulty) {this.hackDifficulty = this.minDifficulty;} if (this.hackDifficulty < this.minDifficulty) {this.hackDifficulty = this.minDifficulty;}
if (this.hackDifficulty < 1) {this.hackDifficulty = 1;} if (this.hackDifficulty < 1) {this.hackDifficulty = 1;}
} }
@ -126,7 +138,7 @@ Server.fromJSON = function(value) {
Reviver.constructors.Server = Server; Reviver.constructors.Server = Server;
initForeignServers = function() { function initForeignServers() {
//MegaCorporations //MegaCorporations
var ECorpServer = new Server(createRandomIp(), "ecorp", "ECorp", false, false, false, 0); var ECorpServer = new Server(createRandomIp(), "ecorp", "ECorp", false, false, false, 0);
ECorpServer.setHackingParameters(getRandomInt(1150, 1300), getRandomInt(30000000000, 70000000000), 99, 99); ECorpServer.setHackingParameters(getRandomInt(1150, 1300), getRandomInt(30000000000, 70000000000), 99, 99);
@ -637,7 +649,7 @@ initForeignServers = function() {
} }
//Applied server growth for a single server. Returns the percentage growth //Applied server growth for a single server. Returns the percentage growth
processSingleServerGrowth = function(server, numCycles) { function processSingleServerGrowth(server, numCycles) {
//Server growth processed once every 450 game cycles //Server growth processed once every 450 game cycles
var numServerGrowthCycles = Math.max(Math.floor(numCycles / 450), 0); var numServerGrowthCycles = Math.max(Math.floor(numCycles / 450), 0);
@ -645,11 +657,10 @@ processSingleServerGrowth = function(server, numCycles) {
var growthRate = CONSTANTS.ServerBaseGrowthRate; var growthRate = CONSTANTS.ServerBaseGrowthRate;
var adjGrowthRate = 1 + (growthRate - 1) / server.hackDifficulty; var adjGrowthRate = 1 + (growthRate - 1) / server.hackDifficulty;
if (adjGrowthRate > CONSTANTS.ServerMaxGrowthRate) {adjGrowthRate = CONSTANTS.ServerMaxGrowthRate;} if (adjGrowthRate > CONSTANTS.ServerMaxGrowthRate) {adjGrowthRate = CONSTANTS.ServerMaxGrowthRate;}
//console.log("Adjusted growth rate: " + adjGrowthRate);
//Calculate adjusted server growth rate based on parameters //Calculate adjusted server growth rate based on parameters
var serverGrowthPercentage = server.serverGrowth / 100; var serverGrowthPercentage = server.serverGrowth / 100;
var numServerGrowthCyclesAdjusted = numServerGrowthCycles * serverGrowthPercentage; var numServerGrowthCyclesAdjusted = numServerGrowthCycles * serverGrowthPercentage * BitNodeMultipliers.ServerGrowthRate;
//Apply serverGrowth for the calculated number of growth cycles //Apply serverGrowth for the calculated number of growth cycles
var serverGrowth = Math.pow(adjGrowthRate, numServerGrowthCyclesAdjusted * Player.hacking_grow_mult); var serverGrowth = Math.pow(adjGrowthRate, numServerGrowthCyclesAdjusted * Player.hacking_grow_mult);
@ -666,14 +677,38 @@ processSingleServerGrowth = function(server, numCycles) {
server.moneyAvailable = server.moneyMax; server.moneyAvailable = server.moneyMax;
return 1; return 1;
} }
//Growing increases server security twice as much as hacking
server.fortify(2 * CONSTANTS.ServerFortifyAmount * numServerGrowthCycles); server.fortify(2 * CONSTANTS.ServerFortifyAmount * numServerGrowthCycles);
return serverGrowth; return serverGrowth;
} }
//List of all servers that exist in the game, indexed by their ip function prestigeHomeComputer(homeComp) {
AllServers = {}; homeComp.programs.length = 0;
homeComp.runningScripts = [];
homeComp.serversOnNetwork = [];
homeComp.isConnectedTo = true;
homeComp.ramUsed = 0;
homeComp.programs.push(Programs.NukeProgram);
SizeOfAllServers = function() { homeComp.messages.length = 0;
}
//List of all servers that exist in the game, indexed by their ip
let AllServers = {};
function prestigeAllServers() {
for (var member in AllServers) {
delete AllServers[member];
}
AllServers = {};
}
function loadAllServers(saveString) {
AllServers = JSON.parse(saveString, Reviver);
}
function SizeOfAllServers() {
var size = 0, key; var size = 0, key;
for (key in AllServers) { for (key in AllServers) {
if (AllServers.hasOwnProperty(key)) size++; if (AllServers.hasOwnProperty(key)) size++;
@ -682,7 +717,7 @@ SizeOfAllServers = function() {
} }
//Add a server onto the map of all servers in the game //Add a server onto the map of all servers in the game
AddToAllServers = function(server) { function AddToAllServers(server) {
var serverIp = server.ip; var serverIp = server.ip;
if (ipExists(serverIp)) { if (ipExists(serverIp)) {
console.log("IP of server that's being added: " + serverIp); console.log("IP of server that's being added: " + serverIp);
@ -696,7 +731,7 @@ AddToAllServers = function(server) {
//Returns server object with corresponding hostname //Returns server object with corresponding hostname
// Relatively slow, would rather not use this a lot // Relatively slow, would rather not use this a lot
GetServerByHostname = function(hostname) { function GetServerByHostname(hostname) {
for (var ip in AllServers) { for (var ip in AllServers) {
if (AllServers.hasOwnProperty(ip)) { if (AllServers.hasOwnProperty(ip)) {
if (AllServers[ip].hostname == hostname) { if (AllServers[ip].hostname == hostname) {
@ -708,7 +743,7 @@ GetServerByHostname = function(hostname) {
} }
//Get server by IP or hostname. Returns null if invalid //Get server by IP or hostname. Returns null if invalid
getServer = function(s) { function getServer(s) {
if (!isValidIPAddress(s)) { if (!isValidIPAddress(s)) {
return GetServerByHostname(s); return GetServerByHostname(s);
} else { } else {
@ -717,10 +752,14 @@ getServer = function(s) {
} }
//Debugging tool //Debugging tool
PrintAllServers = function() { function PrintAllServers() {
for (var ip in AllServers) { for (var ip in AllServers) {
if (AllServers.hasOwnProperty(ip)) { if (AllServers.hasOwnProperty(ip)) {
console.log("Ip: " + ip + ", hostname: " + AllServers[ip].hostname); console.log("Ip: " + ip + ", hostname: " + AllServers[ip].hostname);
} }
} }
} }
export {Server, AllServers, getServer, GetServerByHostname, loadAllServers,
AddToAllServers, processSingleServerGrowth, initForeignServers,
prestigeAllServers, prestigeHomeComputer};

@ -1,8 +1,14 @@
import {CONSTANTS} from "./Constants.js";
import {Player} from "./Player.js";
import {AllServers} from "./Server.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {yesNoTxtInpBoxGetInput} from "../utils/YesNoBox.js";
/* Functions to handle any server-related purchasing: /* Functions to handle any server-related purchasing:
* Purchasing new servers * Purchasing new servers
* Purchasing more RAM for home computer * Purchasing more RAM for home computer
*/ */
purchaseServer = function(ram, cost) { function purchaseServer(ram, cost) {
//Check if player has enough money //Check if player has enough money
if (Player.money.lt(cost)) { if (Player.money.lt(cost)) {
dialogBoxCreate("You don't have enough money to purchase this server!"); dialogBoxCreate("You don't have enough money to purchase this server!");
@ -41,7 +47,7 @@ purchaseServer = function(ram, cost) {
} }
purchaseRamForHomeComputer = function(cost) { function purchaseRamForHomeComputer(cost) {
if (Player.money.lt(cost)) { if (Player.money.lt(cost)) {
dialogBoxCreate("You do not have enough money to purchase additional RAM for your home computer"); dialogBoxCreate("You do not have enough money to purchase additional RAM for your home computer");
return; return;
@ -54,3 +60,5 @@ purchaseRamForHomeComputer = function(cost) {
dialogBoxCreate("Purchased additional RAM for home computer! It now has " + homeComputer.maxRam + "GB of RAM."); dialogBoxCreate("Purchased additional RAM for home computer! It now has " + homeComputer.maxRam + "GB of RAM.");
} }
export {purchaseServer, purchaseRamForHomeComputer};

@ -1,5 +1,5 @@
/* Settings.js */ /* Settings.js */
Settings = { let Settings = {
CodeInstructionRunTime: 100, CodeInstructionRunTime: 100,
MaxLogCapacity: 50, MaxLogCapacity: 50,
MaxPortCapacity: 50, MaxPortCapacity: 50,
@ -7,6 +7,10 @@ Settings = {
SuppressFactionInvites: false, SuppressFactionInvites: false,
} }
function loadSettings(saveString) {
Settings = JSON.parse(saveString);
}
function initSettings() { function initSettings() {
Settings.CodeInstructionRunTime = 100; Settings.CodeInstructionRunTime = 100;
Settings.MaxLogCapacity = 50; Settings.MaxLogCapacity = 50;
@ -16,14 +20,42 @@ function initSettings() {
} }
function setSettingsLabels() { function setSettingsLabels() {
document.getElementById("settingsNSExecTimeRangeValLabel").innerHTML var nsExecTime = document.getElementById("settingsNSExecTimeRangeValLabel");
= Settings.CodeInstructionRunTime + "ms"; var nsLogLimit = document.getElementById("settingsNSLogRangeValLabel");
document.getElementById("settingsNSLogRangeValLabel").innerHTML var nsPortLimit = document.getElementById("settingsNSPortRangeValLabel");
= Settings.MaxLogCapacity; var suppressMsgs = document.getElementById("settingsSuppressMessages");
document.getElementById("settingsNSPortRangeValLabel").innerHTML var suppressFactionInv = document.getElementById("settingsSuppressFactionInvites")
= Settings.MaxPortCapacity;
document.getElementById("settingsSuppressMessages").checked //Initialize values on labels
= Settings.SuppressMessages; nsExecTime.innerHTML = Settings.CodeInstructionRunTime + "ms";
document.getElementById("settingsSuppressFactionInvites").checked nsLogLimit.innerHTML = Settings.MaxLogCapacity;
= Settings.SuppressFactionInvites; nsPortLimit.innerHTML = Settings.MaxPortCapacity;
suppressMsgs.checked = Settings.SuppressMessages;
suppressFactionInv.checked = Settings.SuppressFactionInvites;
//Set handlers for when input changes
document.getElementById("settingsNSExecTimeRangeVal").oninput = function() {
nsExecTime.innerHTML = this.value + 'ms';
Settings.CodeInstructionRunTime = this.value;
};
document.getElementById("settingsNSLogRangeVal").oninput = function() {
nsLogLimit.innerHTML = this.value;
Settings.MaxLogCapacity = this.value;
};
document.getElementById("settingsNSPortRangeVal").oninput = function() {
nsPortLimit.innerHTML = this.value;
Settings.MaxPortCapacity = this.value;
};
document.getElementById("settingsSuppressMessages").onclick = function() {
Settings.SuppressMessages = this.checked;
};
document.getElementById("settingsSuppressFactionInvites").onclick = function() {
Settings.SuppressFactionInvites = this.checked;
};
} }
export {Settings, initSettings, setSettingsLabels, loadSettings};

@ -1,5 +1,7 @@
/* SourceFile.js */ import {Player} from "./Player.js";
import {BitNode, BitNodes} from "./BitNode.js";
/* SourceFile.js */
//Each SourceFile corresponds to a BitNode with the same number //Each SourceFile corresponds to a BitNode with the same number
function SourceFile(number, info="") { function SourceFile(number, info="") {
var bitnodeKey = "BitNode" + number; var bitnodeKey = "BitNode" + number;
@ -15,27 +17,33 @@ function SourceFile(number, info="") {
this.owned = false; this.owned = false;
} }
SourceFiles = { let SourceFiles = {};
SourceFile1: new SourceFile(1, "This Source-File lets the player start with 32GB of RAM on his/her " + function initSourceFiles() {
SourceFiles = {};
SourceFiles["SourceFile1"] = new SourceFile(1, "This Source-File lets the player start with 32GB of RAM on his/her " +
"home computer. It also increases all of the player's multipliers by:<br><br>" + "home computer. It also increases all of the player's multipliers by:<br><br>" +
"Level 1: 16%<br>" + "Level 1: 16%<br>" +
"Level 2: 24%<br>" + "Level 2: 24%<br>" +
"Level 3: 28%"), "Level 3: 28%");
SourceFile2: new SourceFile(2, "This Source-File increases the player's crime success rate, crime money, and charisma " + SourceFiles["SourceFile2"] = new SourceFile(2, "This Source-File increases the player's crime success rate, crime money, and charisma " +
"multipliers by:<br><br>" + "multipliers by:<br><br>" +
"Level 1: 20%<br>" + "Level 1: 20%<br>" +
"Level 2: 30%<br>" + "Level 2: 30%<br>" +
"Level 3: 35%"), "Level 3: 35%");
SourceFile3: new SourceFile(3), SourceFiles["SourceFile3"] = new SourceFile(3);
SourceFile4: new SourceFile(4), SourceFiles["SourceFile4"] = new SourceFile(4, "This Source-File lets you access and use the Singularity Functions in every BitNode. Every " +
SourceFile5: new SourceFile(5), "level of this Source-File opens up more of the Singularity Functions you can use.");
SourceFile6: new SourceFile(6), SourceFiles["SourceFile5"] = new SourceFile(5);
SourceFile7: new SourceFile(7), SourceFiles["SourceFile6"] = new SourceFile(6);
SourceFile8: new SourceFile(8), SourceFiles["SourceFile7"] = new SourceFile(7);
SourceFile9: new SourceFile(9), SourceFiles["SourceFile8"] = new SourceFile(8);
SourceFile10: new SourceFile(10), SourceFiles["SourceFile9"] = new SourceFile(9);
SourceFile11: new SourceFile(11), SourceFiles["SourceFile10"] = new SourceFile(10);
SourceFile12: new SourceFile(12), SourceFiles["SourceFile11"] = new SourceFile(11, "This Source-File increases the player's company salary and reputation gain multipliers by:<br><br>" +
"Level 1: 60%<br>" +
"Level 2: 90%<br>" +
"Level 3: 105%<br>");
SourceFiles["SourceFile12"] = new SourceFile(12);
} }
function PlayerOwnedSourceFile(number, level) { function PlayerOwnedSourceFile(number, level) {
@ -97,6 +105,18 @@ function applySourceFile(srcFile) {
Player.crime_success_mult *= incMult; Player.crime_success_mult *= incMult;
Player.charisma_mult *= incMult; Player.charisma_mult *= incMult;
break; break;
case 4: //The Singularity
//No effects, just gives access to Singularity functions
break;
case 11: //The Big Crash
var mult = 0;
for (var i = 0; i < srcFile.lvl; ++i) {
mult += (60 / (Math.pow(2, i)));
}
var incMult = 1 + (mult / 100);
Player.work_money_mult *= incMult;
Player.company_rep_mult *= incMult;
break;
default: default:
console.log("ERROR: Invalid source file number: " + srcFile.n); console.log("ERROR: Invalid source file number: " + srcFile.n);
break; break;
@ -105,18 +125,4 @@ function applySourceFile(srcFile) {
sourceFileObject.owned = true; sourceFileObject.owned = true;
} }
PlayerObject.prototype.reapplyAllSourceFiles = function() { export {SourceFiles, PlayerOwnedSourceFile, applySourceFile, initSourceFiles};
console.log("Re-applying source files");
//Will always be called after reapplyAllAugmentations() so multipliers do not have to be reset
//this.resetMultipliers();
for (i = 0; i < this.sourceFiles.length; ++i) {
var srcFileKey = "SourceFile" + this.sourceFiles[i].n;
var sourceFileObject = SourceFiles[srcFileKey];
if (sourceFileObject == null) {
console.log("ERROR: Invalid source file number: " + this.sourceFiles[i].n);
continue;
}
applySourceFile(this.sourceFiles[i]);
}
}

@ -1,5 +1,8 @@
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js";
/* Holds IP of Special Servers */ /* Holds IP of Special Servers */
SpecialServerNames = { let SpecialServerNames = {
FulcrumSecretTechnologies: "Fulcrum Secret Technologies Server", FulcrumSecretTechnologies: "Fulcrum Secret Technologies Server",
CyberSecServer: "CyberSec Server", CyberSecServer: "CyberSec Server",
NiteSecServer: "NiteSec Server", NiteSecServer: "NiteSec Server",
@ -23,6 +26,25 @@ SpecialServerIpsMap.fromJSON = function(value) {
return Generic_fromJSON(SpecialServerIpsMap, value.data); return Generic_fromJSON(SpecialServerIpsMap, value.data);
} }
Reviver.constructors.SpecialServerIpsMap = SpecialServerIpsMap(); Reviver.constructors.SpecialServerIpsMap = SpecialServerIpsMap;
SpecialServerIps = null; let SpecialServerIps = new SpecialServerIpsMap();
function prestigeSpecialServerIps() {
for (var member in SpecialServerIps) {
delete SpecialServerIps[member];
}
SpecialServerIps = null;
SpecialServerIps = new SpecialServerIpsMap();
}
function loadSpecialServerIps(saveString) {
SpecialServerIps = JSON.parse(saveString, Reviver);
}
function initSpecialServerIps() {
SpecialServerIps = new SpecialServerIpsMap();
}
export {SpecialServerNames, SpecialServerIps, SpecialServerIpsMap, loadSpecialServerIps,
prestigeSpecialServerIps, initSpecialServerIps};

@ -1,3 +1,14 @@
import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js";
import {Locations} from "./Location.js";
import {Player} from "./Player.js";
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {clearEventListeners, getRandomInt} from "../utils/HelperFunctions.js";
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js";
import {formatNumber} from "../utils/StringHelperFunctions.js";
/* StockMarket.js */ /* StockMarket.js */
function Stock(name, symbol, mv, b, otlkMag, initPrice=10000) { function Stock(name, symbol, mv, b, otlkMag, initPrice=10000) {
this.symbol = symbol; this.symbol = symbol;
@ -11,10 +22,27 @@ function Stock(name, symbol, mv, b, otlkMag, initPrice=10000) {
this.otlkMag = otlkMag; this.otlkMag = otlkMag;
} }
Stock.prototype.toJSON = function() {
return Generic_toJSON("Stock", this);
}
StockMarket = {} //Full name to stock object Stock.fromJSON = function(value) {
StockSymbols = {} //Full name to symbol return Generic_fromJSON(Stock, value.data);
SymbolToStockMap = {}; //Symbol to Stock object }
Reviver.constructors.Stock = Stock;
let StockMarket = {} //Full name to stock object
let StockSymbols = {} //Full name to symbol
let SymbolToStockMap = {}; //Symbol to Stock object
function loadStockMarket(saveString) {
if (saveString === "") {
StockMarket = {};
} else {
StockMarket = JSON.parse(saveString, Reviver);
}
}
function initStockSymbols() { function initStockSymbols() {
//Stocks for companies at which you can work //Stocks for companies at which you can work
@ -51,7 +79,6 @@ function initStockSymbols() {
StockSymbols["Sigma Cosmetics"] = "SGC"; StockSymbols["Sigma Cosmetics"] = "SGC";
StockSymbols["Joes Guns"] = "JGN"; StockSymbols["Joes Guns"] = "JGN";
StockSymbols["Catalyst Ventures"] = "CTYS"; StockSymbols["Catalyst Ventures"] = "CTYS";
StockSymbols["Taiyang Digital"] = "TAI";
StockSymbols["Microdyne Technologies"] = "MDYN"; StockSymbols["Microdyne Technologies"] = "MDYN";
StockSymbols["Titan Laboratories"] = "TITN"; StockSymbols["Titan Laboratories"] = "TITN";
} }
@ -119,10 +146,6 @@ function initStockMarket() {
var universalenergyStk = new Stock(universalenergy, StockSymbols[universalenergy], 0.55, true, 10, getRandomInt(20000, 25000)); var universalenergyStk = new Stock(universalenergy, StockSymbols[universalenergy], 0.55, true, 10, getRandomInt(20000, 25000));
StockMarket[universalenergy] = universalenergyStk; StockMarket[universalenergy] = universalenergyStk;
var galactic = Locations.AevumGalacticCybersystems;
var galacticStk = new Stock(galactic, StockSymbols[galactic], 0.6, true, 5, getRandomInt(8000, 10000));
StockMarket[galactic] = galacticStk;
var aerocorp = Locations.AevumAeroCorp; var aerocorp = Locations.AevumAeroCorp;
var aerocorpStk = new Stock(aerocorp, StockSymbols[aerocorp], 0.6, true, 6, getRandomInt(10000, 15000)); var aerocorpStk = new Stock(aerocorp, StockSymbols[aerocorp], 0.6, true, 6, getRandomInt(10000, 15000));
StockMarket[aerocorp] = aerocorpStk; StockMarket[aerocorp] = aerocorpStk;
@ -191,10 +214,6 @@ function initStockMarket() {
var catalystStk = new Stock(catalyst, StockSymbols[catalyst], 1.25, true, 0, getRandomInt(1000, 1500)); var catalystStk = new Stock(catalyst, StockSymbols[catalyst], 1.25, true, 0, getRandomInt(1000, 1500));
StockMarket[catalyst] = catalystStk; StockMarket[catalyst] = catalystStk;
var taiyang = "Taiyang Digital";
var taiyangStk = new Stock(taiyang, StockSymbols[taiyang], 0.75, true, 12, getRandomInt(25000, 30000));
StockMarket[taiyang] = taiyangStk;
var microdyne = "Microdyne Technologies"; var microdyne = "Microdyne Technologies";
var microdyneStk = new Stock(microdyne, StockSymbols[microdyne], 0.75, true, 8, getRandomInt(20000, 25000)); var microdyneStk = new Stock(microdyne, StockSymbols[microdyne], 0.75, true, 8, getRandomInt(20000, 25000));
StockMarket[microdyne] = microdyneStk; StockMarket[microdyne] = microdyneStk;
@ -330,6 +349,10 @@ function updateStockPrices() {
} }
} }
function setStockMarketContentCreated(b) {
stockMarketContentCreated = b;
}
var stockMarketContentCreated = false; var stockMarketContentCreated = false;
function displayStockMarketContent() { function displayStockMarketContent() {
if (Player.hasWseAccount == null) {Player.hasWseAccount = false;} if (Player.hasWseAccount == null) {Player.hasWseAccount = false;}
@ -537,9 +560,9 @@ function displayStockMarketContent() {
//'increase' argument is a boolean indicating whether the price increased or decreased //'increase' argument is a boolean indicating whether the price increased or decreased
function updateStockTicker(stock, increase) { function updateStockTicker(stock, increase) {
var tickerId = "stock-market-ticker-" + stock.symbol; var tickerId = "stock-market-ticker-" + stock.symbol;
stkName = document.getElementById(tickerId + "-name"); let stkName = document.getElementById(tickerId + "-name");
stkSym = document.getElementById(tickerId + "-sym"); let stkSym = document.getElementById(tickerId + "-sym");
stkPrice = document.getElementById(tickerId + "-price"); let stkPrice = document.getElementById(tickerId + "-price");
if (stkName == null || stkSym == null || stkPrice == null) { if (stkName == null || stkSym == null || stkPrice == null) {
console.log("ERROR, couldn't find elements with tickerId " + tickerId); console.log("ERROR, couldn't find elements with tickerId " + tickerId);
@ -584,3 +607,9 @@ function updateStockPlayerPosition(stock) {
avgPriceTxt.innerText = "$" + formatNumber(stock.playerAvgPx, 2); avgPriceTxt.innerText = "$" + formatNumber(stock.playerAvgPx, 2);
sharesTxt.innerText = stock.playerShares.toString(); sharesTxt.innerText = stock.playerShares.toString();
} }
export {StockMarket, StockSymbols, SymbolToStockMap, initStockSymbols,
initStockMarket, initSymbolToStockMap, stockMarketCycle, buyStock,
sellStock, updateStockPrices, displayStockMarketContent,
updateStockTicker, updateStockPlayerPosition, loadStockMarket,
setStockMarketContentCreated};

@ -1,7 +1,35 @@
//Terminal import {substituteAliases, printAliases,
parseAliasDeclaration,
removeAlias, GlobalAliases,
Aliases} from "./Alias.js";
import {CONSTANTS} from "./Constants.js";
import {Programs} from "./CreateProgram.js";
import {executeDarkwebTerminalCommand,
checkIfConnectedToDarkweb} from "./DarkWeb.js";
import {Engine} from "./engine.js";
import {TerminalHelpText, HelpTexts} from "./HelpText.js";
import {iTutorialNextStep, iTutorialSteps,
iTutorialIsRunning,
currITutorialStep} from "./InteractiveTutorial.js";
import {showLiterature} from "./Literature.js";
import {showMessage, Message} from "./Message.js";
import {killWorkerScript, addWorkerScript} from "./NetscriptWorker.js";
import {Player} from "./Player.js";
import {hackWorldDaemon} from "./RedPill.js";
import {findRunningScript, RunningScript,
AllServersMap, Script} from "./Script.js";
import {AllServers, GetServerByHostname,
getServer, Server} from "./Server.js";
import {SpecialServerIps,
SpecialServerNames} from "./SpecialServerIps.js";
import {containsAllStrings, longestCommonStart,
formatNumber} from "../utils/StringHelperFunctions.js";
import {addOffset, printArray} from "../utils/HelperFunctions.js";
import {logBoxCreate} from "../utils/LogBox.js";
/* Write text to terminal */ /* Write text to terminal */
var post = function(input, replace=true) { function post(input, replace=true) {
if (replace) { if (replace) {
$("#terminal-input").before('<tr class="posted"><td class="terminal-line" style="color: var(--my-font-color); background-color: var(--my-background-color);">' + input.replace( / /g, "&nbsp;" ) + '</td></tr>'); $("#terminal-input").before('<tr class="posted"><td class="terminal-line" style="color: var(--my-font-color); background-color: var(--my-background-color);">' + input.replace( / /g, "&nbsp;" ) + '</td></tr>');
} else { } else {
@ -12,12 +40,12 @@ var post = function(input, replace=true) {
} }
//Same thing as post but the td cells have ids so they can be animated for the hack progress bar //Same thing as post but the td cells have ids so they can be animated for the hack progress bar
var hackProgressBarPost = function(input) { function hackProgressBarPost(input) {
$("#terminal-input").before('<tr class="posted"><td id="hack-progress-bar" style="color: var(--my-font-color); background-color: var(--my-background-color);">' + input + '</td></tr>'); $("#terminal-input").before('<tr class="posted"><td id="hack-progress-bar" style="color: var(--my-font-color); background-color: var(--my-background-color);">' + input + '</td></tr>');
updateTerminalScroll(); updateTerminalScroll();
} }
var hackProgressPost = function(input) { function hackProgressPost(input) {
$("#terminal-input").before('<tr class="posted"><td id="hack-progress" style="color: var(--my-font-color); background-color: var(--my-background-color);">' + input + '</td></tr>'); $("#terminal-input").before('<tr class="posted"><td id="hack-progress" style="color: var(--my-font-color); background-color: var(--my-background-color);">' + input + '</td></tr>');
updateTerminalScroll(); updateTerminalScroll();
} }
@ -28,7 +56,7 @@ function updateTerminalScroll() {
element.scrollTop = element.scrollHeight; element.scrollTop = element.scrollHeight;
} }
var postNetburnerText = function() { function postNetburnerText() {
post("Bitburner v" + CONSTANTS.Version); post("Bitburner v" + CONSTANTS.Version);
} }
@ -134,7 +162,7 @@ $(document).keydown(function(event) {
}); });
//Keep terminal in focus //Keep terminal in focus
terminalCtrlPressed = false; let terminalCtrlPressed = 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();
@ -346,7 +374,7 @@ function determineAllPossibilitiesForTabCompletion(input, index=0) {
return allPos; return allPos;
} }
var Terminal = { let Terminal = {
//Flags to determine whether the player is currently running a hack or an analyze //Flags to determine whether the player is currently running a hack or an analyze
hackFlag: false, hackFlag: false,
analyzeFlag: false, analyzeFlag: false,
@ -1592,5 +1620,6 @@ var Terminal = {
post("ERROR: No such script"); post("ERROR: No such script");
} }
}; };
export {postNetburnerText, post, Terminal};

@ -1,3 +1,65 @@
var ace = require('brace');
require('brace/mode/javascript');
require('brace/theme/monokai');
require('brace/theme/terminal');
require('brace/theme/twilight');
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {gameOptionsBoxOpen, gameOptionsBoxClose}from "../utils/GameOptions.js";
import {clearEventListeners} from "../utils/HelperFunctions.js";
import numeral from "../utils/numeral.min.js";
import {formatNumber,
convertTimeMsToTimeElapsedString} from "../utils/StringHelperFunctions.js";
import {loxBoxCreate, logBoxUpdateText,
logBoxOpened} from "../utils/LogBox.js";
import {setActiveScriptsClickHandlers,
updateActiveScriptsItems} from "./ActiveScriptsUI.js";
import {Augmentations, installAugmentations,
initAugmentations, AugmentationNames} from "./Augmentations.js";
import {BitNodes, initBitNodes,
initBitNodeMultipliers} from "./BitNode.js";
import {CompanyPositions, initCompanies} from "./Company.js";
import {CONSTANTS} from "./Constants.js";
import {Programs, displayCreateProgramContent,
getNumAvailableCreateProgram,
initCreateProgramButtons} from "./CreateProgram.js";
import {displayFactionContent, joinFaction,
processPassiveFactionRepGain, Factions,
inviteToFaction, initFactions} from "./Faction.js";
import {Locations, displayLocationContent,
initLocationButtons} from "./Location.js";
import {displayGangContent, updateGangContent,
Gang} from "./Gang.js";
import {displayHacknetNodesContent, processAllHacknetNodeEarnings,
updateHacknetNodesContent} from "./HacknetNode.js";
import {iTutorialStart} from "./InteractiveTutorial.js";
import {initLiterature} from "./Literature.js";
import {checkForMessagesToSend, initMessages} from "./Message.js";
import {initSingularitySFFlags,
hasSingularitySF} from "./NetscriptFunctions.js";
import {updateOnlineScriptTimes,
runScriptsLoop} from "./NetscriptWorker.js";
import {Player} from "./Player.js";
import {prestigeAugmentation,
prestigeSourceFile} from "./Prestige.js";
import {redPillFlag} from "./RedPill.js";
import {saveObject, loadGame} from "./SaveObject.js";
import {loadAllRunningScripts,
updateScriptEditorContent} from "./Script.js";
import {AllServers, Server, initForeignServers} from "./Server.js";
import {Settings, setSettingsLabels} from "./Settings.js";
import {initSourceFiles, SourceFiles} from "./SourceFile.js";
import {SpecialServerIps, initSpecialServerIps} from "./SpecialServerIps.js";
import {StockMarket, StockSymbols,
SymbolToStockMap, initStockSymbols,
initSymbolToStockMap, stockMarketCycle,
updateStockPrices,
displayStockMarketContent} from "./StockMarket.js";
import {Terminal, postNetburnerText, post} from "./Terminal.js";
/* Shortcuts to navigate through the game /* Shortcuts to navigate through the game
* Alt-t - Terminal * Alt-t - Terminal
* Alt-c - Character * Alt-c - Character
@ -60,7 +122,7 @@ $(document).keydown(function(e) {
} }
}); });
var Engine = { let Engine = {
version: "", version: "",
Debug: true, Debug: true,
@ -125,9 +187,6 @@ var Engine = {
//Character info //Character info
characterInfo: null, characterInfo: null,
//Script editor text
scriptEditorText: null,
}, },
//Current page status //Current page status
@ -177,12 +236,13 @@ var Engine = {
loadScriptEditorContent: function(filename = "", code = "") { loadScriptEditorContent: function(filename = "", code = "") {
Engine.hideAllContent(); Engine.hideAllContent();
Engine.Display.scriptEditorContent.style.visibility = "visible"; Engine.Display.scriptEditorContent.style.visibility = "visible";
var editor = ace.edit('javascript-editor');
if (filename != "") { if (filename != "") {
document.getElementById("script-editor-filename").value = filename; document.getElementById("script-editor-filename").value = filename;
document.getElementById("script-editor-text").value = code; editor.setValue(code);
} }
document.getElementById("script-editor-text").focus(); editor.focus();
upgradeScriptEditorContent(); updateScriptEditorContent();
Engine.currentPage = Engine.Page.ScriptEditor; Engine.currentPage = Engine.Page.ScriptEditor;
document.getElementById("create-script-menu-link").classList.add("active"); document.getElementById("create-script-menu-link").classList.add("active");
}, },
@ -324,7 +384,7 @@ var Engine = {
loadGangContent: function() { loadGangContent: function() {
Engine.hideAllContent(); Engine.hideAllContent();
if (document.getElementById("gang-container") || Player.gang) { if (document.getElementById("gang-container") || Player.inGang()) {
displayGangContent(); displayGangContent();
Engine.currentPage = Engine.Page.Gang; Engine.currentPage = Engine.Page.Gang;
} else { } else {
@ -383,7 +443,6 @@ var Engine = {
if (Player.hp == null) {Player.hp = Player.max_hp;} if (Player.hp == null) {Player.hp = Player.max_hp;}
document.getElementById("character-overview-text").innerHTML = document.getElementById("character-overview-text").innerHTML =
("Hp: " + Player.hp + " / " + Player.max_hp + "<br>" + ("Hp: " + Player.hp + " / " + Player.max_hp + "<br>" +
//"Money: $" + formatNumber(Player.money.toNumber(), 2) + "<br>" +
"Money: " + numeral(Player.money.toNumber()).format('($0.000a)') + "<br>" + "Money: " + numeral(Player.money.toNumber()).format('($0.000a)') + "<br>" +
"Hack: " + (Player.hacking_skill).toLocaleString() + "<br>" + "Hack: " + (Player.hacking_skill).toLocaleString() + "<br>" +
"Str: " + (Player.strength).toLocaleString() + "<br>" + "Str: " + (Player.strength).toLocaleString() + "<br>" +
@ -473,7 +532,6 @@ var Engine = {
document.getElementById("world-city-name").innerHTML = Player.city; document.getElementById("world-city-name").innerHTML = Player.city;
var cityDesc = document.getElementById("world-city-desc"); //TODO var cityDesc = document.getElementById("world-city-desc"); //TODO
switch(Player.city) { switch(Player.city) {
case Locations.Aevum: case Locations.Aevum:
Engine.aevumLocationsList.style.display = "inline"; Engine.aevumLocationsList.style.display = "inline";
break; break;
@ -857,6 +915,7 @@ var Engine = {
if (Engine.Counters.checkFactionInvitations <= 0) { if (Engine.Counters.checkFactionInvitations <= 0) {
var invitedFactions = Player.checkForFactionInvitations(); var invitedFactions = Player.checkForFactionInvitations();
if (invitedFactions.length > 0) { if (invitedFactions.length > 0) {
Player.firstFacInvRecvd = true;
var randFaction = invitedFactions[Math.floor(Math.random() * invitedFactions.length)]; var randFaction = invitedFactions[Math.floor(Math.random() * invitedFactions.length)];
inviteToFaction(randFaction); inviteToFaction(randFaction);
} }
@ -891,7 +950,7 @@ var Engine = {
if (Engine.Counters.updateScriptEditorDisplay <= 0) { if (Engine.Counters.updateScriptEditorDisplay <= 0) {
if (Engine.currentPage == Engine.Page.ScriptEditor) { if (Engine.currentPage == Engine.Page.ScriptEditor) {
upgradeScriptEditorContent(); updateScriptEditorContent();
} }
Engine.Counters.updateScriptEditorDisplay = 5; Engine.Counters.updateScriptEditorDisplay = 5;
} }
@ -960,6 +1019,13 @@ var Engine = {
}, },
load: function() { load: function() {
//Load script editor
var editor = ace.edit('javascript-editor');
editor.getSession().setMode('ace/mode/javascript');
editor.setTheme('ace/theme/monokai');
document.getElementById('javascript-editor').style.fontSize='16px';
editor.setOption("showPrintMargin", false);
//Initialize main menu accordion panels to all start as "open" //Initialize main menu accordion panels to all start as "open"
var terminal = document.getElementById("terminal-tab"); var terminal = document.getElementById("terminal-tab");
var createScript = document.getElementById("create-script-tab"); var createScript = document.getElementById("create-script-tab");
@ -978,7 +1044,9 @@ var Engine = {
//Load game from save or create new game //Load game from save or create new game
if (loadGame(saveObject)) { if (loadGame(saveObject)) {
console.log("Loaded game from save"); console.log("Loaded game from save");
initBitNodes();
initBitNodeMultipliers(); initBitNodeMultipliers();
initSourceFiles();
Engine.setDisplayElements(); //Sets variables for important DOM elements Engine.setDisplayElements(); //Sets variables for important DOM elements
Engine.init(); //Initialize buttons, work, etc. Engine.init(); //Initialize buttons, work, etc.
CompanyPositions.init(); CompanyPositions.init();
@ -989,6 +1057,7 @@ var Engine = {
initSymbolToStockMap(); initSymbolToStockMap();
} }
initLiterature(); initLiterature();
initSingularitySFFlags();
//Calculate the number of cycles have elapsed while offline //Calculate the number of cycles have elapsed while offline
Engine._lastUpdate = new Date().getTime(); Engine._lastUpdate = new Date().getTime();
@ -1081,8 +1150,10 @@ var Engine = {
} else { } else {
//No save found, start new game //No save found, start new game
console.log("Initializing new game"); console.log("Initializing new game");
initBitNodes();
initBitNodeMultipliers(); initBitNodeMultipliers();
SpecialServerIps = new SpecialServerIpsMap(); initSourceFiles();
initSpecialServerIps();
Engine.setDisplayElements(); //Sets variables for important DOM elements Engine.setDisplayElements(); //Sets variables for important DOM elements
Engine.start(); //Run main game loop and Scripts loop Engine.start(); //Run main game loop and Scripts loop
Player.init(); Player.init();
@ -1094,6 +1165,7 @@ var Engine = {
initMessages(); initMessages();
initStockSymbols(); initStockSymbols();
initLiterature(); initLiterature();
initSingularitySFFlags();
//Open main menu accordions for new game //Open main menu accordions for new game
//Main menu accordions //Main menu accordions
@ -1212,9 +1284,6 @@ var Engine = {
//Init Location buttons //Init Location buttons
initLocationButtons(); initLocationButtons();
//Script editor
Engine.Display.scriptEditorText = document.getElementById("script-editor-text");
//Tutorial buttons //Tutorial buttons
Engine.Clickables.tutorialNetworkingButton = document.getElementById("tutorial-networking-link"); Engine.Clickables.tutorialNetworkingButton = document.getElementById("tutorial-networking-link");
Engine.Clickables.tutorialNetworkingButton.addEventListener("click", function() { Engine.Clickables.tutorialNetworkingButton.addEventListener("click", function() {
@ -1233,7 +1302,12 @@ var Engine = {
Engine.Clickables.tutorialNetscriptButton = document.getElementById("tutorial-netscript-link"); Engine.Clickables.tutorialNetscriptButton = document.getElementById("tutorial-netscript-link");
Engine.Clickables.tutorialNetscriptButton.addEventListener("click", function() { Engine.Clickables.tutorialNetscriptButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialNetscriptText); if (Player.bitNodeN === 4 || hasSingularitySF) {
Engine.displayTutorialPage(CONSTANTS.TutorialNetscriptText + CONSTANTS.TutorialSingularityFunctionsText);
} else {
Engine.displayTutorialPage(CONSTANTS.TutorialNetscriptText);
}
}); });
Engine.Clickables.tutorialTravelingButton = document.getElementById("tutorial-traveling-link"); Engine.Clickables.tutorialTravelingButton = document.getElementById("tutorial-traveling-link");
@ -1269,6 +1343,11 @@ var Engine = {
/* Initialization */ /* Initialization */
init: function() { init: function() {
//Import game link
document.getElementById("import-game-link").onclick = function() {
saveObject.importGame();
};
//Main menu accordions //Main menu accordions
var hackingHdr = document.getElementById("hacking-menu-header"); var hackingHdr = document.getElementById("hacking-menu-header");
//hackingHdr.classList.toggle("opened"); //hackingHdr.classList.toggle("opened");
@ -1603,9 +1682,9 @@ var Engine = {
cancelButton.addEventListener("click", function() { cancelButton.addEventListener("click", function() {
if (Player.workType == CONSTANTS.WorkTypeFaction) { if (Player.workType == CONSTANTS.WorkTypeFaction) {
var fac = Factions[Player.currentWorkFactionName]; var fac = Factions[Player.currentWorkFactionName];
Player.finishFactionWork(true, fac); Player.finishFactionWork(true);
} else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) { } else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) {
Player.finishCreateProgramWork(true, Player.createProgramName); Player.finishCreateProgramWork(true);
} else if (Player.workType == CONSTANTS.WorkTypeStudyClass) { } else if (Player.workType == CONSTANTS.WorkTypeStudyClass) {
Player.finishClass(); Player.finishClass();
} else if (Player.workType == CONSTANTS.WorkTypeCrime) { } else if (Player.workType == CONSTANTS.WorkTypeCrime) {
@ -1661,3 +1740,5 @@ var Engine = {
window.onload = function() { window.onload = function() {
Engine.load(); Engine.load();
}; };
export {Engine};

@ -1,5 +1,5 @@
/* Pop up Dialog Box */ /* Pop up Dialog Box */
dialogBoxes = []; let dialogBoxes = [];
//Close dialog box when clicking outside //Close dialog box when clicking outside
$(document).click(function(event) { $(document).click(function(event) {
@ -32,31 +32,33 @@ $(document).on('click', '.dialog-box-close-button', function( event ) {
var dialogBoxOpened = false; var dialogBoxOpened = false;
dialogBoxCreate = function(txt) { function dialogBoxCreate(txt) {
var container = document.createElement("div"); var container = document.createElement("div");
container.setAttribute("class", "dialog-box-container"); container.setAttribute("class", "dialog-box-container");
var content = document.createElement("div"); var content = document.createElement("div");
content.setAttribute("class", "dialog-box-content"); content.setAttribute("class", "dialog-box-content");
var closeButton = document.createElement("span"); var closeButton = document.createElement("span");
closeButton.setAttribute("class", "dialog-box-close-button"); closeButton.setAttribute("class", "dialog-box-close-button");
closeButton.innerHTML = "&times;" closeButton.innerHTML = "&times;"
var textE = document.createElement("p"); var textE = document.createElement("p");
textE.innerHTML = txt; textE.innerHTML = txt;
content.appendChild(closeButton); content.appendChild(closeButton);
content.appendChild(textE); content.appendChild(textE);
container.appendChild(content); container.appendChild(content);
document.body.appendChild(container); document.body.appendChild(container);
if (dialogBoxes.length >= 1) { if (dialogBoxes.length >= 1) {
container.style.visibility = "hidden"; container.style.visibility = "hidden";
} }
dialogBoxes.push(container); dialogBoxes.push(container);
setTimeout(function() { setTimeout(function() {
dialogBoxOpened = true; dialogBoxOpened = true;
}, 400); }, 400);
} }
export {dialogBoxCreate};

@ -1,26 +1,30 @@
import {Faction, joinFaction} from "../src/Faction.js";
import {Player} from "../src/Player.js";
import {clearEventListeners} from "./HelperFunctions.js";
/* Faction Invitation Pop-up box */ /* Faction Invitation Pop-up box */
factionInvitationBoxClose = function() { function factionInvitationBoxClose() {
var factionInvitationBox = document.getElementById("faction-invitation-box-container"); var factionInvitationBox = document.getElementById("faction-invitation-box-container");
factionInvitationBox.style.display = "none"; factionInvitationBox.style.display = "none";
} }
factionInvitationBoxOpen = function() { function factionInvitationBoxOpen() {
var factionInvitationBox = document.getElementById("faction-invitation-box-container"); var factionInvitationBox = document.getElementById("faction-invitation-box-container");
factionInvitationBox.style.display = "block"; factionInvitationBox.style.display = "block";
} }
factionInvitationSetText = function(txt) { function factionInvitationSetText(txt) {
var textBox = document.getElementById("faction-invitation-box-text"); var textBox = document.getElementById("faction-invitation-box-text");
textBox.innerHTML = txt; textBox.innerHTML = txt;
} }
factionInvitationSetMessage = function(msg) { function factionInvitationSetMessage(msg) {
var msgBox = document.getElementById("faction-invitation-box-message"); var msgBox = document.getElementById("faction-invitation-box-message");
msgBox.innerHTML = msg; msgBox.innerHTML = msg;
} }
//ram argument is in GB //ram argument is in GB
factionInvitationBoxCreate = function(faction) { function factionInvitationBoxCreate(faction) {
factionInvitationSetText("You have received a faction invitation from " + faction.name); factionInvitationSetText("You have received a faction invitation from " + faction.name);
//TODO Faction invitation message //TODO Faction invitation message
@ -41,3 +45,5 @@ factionInvitationBoxCreate = function(faction) {
factionInvitationBoxOpen(); factionInvitationBoxOpen();
} }
export {factionInvitationBoxCreate};

@ -2,9 +2,9 @@
//Close box when clicking outside //Close box when clicking outside
$(document).click(function(event) { $(document).click(function(event) {
if (gameOptionsOpened) { if (gameOptionsOpened) {
if ( $(event.target).closest(".game-options-box").get(0) == null ) { if ( $(event.target).closest(".game-options-box").get(0) == null ) {
gameOptionsBoxClose(); gameOptionsBoxClose();
} }
} }
}); });
@ -16,7 +16,7 @@ function gameOptionsBoxInit() {
gameOptionsBoxOpen(); gameOptionsBoxOpen();
return false; return false;
}); });
//Close button //Close button
var closeButton = document.getElementById("game-options-close-button"); var closeButton = document.getElementById("game-options-close-button");
closeButton.addEventListener("click", function() { closeButton.addEventListener("click", function() {
@ -27,17 +27,19 @@ function gameOptionsBoxInit() {
document.addEventListener("DOMContentLoaded", gameOptionsBoxInit, false); document.addEventListener("DOMContentLoaded", gameOptionsBoxInit, false);
gameOptionsBoxClose = function() { function gameOptionsBoxClose() {
gameOptionsOpened = false; gameOptionsOpened = false;
var box = document.getElementById("game-options-container"); var box = document.getElementById("game-options-container");
box.style.display = "none"; box.style.display = "none";
} }
gameOptionsBoxOpen = function() { function gameOptionsBoxOpen() {
var box = document.getElementById("game-options-container"); var box = document.getElementById("game-options-container");
box.style.display = "block"; box.style.display = "block";
setTimeout(function() { setTimeout(function() {
gameOptionsOpened = true; gameOptionsOpened = true;
}, 500); }, 500);
} }
export {gameOptionsBoxOpen, gameOptionsBoxClose};

@ -10,13 +10,13 @@ function sizeOfObject(obj) {
} }
//Adds a random offset to a number within a certain percentage //Adds a random offset to a number within a certain percentage
//e.g. addOffset(100, 5) will return anything from 95 to 105. //e.g. addOffset(100, 5) will return anything from 95 to 105.
//The percentage argument must be between 0 and 100; //The percentage argument must be between 0 and 100;
function addOffset(n, percentage) { function addOffset(n, percentage) {
if (percentage < 0 || percentage > 100) {return;} if (percentage < 0 || percentage > 100) {return;}
var offset = n * (percentage / 100); var offset = n * (percentage / 100);
return n + ((Math.random() * (2 * offset)) - offset); return n + ((Math.random() * (2 * offset)) - offset);
} }
@ -41,7 +41,7 @@ function compareArrays(a1, a2) {
if (a1.length != a2.length) { if (a1.length != a2.length) {
return false; return false;
} }
for (var i = 0; i < a1.length; ++i) { for (var i = 0; i < a1.length; ++i) {
if (a1[i] != a2[i]) {return false;} if (a1[i] != a2[i]) {return false;}
} }
@ -56,4 +56,7 @@ function printArray(a) {
function powerOfTwo(n) { function powerOfTwo(n) {
if (isNaN(n)) {return false;} if (isNaN(n)) {return false;}
return n && (n & (n-1)) === 0; return n && (n & (n-1)) === 0;
} }
export {sizeOfObject, addOffset, clearEventListeners, getRandomInt,
compareArrays, printArray, powerOfTwo};

@ -1,13 +1,14 @@
import {AllServers} from "../src/Server.js";
/* Functions to deal with manipulating IP addresses*/ /* Functions to deal with manipulating IP addresses*/
//Generate a random IP address //Generate a random IP address
//Will not return an IP address that already exists in the AllServers array //Will not return an IP address that already exists in the AllServers array
createRandomIp = function() { function createRandomIp() {
var ip = createRandomByte(99) +'.' + var ip = createRandomByte(99) +'.' +
createRandomByte(9) +'.' + createRandomByte(9) +'.' +
createRandomByte(9) +'.' + createRandomByte(9) +'.' +
createRandomByte(9); createRandomByte(9);
//If the Ip already exists, recurse to create a new one //If the Ip already exists, recurse to create a new one
if (ipExists(ip)) { if (ipExists(ip)) {
return createRandomIp(); return createRandomIp();
@ -16,7 +17,7 @@ createRandomIp = function() {
} }
//Returns true if the IP already exists in one of the game's servers //Returns true if the IP already exists in one of the game's servers
ipExists = function(ip) { function ipExists(ip) {
for (var property in AllServers) { for (var property in AllServers) {
if (AllServers.hasOwnProperty(property)) { if (AllServers.hasOwnProperty(property)) {
if (property == ip) { if (property == ip) {
@ -27,14 +28,16 @@ ipExists = function(ip) {
return false; return false;
} }
createRandomByte = function(n=9) { function createRandomByte(n=9) {
return Math.round(Math.random()*n); return Math.round(Math.random()*n);
} }
isValidIPAddress = function(ipaddress) { function isValidIPAddress(ipaddress) {
if (/^(25[0-6]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-6]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-6]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-6]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ipaddress)) if (/^(25[0-6]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-6]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-6]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-6]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ipaddress))
{ {
return true; return true;
} }
return false; return false;
} }
export {createRandomIp, ipExists, isValidIPAddress};

@ -1,69 +1,76 @@
import {CONSTANTS} from "../src/Constants.js";
import {Factions, Faction} from "../src/Faction.js";
import {Player} from "../src/Player.js";
import {dialogBoxCreate} from "./DialogBox.js";
import {clearEventListeners} from "./HelperFunctions.js";
import {formatNumber} from "./StringHelperFunctions.js";
/* InfiltrationBox.js */ /* InfiltrationBox.js */
infiltrationBoxClose = function() { function infiltrationBoxClose() {
var box = document.getElementById("infiltration-box-container"); var box = document.getElementById("infiltration-box-container");
box.style.display = "none"; box.style.display = "none";
} }
infiltrationBoxOpen = function() { function infiltrationBoxOpen() {
var box = document.getElementById("infiltration-box-container"); var box = document.getElementById("infiltration-box-container");
box.style.display = "block"; box.style.display = "block";
} }
infiltrationSetText = function(txt) { function infiltrationSetText(txt) {
var textBox = document.getElementById("infiltration-box-text"); var textBox = document.getElementById("infiltration-box-text");
textBox.innerHTML = txt; textBox.innerHTML = txt;
} }
//ram argument is in GB //ram argument is in GB
infiltrationBoxCreate = function(inst) { function infiltrationBoxCreate(inst) {
var totalValue = 0; var totalValue = 0;
for (var i = 0; i < inst.secretsStolen.length; ++i) { for (var i = 0; i < inst.secretsStolen.length; ++i) {
totalValue += inst.secretsStolen[i]; totalValue += inst.secretsStolen[i];
} }
if (totalValue == 0) { if (totalValue == 0) {
dialogBoxCreate("You successfully escaped the facility but you did not steal " + dialogBoxCreate("You successfully escaped the facility but you did not steal " +
"anything of worth when infiltrating.<br><br>" + "anything of worth when infiltrating.<br><br>" +
"You gained:<br>" + "You gained:<br>" +
formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" + formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" +
formatNumber(inst.strExpGained, 3) + " str exp<br>" + formatNumber(inst.strExpGained, 3) + " str exp<br>" +
formatNumber(inst.defExpGained, 3) + " def exp<br>" + formatNumber(inst.defExpGained, 3) + " def exp<br>" +
formatNumber(inst.dexExpGained, 3) + " dex exp<br>" + formatNumber(inst.dexExpGained, 3) + " dex exp<br>" +
formatNumber(inst.agiExpGained, 3) + " agi exp<br>" + formatNumber(inst.agiExpGained, 3) + " agi exp<br>" +
formatNumber(inst.chaExpGained, 3) + " cha exp<br>"); formatNumber(inst.chaExpGained, 3) + " cha exp<br>");
return; return;
} }
var facValue = totalValue * Player.faction_rep_mult * 1.2 var facValue = totalValue * Player.faction_rep_mult * 1.2
var moneyValue = totalValue * CONSTANTS.InfiltrationMoneyValue; var moneyValue = totalValue * CONSTANTS.InfiltrationMoneyValue;
infiltrationSetText("You can sell the classified documents and secrets " + infiltrationSetText("You can sell the classified documents and secrets " +
"you stole from " + inst.companyName + " for $" + "you stole from " + inst.companyName + " for $" +
formatNumber(moneyValue, 2) + " on the black market or you can give it " + formatNumber(moneyValue, 2) + " on the black market or you can give it " +
"to a faction to gain " + formatNumber(facValue, 3) + " reputation with " + "to a faction to gain " + formatNumber(facValue, 3) + " reputation with " +
"that faction."); "that faction.");
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) {
selector.innerHTML += "<option value='" + Player.factions[i] + selector.innerHTML += "<option value='" + Player.factions[i] +
"'>" + Player.factions[i] + "</option>"; "'>" + Player.factions[i] + "</option>";
} }
var sellButton = clearEventListeners("infiltration-box-sell"); var sellButton = clearEventListeners("infiltration-box-sell");
setTimeout(function() { setTimeout(function() {
sellButton.addEventListener("click", function() { sellButton.addEventListener("click", function() {
Player.gainMoney(moneyValue); Player.gainMoney(moneyValue);
dialogBoxCreate("You sold the classified information you stole from " + inst.companyName + dialogBoxCreate("You sold the classified information you stole from " + inst.companyName +
" for $" + moneyValue + " on the black market!<br><br>" + " for $" + moneyValue + " on the black market!<br><br>" +
"You gained:<br>" + "You gained:<br>" +
formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" + formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" +
formatNumber(inst.strExpGained, 3) + " str exp<br>" + formatNumber(inst.strExpGained, 3) + " str exp<br>" +
formatNumber(inst.defExpGained, 3) + " def exp<br>" + formatNumber(inst.defExpGained, 3) + " def exp<br>" +
formatNumber(inst.dexExpGained, 3) + " dex exp<br>" + formatNumber(inst.dexExpGained, 3) + " dex exp<br>" +
formatNumber(inst.agiExpGained, 3) + " agi exp<br>" + formatNumber(inst.agiExpGained, 3) + " agi exp<br>" +
formatNumber(inst.chaExpGained, 3) + " cha exp<br>"); formatNumber(inst.chaExpGained, 3) + " cha exp<br>");
infiltrationBoxClose(); infiltrationBoxClose();
return false; return false;
}); });
}, 750); }, 750);
var factionButton = clearEventListeners("infiltration-box-faction"); var factionButton = clearEventListeners("infiltration-box-faction");
setTimeout(function() { setTimeout(function() {
factionButton.addEventListener("click", function() { factionButton.addEventListener("click", function() {
@ -74,18 +81,20 @@ infiltrationBoxCreate = function(inst) {
return false; return false;
} }
faction.playerReputation += facValue; faction.playerReputation += facValue;
dialogBoxCreate("You gave the classified information you stole from " + inst.companyName + dialogBoxCreate("You gave the classified information you stole from " + inst.companyName +
" to " + facName + " and gained " + formatNumber(facValue, 3) + " reputation with the faction. <br><br>" + " to " + facName + " and gained " + formatNumber(facValue, 3) + " reputation with the faction. <br><br>" +
"You gained:<br>" + "You gained:<br>" +
formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" + formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" +
formatNumber(inst.strExpGained, 3) + " str exp<br>" + formatNumber(inst.strExpGained, 3) + " str exp<br>" +
formatNumber(inst.defExpGained, 3) + " def exp<br>" + formatNumber(inst.defExpGained, 3) + " def exp<br>" +
formatNumber(inst.dexExpGained, 3) + " dex exp<br>" + formatNumber(inst.dexExpGained, 3) + " dex exp<br>" +
formatNumber(inst.agiExpGained, 3) + " agi exp<br>" + formatNumber(inst.agiExpGained, 3) + " agi exp<br>" +
formatNumber(inst.chaExpGained, 3) + " cha exp<br>"); formatNumber(inst.chaExpGained, 3) + " cha exp<br>");
infiltrationBoxClose(); infiltrationBoxClose();
return false; return false;
}); });
}, 750); }, 750);
infiltrationBoxOpen(); infiltrationBoxOpen();
} }
export {infiltrationBoxCreate};

@ -17,13 +17,13 @@ function Reviver(key, value) {
ctor = Reviver.constructors[value.ctor] || window[value.ctor]; ctor = Reviver.constructors[value.ctor] || window[value.ctor];
if (typeof ctor === "function" && if (typeof ctor === "function" &&
typeof ctor.fromJSON === "function") { typeof ctor.fromJSON === "function") {
return ctor.fromJSON(value); return ctor.fromJSON(value);
} }
} }
return value; return value;
} }
Reviver.constructors = {}; // A list of constructors the smart reviver should know about Reviver.constructors = {}; // A list of constructors the smart reviver should know about
// A generic "toJSON" function that creates the data expected // A generic "toJSON" function that creates the data expected
// by Reviver. // by Reviver.
@ -67,3 +67,5 @@ function Generic_fromJSON(ctor, data) {
} }
return obj; return obj;
} }
export {Reviver, Generic_toJSON, Generic_fromJSON};

@ -1,26 +1,15 @@
/* Log Box */ import {printArray} from "./HelperFunctions.js";
//Close box when clicking outside
/*
$(document).click(function(event) {
if (logBoxOpened) {
if ( $(event.target).closest("#log-box-container").get(0) == null ) {
logBoxClose();
}
}
});
*/
$(document).keydown(function(event) { $(document).keydown(function(event) {
if (logBoxOpened && event.keyCode == 27) { if (logBoxOpened && event.keyCode == 27) {
logBoxClose(); logBoxClose();
} }
}); });
function logBoxInit() { function logBoxInit() {
var closeButton = document.getElementById("log-box-close"); var closeButton = document.getElementById("log-box-close");
logBoxClose(); logBoxClose();
//Close Dialog box //Close Dialog box
closeButton.addEventListener("click", function() { closeButton.addEventListener("click", function() {
logBoxClose(); logBoxClose();
@ -30,15 +19,15 @@ function logBoxInit() {
document.addEventListener("DOMContentLoaded", logBoxInit, false); document.addEventListener("DOMContentLoaded", logBoxInit, false);
logBoxClose = function() { function logBoxClose() {
logBoxOpened = false; logBoxOpened = false;
var logBox = document.getElementById("log-box-container"); var logBox = document.getElementById("log-box-container");
logBox.style.display = "none"; logBox.style.display = "none";
} }
logBoxOpen = function() { function logBoxOpen() {
logBoxOpened = true; logBoxOpened = true;
var logBox = document.getElementById("log-box-container"); var logBox = document.getElementById("log-box-container");
logBox.style.display = "block"; logBox.style.display = "block";
} }
@ -47,13 +36,13 @@ logBoxOpen = function() {
var logBoxOpened = false; var logBoxOpened = false;
var logBoxCurrentScript = null; var logBoxCurrentScript = null;
//ram argument is in GB //ram argument is in GB
logBoxCreate = function(script) { function logBoxCreate(script) {
logBoxCurrentScript = script; logBoxCurrentScript = script;
logBoxOpen(); logBoxOpen();
logBoxUpdateText(); logBoxUpdateText();
} }
logBoxUpdateText = function() { function logBoxUpdateText() {
var txt = document.getElementById("log-box-text"); var txt = document.getElementById("log-box-text");
if (logBoxCurrentScript && logBoxOpened && txt) { if (logBoxCurrentScript && logBoxOpened && txt) {
txt.innerHTML = logBoxCurrentScript.filename + printArray(logBoxCurrentScript.args) + ":<br><br>"; txt.innerHTML = logBoxCurrentScript.filename + printArray(logBoxCurrentScript.args) + ":<br><br>";
@ -62,4 +51,6 @@ logBoxUpdateText = function() {
txt.innerHTML += "<br>"; txt.innerHTML += "<br>";
} }
} }
} }
export {logBoxCreate, logBoxUpdateText, logBoxOpened, logBoxCurrentScript};

@ -1,3 +1,5 @@
import {dialogBoxCreate} from "./DialogBox.js";
//Netburner String helper functions //Netburner String helper functions
//Searches for every occurence of searchStr within str and returns an array of the indices of //Searches for every occurence of searchStr within str and returns an array of the indices of
@ -31,18 +33,18 @@ String.prototype.replaceAt=function(index, character) {
function convertTimeMsToTimeElapsedString(time) { function convertTimeMsToTimeElapsedString(time) {
//Convert ms to seconds, since we only have second-level precision //Convert ms to seconds, since we only have second-level precision
time = Math.floor(time / 1000); time = Math.floor(time / 1000);
var days = Math.floor(time / 86400); var days = Math.floor(time / 86400);
time %= 86400; time %= 86400;
var hours = Math.floor(time / 3600); var hours = Math.floor(time / 3600);
time %= 3600; time %= 3600;
var minutes = Math.floor(time / 60); var minutes = Math.floor(time / 60);
time %= 60; time %= 60;
var seconds = time; var seconds = time;
var res = ""; var res = "";
if (days) {res += days + " days ";} if (days) {res += days + " days ";}
if (hours) {res += hours + " hours ";} if (hours) {res += hours + " hours ";}
@ -55,8 +57,8 @@ function convertTimeMsToTimeElapsedString(time) {
function longestCommonStart(strings) { function longestCommonStart(strings) {
if (!containsAllStrings(strings)) {return;} if (!containsAllStrings(strings)) {return;}
if (strings.length == 0) {return;} if (strings.length == 0) {return;}
var A = strings.concat().sort(), var A = strings.concat().sort(),
a1= A[0], a2= A[A.length-1], L= a1.length, i= 0; a1= A[0], a2= A[A.length-1], L= a1.length, i= 0;
while(i<L && a1.charAt(i)=== a2.charAt(i)) i++; while(i<L && a1.charAt(i)=== a2.charAt(i)) i++;
return a1.substring(0, i); return a1.substring(0, i);
@ -126,3 +128,7 @@ function numNetscriptOperators(string) {
} }
return total; return total;
} }
export {getIndicesOf, convertTimeMsToTimeElapsedString, longestCommonStart,
isString, isPositiveNumber, containsAllStrings, formatNumber,
numOccurrences, numNetscriptOperators};

@ -1,3 +1,4 @@
import {clearEventListeners} from "./HelperFunctions.js";
/* Generic Yes-No Pop-up box /* Generic Yes-No Pop-up box
* Can be used to create pop-up boxes that require a yes/no response from player * Can be used to create pop-up boxes that require a yes/no response from player
*/ */
@ -74,3 +75,9 @@ function yesNoTxtInpBoxCreate(txt) {
console.log("ERROR: Container not found for YesNoTextInputBox"); console.log("ERROR: Container not found for YesNoTextInputBox");
} }
} }
export {yesNoBoxCreate, yesNoTxtInpBoxCreate,
yesNoBoxGetYesButton, yesNoBoxGetNoButton,
yesNoTxtInpBoxGetYesButton, yesNoTxtInpBoxGetNoButton,
yesNoTxtInpBoxGetInput, yesNoBoxClose,
yesNoTxtInpBoxClose, yesNoBoxOpen};