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
Netburner.txt
README.md
README.md
/node_modules

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

@ -16,6 +16,42 @@
}
/* 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 */
.tmp-element {
visibility: hidden;
@ -56,6 +92,7 @@
#script-editor-wrapper {
height:100%;
width: 70%;
background:transparent;
}
#script-editor-filename-wrapper {
@ -103,28 +140,6 @@
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-list {
list-style-type: none;
@ -261,6 +276,7 @@
box-shadow: 1px 1px 3px #000;
margin: 4px;
padding: 4px;
background-color:black;
}
.active-scripts-button:hover,
@ -569,6 +585,7 @@ div.faction-clear {
color: var(--my-font-color);
padding: 4px;
margin: 4px;
background-color:black;
}
.stock-market-buy-sell-button {

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

@ -1,20 +1,20 @@
/** This removes all padding and margins as well as
setting a default font size and family for the page **/
:root{
--my-font-color: #66ff33;
--my-background-color: #000000;
--my-highlight-color: #ffffff;
}
* {
margin: 0;
padding: 0;
font-size: 16px;
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);
}
@ -41,6 +41,10 @@ span {
padding: 4px;
}
#entire-game-container {
background-color:transparent;
}
/* Disable border highlight on elements */
input:focus,
textarea:focus,
@ -346,6 +350,7 @@ a:link, a:visited {
-webkit-box-shadow: 1px 1px 3px #000;
box-shadow: 1px 1px 3px #000;
height: 22px;
background-color:black;
}
#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>
</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 -->
<div id="terminal-container">
<table id="terminal">
@ -108,23 +126,6 @@
</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 -->
<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
@ -839,8 +840,6 @@
</label>
<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">
</input>
<em id="settingsNSExecTimeRangeValLabel" style="font-style: normal;"></em>
@ -857,8 +856,6 @@
</label>
<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">
</input>
<em id="settingsNSLogRangeValLabel" style="font-style: normal;"></em>
@ -875,8 +872,6 @@
</label>
<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">
</input>
<em id="settingsNSPortRangeValLabel" style="font-style: normal;"></em>
@ -891,8 +886,7 @@
and can be viewed with the 'cat' Terminal command.
</span>
</label>
<input type="checkbox" name="settingsSuppressMessages" id="settingsSuppressMessages"
onclick="Settings.SuppressMessages = this.checked;">
<input type="checkbox" name="settingsSuppressMessages" id="settingsSuppressMessages">
</fieldset>
<!-- Suppress faction invites -->
@ -903,8 +897,7 @@
on the screen. Your outstanding faction invites can be viewed in the 'Factions' page.
</span>
</label>
<input type="checkbox" name="settingsSuppressFactionInvites" id="settingsSuppressFactionInvites"
onclick="Settings.SuppressFactionInvites = this.checked;">
<input type="checkbox" name="settingsSuppressFactionInvites" id="settingsSuppressFactionInvites">
</fieldset>
<!-- 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="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"/>
<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%;">
(DEBUG) Delete Active Scripts
<span class="tooltiptext">
@ -949,64 +942,5 @@
<div class="loaderlabel">Loading Bitburner...</div>
</div>
</body>
<!--jQuery library-->
<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>
<script src="dist/bundle.js"></script>
</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() {
//Server panel click handlers
var serverPanels = document.getElementsByClassName("active-scripts-server-header");
@ -10,7 +19,7 @@ function setActiveScriptsClickHandlers() {
for (i = 0; i < serverPanels.length; ++i) {
serverPanels[i].onclick = function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
@ -19,7 +28,7 @@ function setActiveScriptsClickHandlers() {
}
}
}
//Script Panel click handlers
var scriptPanels = document.getElementsByClassName("active-scripts-script-header");
if (scriptPanels == null) {
@ -29,13 +38,13 @@ function setActiveScriptsClickHandlers() {
for (var i = 0; i < scriptPanels.length; ++i) {
scriptPanels[i].onclick = function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
}
}
}
}
@ -54,35 +63,34 @@ function getActiveScriptsServerList(server) {
function createActiveScriptsServerPanel(server) {
var panelname = "active-scripts-server-panel-" + server.hostname;
var activeScriptsList = document.getElementById("active-scripts-list");
//Div of entire Panel
var panelDiv = document.createElement("div");
panelDiv.setAttribute("id", panelname);
//Panel Header
var panelHdr = document.createElement("button");
panelHdr.setAttribute("class", "active-scripts-server-header")
panelHdr.setAttribute("id", panelname + "-hdr");
panelHdr.innerHTML = server.hostname;
//Panel content
var panelContentDiv = document.createElement("div");
panelContentDiv.setAttribute("class", "active-scripts-server-panel");
panelContentDiv.setAttribute("id", panelname + "-content");
//List of scripts
var panelScriptList = document.createElement("ul");
panelScriptList.setAttribute("id", panelname + "-script-list");
panelContentDiv.appendChild(panelScriptList);
panelDiv.appendChild(panelHdr);
panelDiv.appendChild(panelContentDiv);
activeScriptsList.appendChild(panelDiv);
setActiveScriptsClickHandlers() //Reset click handlers
return panelDiv;
//TODO Alphabetize Active Scripts list?
}
//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);
return;
}
//Remove the panel if it has no elements
var scriptList = document.getElementById(panelname + "-script-list");
if (scriptList.childNodes.length == 0) {
@ -110,12 +118,12 @@ function addActiveScriptsItem(workerscript) {
return;
}
var panelname = "active-scripts-server-panel-" + server.hostname;
var panel = document.getElementById(panelname);
if (panel == null) {
panel = createActiveScriptsServerPanel(server);
}
//Create the element itself. Each element is an accordion collapsible
var itemNameArray = ["active", "scripts", server.hostname, workerscript.name];
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 item = document.createElement("li");
item.setAttribute("id", itemName);
var btn = document.createElement("button");
btn.setAttribute("class", "active-scripts-script-header");
btn.innerHTML = workerscript.name;
var itemContentDiv = document.createElement("div");
itemContentDiv.setAttribute("class", "active-scripts-script-panel");
itemContentDiv.setAttribute("id", itemName + "-content");
item.appendChild(btn);
item.appendChild(itemContentDiv);
createActiveScriptsText(workerscript, itemContentDiv);
//Append element to list
var list = getActiveScriptsServerList(server);
list.appendChild(item);
setActiveScriptsClickHandlers() //Reset click handlers
}
@ -191,47 +199,47 @@ function updateActiveScriptsItemContent(workerscript) {
var itemName = itemNameArray.join("-");
//var itemName = "active-scripts-" + server.hostname + "-" + workerscript.name;
var itemContent = document.getElementById(itemName + "-content")
//Clear the item
while (itemContent.firstChild) {
itemContent.removeChild(itemContent.firstChild);
}
//Add the updated text back. Returns the total online production rate
return createActiveScriptsText(workerscript, itemContent);
}
function createActiveScriptsText(workerscript, item) {
var itemText = document.createElement("p");
//Server ip/hostname
var threads = "Threads: " + workerscript.scriptRef.threads;
var args = "Args: " + printArray(workerscript.args);
//Online
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 onlineMps = workerscript.scriptRef.onlineMoneyMade / workerscript.scriptRef.onlineRunningTime;
var onlineMpsText = "Online production rate: $" + formatNumber(onlineMps, 2) + "/second";
var onlineEps = workerscript.scriptRef.onlineExpGained / workerscript.scriptRef.onlineRunningTime;
var onlineEpsText = (Array(25).join(" ") + formatNumber(onlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;");
//Offline
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 offlineMps = workerscript.scriptRef.offlineMoneyMade / workerscript.scriptRef.offlineRunningTime;
var offlineMpsText = "Offline production rate: $" + formatNumber(offlineMps, 2) + "/second";
var offlineEps = workerscript.scriptRef.offlineExpGained / workerscript.scriptRef.offlineRunningTime;
var offlineEpsText = (Array(26).join(" ") + formatNumber(offlineEps, 4) + " hacking exp/second").replace( / /g, "&nbsp;");
itemText.innerHTML = threads + "<br>" + args + "<br>" + onlineTotalMoneyMade + "<br>" + onlineTotalExpEarned + "<br>" +
onlineMpsText + "<br>" + onlineEpsText + "<br>" + offlineTotalMoneyMade + "<br>" + offlineTotalExpEarned + "<br>" +
offlineMpsText + "<br>" + offlineEpsText + "<br>";
item.appendChild(itemText);
var logButton = document.createElement("span");
logButton.innerHTML = "Log";
var killButton = document.createElement("span");
@ -249,7 +257,9 @@ function createActiveScriptsText(workerscript, item) {
});
item.appendChild(logButton);
item.appendChild(killButton);
//Return total online production rate
return onlineMps;
}
}
export {setActiveScriptsClickHandlers, addActiveScriptsItem, deleteActiveScriptsItem, updateActiveScriptsItems};

@ -1,6 +1,23 @@
/* Alias.js */
Aliases = {};
GlobalAliases = {};
import {post} from "./Terminal.js";
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
function printAliases() {
@ -91,4 +108,7 @@ function substituteAliases(origCommand) {
}
}
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
function Augmentation(name) {
this.name = name;
@ -18,8 +27,8 @@ Augmentation.prototype.setInfo = function(inf) {
}
Augmentation.prototype.setRequirements = function(rep, cost) {
this.baseRepRequirement = rep * CONSTANTS.AugmentationRepMultiplier;
this.baseCost = cost * CONSTANTS.AugmentationCostMultiplier;
this.baseRepRequirement = rep * CONSTANTS.AugmentationRepMultiplier * BitNodeMultipliers.AugmentationRepCost;
this.baseCost = cost * CONSTANTS.AugmentationCostMultiplier * BitNodeMultipliers.AugmentationMoneyCost;
}
//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;
Augmentations = {}
let Augmentations = {}
AddToAugmentations = function(aug) {
function AddToAugmentations(aug) {
var name = aug.name;
Augmentations[name] = aug;
}
AugmentationNames = {
let AugmentationNames = {
Targeting1: "Augmented Targeting I",
Targeting2: "Augmented Targeting II",
Targeting3: "Augmented Targeting III",
@ -153,7 +162,7 @@ AugmentationNames = {
SNA: "Social Negotiation Assistant (S.N.A)"
}
initAugmentations = function() {
function initAugmentations() {
for (var name in Factions) {
if (Factions.hasOwnProperty(name)) {
Factions[name].augmentations = [];
@ -377,7 +386,7 @@ initAugmentations = function() {
}
AddToAugmentations(SpeechProcessor);
TITN41Injection = new Augmentation(AugmentationNames.TITN41Injection);
let TITN41Injection = new Augmentation(AugmentationNames.TITN41Injection);
TITN41Injection.setRequirements(10000, 38000000);
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 " +
@ -1403,7 +1412,7 @@ initAugmentations = function() {
}
}
applyAugmentation = function(aug, reapply=false) {
function applyAugmentation(aug, reapply=false) {
Augmentations[aug.name].owned = true;
switch(aug.name) {
//Combat stat augmentations
@ -1904,7 +1913,7 @@ function PlayerOwnedAugmentation(name) {
function installAugmentations() {
if (Player.queuedAugmentations.length == 0) {
dialogBoxCreate("You have not purchased any Augmentations to install!");
return;
return false;
}
var augmentationList = "";
for (var i = 0; i < Player.queuedAugmentations.length; ++i) {
@ -1923,39 +1932,6 @@ function installAugmentations() {
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) {
return Augmentations.hasOwnProperty(name);
}
@ -1970,3 +1946,6 @@ function giveAllAugmentations() {
}
Player.reapplyAllAugmentations();
}
export {AugmentationNames, Augmentations, PlayerOwnedAugmentation, installAugmentations,
initAugmentations, applyAugmentation, augmentationExists, Augmentation};

@ -1,7 +1,16 @@
/* BitNode.js */
import {Player} from "./Player.js";
BitNodes = {
BitNode1: new BitNode(1, "Source Genesis", "The original BitNode",
function BitNode(n, name, desc="", info="") {
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 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 " +
@ -12,8 +21,8 @@ BitNodes = {
"new BitNode, and also increases all of the player's multipliers by:<br><br>" +
"Level 1: 16%<br>" +
"Level 2: 24%<br>" +
"Level 3: 28%"),
BitNode2: new BitNode(2, "Rise of the Underworld", "From the shadows, they rose", //Gangs
"Level 3: 28%");
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 " +
"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 " +
@ -31,52 +40,71 @@ BitNodes = {
"crime money, and charisma multipliers by:<br><br>" +
"Level 1: 20%<br>" +
"Level 2: 30%<br>" +
"Level 3: 35%"),
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
BitNode5: new BitNode(5, "2084", "COMING SOON"), //Big Brother
BitNode6: new BitNode(6, "Hacktocracy", "COMING SOON"), //Healthy Hacknet balancing mechanic
BitNode7: new BitNode(7, "Do Androids Dream?", "COMING SOON"), //Build androids for automation
BitNode8: new BitNode(8, "Ghost of Wall Street", "COMING SOON"), //Trading only viable strategy
BitNode9: new BitNode(9, "MegaCorp", "COMING SOON"), //Single corp/server with increasing difficulty
BitNode10: new BitNode(10, "Wasteland", "COMING SOON"), //Postapocalyptic
BitNode11: new BitNode(11, "The Big Crash", "COMING SOON"), //Crashing economy
/* Okay. Sell it all.
"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 " +
"of disorder that eventually lead to the governmental reformation of many global superpowers, most notably " +
"the USA and China. But just as the world was slowly beginning to recover from these dark times, financial catastrophe hit.<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 " +
"were able to steal billions of dollars from the world's largest electronic banks, prompting an international banking crisis as " +
"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>" +
"In this BitNode:<br><br>" +
"The starting and maximum amount of money available on servers is significantly decreased<br>" +
"The growth rate of servers is halved<br>" +
"Weakening a server is twice as effective<br>" +
"Company wages are decreased by 25%<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 multiplier by:<br><br>" +
"Level 1: 60%<br>" +
"Level 2: 90%<br>" +
"Level 3: 105%";
"Level 3: 35%");
BitNodes["BitNode3"] = new BitNode(3, "The Price of Civilization", "COMING SOON"); //Corporate Warfare, Run own company
BitNodes["BitNode4"] = new BitNode(4, "The Singularity", "The Man and the Machine", "The Singularity has arrived. The human race is gone, replaced " +
"by artificially superintelligent beings that are more machine than man. <br><br>" +
"In this BitNode, progressing is significantly harder. Experience gain rates " +
"for all stats are reduced. Most methods of earning money will now give significantly less.<br><br>" +
"In this BitNode you will gain access to a new set of Netscript Functions known as Singularity Functions. " +
"These functions allow you to control most aspects of the game through scripts, including working for factions/companies, " +
"purchasing/installing Augmentations, and creating programs.<br><br>" +
"Destroying this BitNode will give you Source-File 4, or if you already have this Source-File it will " +
"upgrade its level up to a maximum of 3. This Source-File lets you access and use the Singularity " +
"Functions in other BitNodes. Each level of this Source-File will open up more Singularity Functions " +
"that you can use.");
BitNodes["BitNode5"] = new BitNode(5, "Artificial Intelligence", "COMING SOON"); //Int
BitNodes["BitNode6"] = new BitNode(6, "Hacktocracy", "COMING SOON"); //Healthy Hacknet balancing mechanic
BitNodes["BitNode7"] = new BitNode(7, "Do Androids Dream?", "COMING SOON"); //Build androids for automation
BitNodes["BitNode8"] = new BitNode(8, "Ghost of Wall Street", "COMING SOON"); //Trading only viable strategy
BitNodes["BitNode9"] = new BitNode(9, "MegaCorp", "COMING SOON"); //Single corp/server with increasing difficulty
BitNodes["BitNode10"] = new BitNode(10, "Wasteland", "COMING SOON"); //Postapocalyptic
BitNodes["BitNode11"] = new BitNode(11, "The Big Crash", "Okay. Sell it all.", //Crashing economy
"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 " +
"of disorder that eventually lead to the governmental reformation of many global superpowers, most notably " +
"the USA and China. But just as the world was slowly beginning to recover from these dark times, financial catastrophe hit.<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 " +
"were able to steal billions of dollars from the world's largest electronic banks, prompting an international banking crisis as " +
"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>" +
"In this BitNode:<br><br>" +
"The starting and maximum amount of money available on servers is significantly decreased<br>" +
"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%");
*/
BitNode12: new BitNode(12, "Eye of the World", "COMING SOON"), //Become AI
BitNodes["BitNode12"] = new BitNode(12, "Eye of the World", "COMING SOON"); //Become AI
}
function BitNode(n, name, desc="", info="") {
this.number = n;
this.name = name;
this.desc = desc;
this.info = info;
}
BitNodeMultipliers = {
let BitNodeMultipliers = {
ServerMaxMoney: 1,
ServerStartingMoney: 1,
ServerGrowthRate: 1,
ServerWeakenRate: 1,
ManualHackMoney: 1,
ScriptHackMoney: 1,
CompanyWorkMoney: 1,
CrimeMoney: 1,
HacknetNodeMoney: 1,
CompanyWorkExpGain: 1,
ClassGymExpGain: 1,
FactionWorkExpGain: 1,
HackExpGain: 1,
CrimeExpGain: 1,
FactionWorkRepGain: 1,
FactionPassiveRepGain: 1,
AugmentationRepCost: 1,
AugmentationMoneyCost: 1,
}
function initBitNodeMultipliers() {
@ -93,13 +121,37 @@ function initBitNodeMultipliers() {
case 1:
break;
case 2: //Rise of the Underworld
BitNodeMultipliers.ServerMaxMoney = 0.2;
BitNodeMultipliers.CrimeMoney = 2;
BitNodeMultipliers.FactionWorkRepGain = 0.5;
BitNodeMultipliers.FactionPassiveRepGain = 0;
BitNodeMultipliers.ServerMaxMoney = 0.2;
BitNodeMultipliers.CrimeMoney = 2;
BitNodeMultipliers.FactionWorkRepGain = 0.5;
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;
default:
console.log("WARNING: Player.bitNodeN invalid");
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
// Note: Company Positions can be loaded every time with init() but Company class needs
// to be saved/loaded from localStorage
@ -251,7 +258,7 @@ CompanyPosition.fromJSON = function(value) {
Reviver.constructors.CompanyPosition = CompanyPosition;
CompanyPositions = {
let CompanyPositions = {
//Constructor: CompanyPosition(name, reqHack, reqStr, reqDef, reqDex, reqAgi, reqCha, reqRep, salary)
//Software
@ -403,7 +410,7 @@ CompanyPositions = {
//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
getNextCompanyPosition = function(currPos) {
function getNextCompanyPosition(currPos) {
if (currPos == null) {return null;}
//Software
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
* usually loaded from localStorage */
initCompanies = function() {
function initCompanies() {
/* Companies that also have servers */
//Megacorporations
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
Companies = {}
let Companies = {}
function loadCompanies(saveString) {
Companies = JSON.parse(saveString, Reviver);
}
//Add a Company object onto the map of all Companies in the game
AddToCompanies = function (company) {
function AddToCompanies(company) {
var name = company.companyName;
Companies[name] = company;
}
@ -1099,3 +1110,41 @@ AddToCompanies = function (company) {
function companyExists(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 */
//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;
}
//TODO probably just move this to whatever file needs it then delete this

@ -1,5 +1,5 @@
CONSTANTS = {
Version: "0.27.3",
let CONSTANTS = {
Version: "0.28.1",
//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
@ -75,8 +75,12 @@ CONSTANTS = {
ScriptRoundRamCost: 0.05,
ScriptReadWriteRamCost: 1.0,
ScriptArbScriptRamCost: 1.0, //Functions that apply to all scripts regardless of args
ScriptGetScriptCost: 0.1,
ScriptGetHackTimeCost: 0.05,
ScriptGetScriptRamCost: 0.1,
ScriptGetHackTimeRamCost: 0.05,
ScriptSingularityFn1RamCost: 1,
ScriptSingularityFn2RamCost: 2,
ScriptSingularityFn3RamCost: 3,
MultithreadingRAMCost: 1,
@ -320,6 +324,9 @@ CONSTANTS = {
"numeric - Integers and floats (eg. 6, 10.4999)<br>" +
"string - Encapsulated by single or double quotes (eg. 'this is a string')<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>" +
"i = 5;<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 " +
"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>" +
"<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>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>" +
@ -618,6 +626,140 @@ CONSTANTS = {
"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, " +
"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> " +
" Aevum<br>" +
@ -717,38 +859,14 @@ CONSTANTS = {
"World Stock Exchange account and TIX API Access<br>",
LatestUpdate:
"v0.27.3<br>" +
"-You can now purchase upgrades for Gang Members (BitNode 2 only)<br>" +
"-Decreased Gang respect gains and slightly increased wanted gains (BitNode 2 only)<br>" +
"-Other gangs will increase in power faster (BitNode 2 only)<br>" +
"-Added getHackTime(), getGrowTime(), and getWeakenTime() Netscript functions<br><br>" +
"v0.27.2<br>" +
"-Added getServerGrowth() Netscript function<br>" +
"-Added getNextHacknetNodeCost() Netscript function<br>" +
"-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>"
"v0.28.1<br>" +
"-The script editor now uses the open-source Ace editor, which provides a much better experience when coding!<br>" +
"-Added tprint() Netscript function<br><br>" +
"v0.28.0<br>" +
"-Added BitNode-4: The Singularity<br>" +
"-Added BitNode-11: The Big Crash<br>" +
"-Migrated the codebase to use webpack (doesn't affect any in game content, except maybe some slight " +
"performance improvements and there may be bugs that result from dependency errors)"
}
export {CONSTANTS};

@ -1,17 +1,20 @@
import {CONSTANTS} from "./Constants.js";
import {Player} from "./Player.js";
/* Create programs */
Programs = {
NukeProgram: "NUKE.exe",
BruteSSHProgram: "BruteSSH.exe",
FTPCrackProgram: "FTPCrack.exe",
RelaySMTPProgram: "relaySMTP.exe",
HTTPWormProgram: "HTTPWorm.exe",
SQLInjectProgram: "SQLInject.exe",
DeepscanV1: "DeepscanV1.exe",
DeepscanV2: "DeepscanV2.exe",
ServerProfiler: "ServerProfiler.exe",
AutoLink: "AutoLink.exe",
Flight: "fl1ght.exe",
}
let Programs = {
NukeProgram: "NUKE.exe",
BruteSSHProgram: "BruteSSH.exe",
FTPCrackProgram: "FTPCrack.exe",
RelaySMTPProgram: "relaySMTP.exe",
HTTPWormProgram: "HTTPWorm.exe",
SQLInjectProgram: "SQLInject.exe",
DeepscanV1: "DeepscanV1.exe",
DeepscanV2: "DeepscanV2.exe",
ServerProfiler: "ServerProfiler.exe",
AutoLink: "AutoLink.exe",
Flight: "fl1ght.exe",
};
//TODO Right now the times needed to complete work are hard-coded...
//maybe later make this dependent on hacking level or something
@ -26,9 +29,9 @@ function displayCreateProgramContent() {
var deepscanv2ALink = document.getElementById("create-program-deepscanv2");
var servProfilerALink = document.getElementById("create-program-serverprofiler");
var autolinkALink = document.getElementById("create-program-autolink");
nukeALink.style.display = "none";
bruteSshALink.style.display = "none";
bruteSshALink.style.display = "none";
ftpCrackALink.style.display = "none";
relaySmtpALink.style.display = "none";
httpWormALink.style.display = "none";
@ -37,15 +40,15 @@ function displayCreateProgramContent() {
deepscanv2ALink.style.display = "none";
servProfilerALink.style.display = "none";
autolinkALink.style.display = "none";
//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";
}
//BruteSSH
if (Player.getHomeComputer().programs.indexOf(Programs.BruteSSHProgram) == -1 &&
Player.hacking_skill >= 50) {
bruteSshALink.style.display = "inline-block";
bruteSshALink.style.display = "inline-block";
}
//FTPCrack
if (Player.getHomeComputer().programs.indexOf(Programs.FTPCrackProgram) == -1 &&
@ -88,7 +91,7 @@ function displayCreateProgramContent() {
function getNumAvailableCreateProgram() {
var count = 0;
//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;
}
//BruteSSH
@ -131,6 +134,7 @@ function getNumAvailableCreateProgram() {
if (!Player.hasProgram(Programs.AutoLink) && Player.hacking_skill >= 25) {
++count;
}
if (count > 0) {Player.firstProgramAvailable = true;}
return count;
}
@ -145,7 +149,7 @@ function initCreateProgramButtons() {
var deepscanv2ALink = document.getElementById("create-program-deepscanv2");
var servProfilerALink = document.getElementById("create-program-serverprofiler");
var autolinkALink = document.getElementById("create-program-autolink");
nukeALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.NukeProgram, CONSTANTS.MillisecondsPerFiveMinutes, 1);
return false;
@ -185,5 +189,8 @@ function initCreateProgramButtons() {
autolinkALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.AutoLink, CONSTANTS.MillisecondsPerQuarterHour, 25);
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 */
function commitShopliftCrime() {
Player.crimeType = CONSTANTS.CrimeShoplift;
@ -202,3 +206,14 @@ function determineCrimeChanceHeist() {
chance *= Player.crime_success_mult;
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 */
//Posts a "help" message if connected to DarkWeb
checkIfConnectedToDarkweb = function() {
function checkIfConnectedToDarkweb() {
if (SpecialServerIps.hasOwnProperty("Darkweb Server")) {
var darkwebIp = SpecialServerIps["Darkweb Server"];
if (!isValidIPAddress(darkwebIp)) {return;}
@ -16,7 +24,7 @@ checkIfConnectedToDarkweb = function() {
//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
//rather than the command string
executeDarkwebTerminalCommand = function(commandArray) {
function executeDarkwebTerminalCommand(commandArray) {
if (commandArray.length == 0) {return;}
switch (commandArray[0]) {
case "buy":
@ -24,6 +32,7 @@ executeDarkwebTerminalCommand = function(commandArray) {
post("Incorrect number of arguments. Usage: ");
post("buy -l");
post("buy [item name]");
return;
}
var arg = commandArray[1];
if (arg == "-l") {
@ -38,7 +47,7 @@ executeDarkwebTerminalCommand = function(commandArray) {
}
}
listAllDarkwebItems = function() {
function listAllDarkwebItems() {
for (var item in DarkWebItems) {
if (DarkWebItems.hasOwnProperty(item)) {
var item = DarkWebItems[item];
@ -76,7 +85,7 @@ listAllDarkwebItems = function() {
else {return price;}
}
buyDarkwebItem = function(itemName) {
function buyDarkwebItem(itemName) {
if (itemName.toLowerCase() == Programs.BruteSSHProgram.toLowerCase()) {
var price = parseDarkwebItemPrice(DarkWebItems.BruteSSHProgram);
if (price > 0 && Player.money.gt(price)) {
@ -152,7 +161,7 @@ buyDarkwebItem = function(itemName) {
}
}
parseDarkwebItemPrice = function(itemDesc) {
function parseDarkwebItemPrice(itemDesc) {
var split = itemDesc.split(" - ");
if (split.length == 3) {
var priceString = split[1];
@ -173,12 +182,16 @@ parseDarkwebItemPrice = function(itemDesc) {
}
}
DarkWebItems = {
BruteSSHProgram: Programs.BruteSSHProgram + " - $500,000 - Opens up SSH Ports",
FTPCrackProgram: Programs.FTPCrackProgram + " - $1,500,000 - Opens up FTP Ports",
RelaySMTPProgram: Programs.RelaySMTPProgram + " - $5,000,000 - Opens up SMTP Ports",
HTTPWormProgram: Programs.HTTPWormProgram + " - $30,000,000 - Opens up HTTP Ports",
SQLInjectProgram: Programs.SQLInjectProgram + " - $250,000,000 - Opens up SQL Ports",
DeepScanV1Program: Programs.DeepscanV1 + " - $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",
let DarkWebItems = {
BruteSSHProgram: "BruteSSH.exe - $500,000 - Opens up SSH Ports",
FTPCrackProgram: "FTPCrack.exe - $1,500,000 - Opens up FTP Ports",
RelaySMTPProgram: "relaySMTP.exe - $5,000,000 - Opens up SMTP Ports",
HTTPWormProgram: "HTTPWorm.exe - $30,000,000 - Opens up HTTP Ports",
SQLInjectProgram: "SQLInject.exe - $250,000,000 - Opens up SQL Ports",
DeepScanV1Program: "DeepscanV1.exe - $500,000 - Enables 'scan-analyze' with a depth up to 5",
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
function factionInit() {
$('#faction-donate-input').on('input', function() {
@ -97,9 +117,13 @@ Faction.fromJSON = function(value) {
Reviver.constructors.Faction = Faction;
//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;
Factions[name] = faction;
}
@ -110,7 +134,7 @@ function factionExists(name) {
//TODO Augmentation price and rep requirement mult are 1 for everything right now,
// This might change in the future for balance
initFactions = function() {
function initFactions() {
//Endgame
var Illuminati = new Faction("Illuminati");
Illuminati.setInfo(FactionInfo.IlluminatiInfo);
@ -368,304 +392,7 @@ initFactions = function() {
AddToFactions(CyberSec);
}
//This function sets the requirements to join a Faction. It checks whether the Player meets
//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) {
function inviteToFaction(faction) {
if (Settings.SuppressFactionInvites) {
faction.alreadyInvited = true;
Player.factionInvitations.push(faction.name);
@ -674,7 +401,7 @@ inviteToFaction = function(faction) {
}
}
joinFaction = function(faction) {
function joinFaction(faction) {
faction.isMember = true;
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
displayFactionContent = function(factionName) {
function displayFactionContent(factionName) {
var faction = Factions[factionName];
document.getElementById("faction-name").innerHTML = factionName;
document.getElementById("faction-info").innerHTML = "<i>" + faction.info + "</i>";
@ -882,8 +570,8 @@ displayFactionContent = function(factionName) {
noBtn.innerHTML = "Cancel";
yesBtn.addEventListener("click", () => {
var hacking = false;
if (factionName == "NiteSec" || factionName == "The Black Hand") {hacking = true;}
Player.gang = new Gang(factionName, hacking);
if (factionName === "NiteSec" || factionName === "The Black Hand") {hacking = true;}
Player.startGang(factionName, hacking);
Engine.loadGangContent();
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;
var faction = Factions[factionName];
@ -1150,87 +838,12 @@ displayFactionAugmentations = function(factionName) {
}
}
purchaseAugmentationBoxCreate = function(aug, fac) {
function purchaseAugmentationBoxCreate(aug, fac) {
var yesBtn = yesNoBoxGetYesButton(), noBtn = yesNoBoxGetNoButton();
yesBtn.innerHTML = "Purchase";
noBtn.innerHTML = "Cancel";
yesBtn.addEventListener("click", function() {
//TODO Requirements for specific augmentations (e.g Embedded Netburner Module b4 its upgrades)
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();
purchaseAugmentation(aug, fac);
});
noBtn.addEventListener("click", function() {
yesNoBoxClose();
@ -1242,6 +855,107 @@ purchaseAugmentationBoxCreate = function(aug, fac) {
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() {
var aug = Augmentations[AugmentationNames.NeuroFluxGovernor];
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
//of each faction
FactionInfo = {
let FactionInfo = {
//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. ",
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. " +
"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.",
//Megacorporations, each forms its own faction
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 " +
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 " +
"information universally accessible.",
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 " +
"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.",
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",
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.",
ClarkeIncorporatedInfo: "Unlocking the power of the genome",
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.",
KuaiGongInternationalInfo: "Dream big. Work hard. Make history.",
//Other Corporations
FulcrumSecretTechnologiesInfo: "TODO",
//Hacker groups
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 " +
@ -47,14 +47,14 @@ FactionInfo = {
"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>" +
"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. " +
"Technological power. " +
BlackHandInfo: "The world, so afraid of strong government, now has no government. Only power - Digital power. Financial power. " +
"Technological power. " +
"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>" +
"So much pain. So many lives. Their darkness must end.",
"So much pain. So many lives. Their darkness must end.",
NiteSecInfo:
" __..__ <br>" +
" _.nITESECNIt. <br>" +
@ -91,7 +91,7 @@ FactionInfo = {
" d .dNITESEC $ | <br>" +
" :bp.__.gNITESEC$$ :$ ; <br>" +
" NITESECNITESECNIT $$b : <br>",
//City factions, essentially governments
ChongqingInfo: "Serve the people",
Sector12Info: "The City of the Future",
@ -99,32 +99,34 @@ FactionInfo = {
AevumInfo: "The Silicon City",
IshimaInfo: "The East Asian Order of the Future",
VolhavenInfo: "Benefit, Honour, and Glory",
//Criminal Organizations/Gangs
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.",
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 " +
"for. <br><br>" +
"for. <br><br>" +
"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",
SlumSnakesInfo: "Slum Snakes rule!",
//Earlygame factions - factions the player will prestige with early on that don't
//belong in other categories
NetburnersInfo: "~~//*>H4CK|\|3T 8URN3R5**>?>\\~~",
TianDiHuiInfo: "Obey Heaven and Work Righteousness",
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. " +
"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 */
//Switch between territory and management screen with 1 and 2
$(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"];
GangLocations = [Locations.Aevum, Locations.Chongqing, Locations.Sector12, Locations.NewTokyo,
Locations.Ishima, Locations.Volhaven];
AllGangs = {
let GangLocations = [Locations.Aevum, Locations.Chongqing, Locations.Sector12, Locations.NewTokyo,
Locations.Ishima, Locations.Volhaven];
let AllGangs = {
"Slum Snakes" : {
power: 1,
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
gangStoredPowerCycles = 0;
let gangStoredPowerCycles = 0;
function processAllGangPowerGains(numCycles=1) {
if (!Player.inGang()) {return;}
gangStoredPowerCycles += numCycles;
@ -85,7 +106,7 @@ function processAllGangPowerGains(numCycles=1) {
gangStoredPowerCycles -= 150;
}
gangStoredTerritoryCycles = 0;
let gangStoredTerritoryCycles = 0;
function processAllGangTerritory(numCycles=1) {
if (!Player.inGang()) {return;}
gangStoredTerritoryCycles += numCycles;
@ -118,12 +139,6 @@ function processAllGangTerritory(numCycles=1) {
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
hacking - Boolean indicating whether its a hacking gang or not
*/
@ -230,7 +245,6 @@ Gang.fromJSON = function(value) {
Reviver.constructors.Gang = Gang;
/*** Gang Member object ***/
function GangMember(name) {
this.name = name;
@ -405,7 +419,7 @@ GangMemberTask.fromJSON = function(value) {
Reviver.constructors.GangMemberTask = GangMemberTask;
//TODO Human trafficking and an equivalent hacking crime
GangMemberTasks = {
let GangMemberTasks = {
"Ransomware" : new GangMemberTask(
"Ransomware",
"Assign this gang member to create and distribute ransomware<br><br>" +
@ -674,7 +688,7 @@ GangMemberUpgrade.fromJSON = function(value) {
Reviver.constructors.GangMemberUpgrade = GangMemberUpgrade;
GangMemberUpgrades = {
let GangMemberUpgrades = {
"Baseball Bat" : new GangMemberUpgrade("Baseball Bat",
"Increases strength and defense by 10%", 1000000, "w"),
"Katana" : new GangMemberUpgrade("Katana",
@ -716,7 +730,7 @@ GangMemberUpgrades = {
}
//Create a pop-up box that lets player purchase upgrades
var gangMemberUpgradeBoxOpened = false;
let gangMemberUpgradeBoxOpened = false;
function createGangMemberUpgradeBox(memberObj) {
console.log("Creating gang member upgrade box for " + memberObj.name);
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() {
if (!gangContentCreated) {
gangContentCreated = true;
@ -1084,7 +1098,7 @@ function setGangMemberClickHandlers() {
console.log("ERROR: Could not find Active Scripts server panels");
return;
}
for (i = 0; i < gangMemberHdrs.length; ++i) {
for (let i = 0; i < gangMemberHdrs.length; ++i) {
gangMemberHdrs[i].onclick = function() {
this.classList.toggle("active");
@ -1168,7 +1182,7 @@ function createGangMemberDisplayElement(memberObj) {
if (memberObj.task instanceof GangMemberTask) {
var taskName = memberObj.task.name;
var taskIndex = 0;
for (i = 0; i < tasks.length; ++i) {
for (let i = 0; i < tasks.length; ++i) {
if (taskName == tasks[i]) {
taskIndex = i;
break;
@ -1247,3 +1261,5 @@ function setGangMemberTaskDescription(memberObj, taskName) {
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 */
function hacknetNodesInit() {
var mult1x = document.getElementById("hacknet-nodes-1x-multiplier");
@ -50,7 +62,9 @@ HacknetNode.prototype.updateMoneyGainRate = function() {
this.moneyGainRatePerSecond = (this.level * gainPerLevel) *
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)) {
this.moneyGainRatePerSecond = 0;
dialogBoxCreate("Error in calculating Hacknet Node production. Please report to game developer");
@ -165,7 +179,7 @@ HacknetNode.fromJSON = function(value) {
Reviver.constructors.HacknetNode = HacknetNode;
purchaseHacknet = function() {
function purchaseHacknet() {
/* INTERACTIVE TUTORIAL */
if (iTutorialIsRunning) {
if (currITutorialStep == iTutorialSteps.HacknetNodesIntroduction) {
@ -199,7 +213,7 @@ purchaseHacknet = function() {
}
//Calculates the total production from all HacknetNodes
updateTotalHacknetProduction = function() {
function updateTotalHacknetProduction() {
var total = 0;
for (var i = 0; i < Player.hacknetNodes.length; ++i) {
total += Player.hacknetNodes[i].moneyGainRatePerSecond;
@ -207,7 +221,7 @@ updateTotalHacknetProduction = function() {
Player.totalHacknetNodeProduction = total;
}
getCostOfNextHacknetNode = function() {
function getCostOfNextHacknetNode() {
//Cost increases exponentially based on how many you own
var numOwned = Player.hacknetNodes.length;
var mult = CONSTANTS.HacknetNodePurchaseNextMult;
@ -215,7 +229,7 @@ getCostOfNextHacknetNode = function() {
}
var hacknetNodePurchaseMultiplier = 1;
updateHacknetNodesMultiplierButtons = function() {
function updateHacknetNodesMultiplierButtons() {
var mult1x = document.getElementById("hacknet-nodes-1x-multiplier");
var mult5x = document.getElementById("hacknet-nodes-5x-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
//a Hacknet Node's level"
getMaxNumberLevelUpgrades = function(nodeObj) {
function getMaxNumberLevelUpgrades(nodeObj) {
if (Player.money.lt(nodeObj.calculateLevelUpgradeCost(1))) {return 0;}
var min = 1;
var max = CONSTANTS.HacknetNodeMaxLevel-1;
@ -268,7 +282,7 @@ getMaxNumberLevelUpgrades = function(nodeObj) {
}
//Creates Hacknet Node DOM elements when the page is opened
displayHacknetNodesContent = function() {
function displayHacknetNodesContent() {
//Update Hacknet Nodes button
var newPurchaseButton = clearEventListeners("hacknet-nodes-purchase-button");
@ -294,7 +308,7 @@ displayHacknetNodesContent = function() {
}
//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
var cost = getCostOfNextHacknetNode();
var purchaseButton = document.getElementById("hacknet-nodes-purchase-button");
@ -317,7 +331,7 @@ updateHacknetNodesContent = function() {
}
//Creates a single Hacknet Node DOM element
createHacknetNodeDomElement = function(nodeObj) {
function createHacknetNodeDomElement(nodeObj) {
var nodeName = nodeObj.name;
var listItem = document.createElement("li");
@ -383,7 +397,7 @@ createHacknetNodeDomElement = function(nodeObj) {
}
//Updates information on a single hacknet node DOM element
updateHacknetNodeDomElement = function(nodeObj) {
function updateHacknetNodeDomElement(nodeObj) {
var nodeName = nodeObj.name;
var txt = document.getElementById("hacknet-node-text-" + nodeName);
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;
for (var i = 0; i < Player.hacknetNodes.length; ++i) {
total += processSingleHacknetNodeEarnings(numCycles, Player.hacknetNodes[i]);
@ -461,7 +475,7 @@ processAllHacknetNodeEarnings = function(numCycles) {
return total;
}
processSingleHacknetNodeEarnings = function(numCycles, nodeObj) {
function processSingleHacknetNodeEarnings(numCycles, nodeObj) {
var cyclesPerSecond = 1000 / Engine._idleSpeed;
var earningPerCycle = nodeObj.moneyGainRatePerSecond / cyclesPerSecond;
if (isNaN(earningPerCycle)) {throw new Error("Calculated Earnings is not a number");}
@ -472,7 +486,7 @@ processSingleHacknetNodeEarnings = function(numCycles, nodeObj) {
return totalEarnings;
}
getHacknetNode = function(name) {
function getHacknetNode(name) {
for (var i = 0; i < Player.hacknetNodes.length; ++i) {
if (Player.hacknetNodes[i].name == name) {
return Player.hacknetNodes[i];
@ -480,3 +494,8 @@ getHacknetNode = function(name) {
}
return null;
}
export {hacknetNodesInit, HacknetNode, purchaseHacknet, updateTotalHacknetProduction,
getCostOfNextHacknetNode, updateHacknetNodesMultiplierButtons, getMaxNumberLevelUpgrades,
displayHacknetNodesContent, updateHacknetNodesContent, processAllHacknetNodeEarnings,
getHacknetNode};

@ -1,8 +1,9 @@
/* HelpText.js */
TerminalHelpText =
let TerminalHelpText =
"Type 'help name' to learn more about the command 'name'<br><br>" +
'alias [-g] [name="value"] Create or display Terminal aliases<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>" +
"check [script] [args...] Print a script's logs to 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>" +
'unalias "[alias name]" Deletes the specified alias<br>';
HelpTexts = {
let HelpTexts = {
alias: 'alias [-g] [name="value"] <br>' +
"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 " +
@ -56,6 +57,11 @@ HelpTexts = {
"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 " +
"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>" +
"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>" +
@ -159,7 +165,7 @@ HelpTexts = {
"it has",
scp: "scp [filename] [target server]<br>" +
"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.",
sudov: "sudov<br>" +
"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'",
}
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
*
* Kill
@ -16,7 +24,7 @@
* Escape
*/
InfiltrationScenarios = {
let InfiltrationScenarios = {
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.",
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;
}
function beginInfiltration(companyName, startLevel, val, maxClearance, diff) {
var inst = new InfiltrationInstance(companyName, startLevel, val, maxClearance, diff);
clearInfiltrationStatusText();
@ -796,3 +802,5 @@ function getInfiltrationEscapeChance(inst) {
(2 * Player.agility +
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 */
iTutorialSteps = {
let iTutorialSteps = {
Start: "Start",
GoToCharacterPage: "Click on the Character page menu link",
CharacterPage: "Introduction to Character page",
@ -652,3 +656,6 @@ function iTutorialSetText(txt) {
textBox.innerHTML = txt;
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
* Lore / world building literature that can be found on servers
*/
@ -15,7 +17,7 @@ function showLiterature(fn) {
dialogBoxCreate(txt);
}
Literatures = {}
let Literatures = {}
function initLiterature() {
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>" +
"From the ashes rose a new order, corporatocracy was its name<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";
Literatures[fn] = new Literature(title, fn, txt);
@ -265,7 +267,7 @@ function initLiterature() {
title = "The Hidden World";
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 ILLUMINATI ARE THE SECRET RULERS OF THE WORLD!<br><br>" +
"Yes, the Illuminati of legends. The ancient secret society that controls the entire " +
@ -317,3 +319,5 @@ function initLiterature() {
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*/
Locations = {
let Locations = {
//Cities
Aevum: "Aevum",
//AevumDesc: ""
@ -86,7 +115,7 @@ Locations = {
WorldStockExchange: "World Stock Exchange",
}
displayLocationContent = function() {
function displayLocationContent() {
if (Engine.debug) {
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
aevumTravelAgency = document.getElementById("aevum-travelagency");
let aevumTravelAgency = document.getElementById("aevum-travelagency");
aevumTravelAgency.addEventListener("click", function() {
Player.location = Locations.AevumTravelAgency;
Engine.loadLocationContent();
return false;
});
aevumHospital = document.getElementById("aevum-hospital");
let aevumHospital = document.getElementById("aevum-hospital");
aevumHospital.addEventListener("click", function() {
Player.location = Locations.Hospital;
Engine.loadLocationContent();
return false;
});
aevumSummitUniversity = document.getElementById("aevum-summituniversity");
let aevumSummitUniversity = document.getElementById("aevum-summituniversity");
aevumSummitUniversity.addEventListener("click", function() {
Player.location = Locations.AevumSummitUniversity;
Engine.loadLocationContent();
return false;
});
aevumECorp = document.getElementById("aevum-ecorp");
let aevumECorp = document.getElementById("aevum-ecorp");
aevumECorp.addEventListener("click", function() {
Player.location = Locations.AevumECorp;
Engine.loadLocationContent();
return false;
});
aevumBachmanAndAssociates = document.getElementById("aevum-bachmanandassociates");
let aevumBachmanAndAssociates = document.getElementById("aevum-bachmanandassociates");
aevumBachmanAndAssociates.addEventListener("click", function() {
Player.location = Locations.AevumBachmanAndAssociates;
Engine.loadLocationContent();
return false;
});
aevumClarkeIncorporated = document.getElementById("aevum-clarkeincorporated");
let aevumClarkeIncorporated = document.getElementById("aevum-clarkeincorporated");
aevumClarkeIncorporated.addEventListener("click", function() {
Player.location = Locations.AevumClarkeIncorporated;
Engine.loadLocationContent();
return false;
});
aevumFulcrumTechnologies = document.getElementById("aevum-fulcrumtechnologies");
let aevumFulcrumTechnologies = document.getElementById("aevum-fulcrumtechnologies");
aevumFulcrumTechnologies.addEventListener("click", function() {
Player.location = Locations.AevumFulcrumTechnologies;
Engine.loadLocationContent();
return false;
});
aevumAeroCorp = document.getElementById("aevum-aerocorp");
let aevumAeroCorp = document.getElementById("aevum-aerocorp");
aevumAeroCorp.addEventListener("click", function() {
Player.location = Locations.AevumAeroCorp;
Engine.loadLocationContent();
return false;
});
aevumGalacticCybersystems = document.getElementById("aevum-galacticcybersystems");
let aevumGalacticCybersystems = document.getElementById("aevum-galacticcybersystems");
aevumGalacticCybersystems.addEventListener("click", function() {
Player.location = Locations.AevumGalacticCybersystems;
Engine.loadLocationContent();
return false;
});
aevumWatchdogSecurity = document.getElementById("aevum-watchdogsecurity");
let aevumWatchdogSecurity = document.getElementById("aevum-watchdogsecurity");
aevumWatchdogSecurity.addEventListener("click", function() {
Player.location = Locations.AevumWatchdogSecurity;
Engine.loadLocationContent();
return false;
});
aevumRhoConstruction = document.getElementById("aevum-rhoconstruction");
let aevumRhoConstruction = document.getElementById("aevum-rhoconstruction");
aevumRhoConstruction.addEventListener("click", function() {
Player.location = Locations.AevumRhoConstruction;
Engine.loadLocationContent();
return false;
});
aevumPolice = document.getElementById("aevum-aevumpolice");
let aevumPolice = document.getElementById("aevum-aevumpolice");
aevumPolice.addEventListener("click", function() {
Player.location = Locations.AevumPolice;
Engine.loadLocationContent();
return false;
});
aevumNetLinkTechnologies = document.getElementById("aevum-netlinktechnologies");
let aevumNetLinkTechnologies = document.getElementById("aevum-netlinktechnologies");
aevumNetLinkTechnologies.addEventListener("click", function() {
Player.location = Locations.AevumNetLinkTechnologies;
Engine.loadLocationContent();
return false;
});
aevumCrushFitnessGym = document.getElementById("aevum-crushfitnessgym");
let aevumCrushFitnessGym = document.getElementById("aevum-crushfitnessgym");
aevumCrushFitnessGym.addEventListener("click", function() {
Player.location = Locations.AevumCrushFitnessGym;
Engine.loadLocationContent();
return false;
});
aevumSnapFitnessGym = document.getElementById("aevum-snapfitnessgym");
let aevumSnapFitnessGym = document.getElementById("aevum-snapfitnessgym");
aevumSnapFitnessGym.addEventListener("click", function() {
Player.location = Locations.AevumSnapFitnessGym;
Engine.loadLocationContent();
return false;
});
aevumSlums = document.getElementById("aevum-slums");
let aevumSlums = document.getElementById("aevum-slums");
aevumSlums.addEventListener("click", function() {
Player.location = Locations.AevumSlums;
Engine.loadLocationContent();
return false;
});
chongqingTravelAgency = document.getElementById("chongqing-travelagency");
let chongqingTravelAgency = document.getElementById("chongqing-travelagency");
chongqingTravelAgency.addEventListener("click", function() {
Player.location = Locations.ChongqingTravelAgency;
Engine.loadLocationContent();
return false;
});
chongqingHospital = document.getElementById("chongqing-hospital");
let chongqingHospital = document.getElementById("chongqing-hospital");
chongqingHospital.addEventListener("click", function() {
Player.location = Locations.Hospital;
Engine.loadLocationContent();
return false;
});
chongqingKuaiGongInternational = document.getElementById("chongqing-kuaigonginternational");
let chongqingKuaiGongInternational = document.getElementById("chongqing-kuaigonginternational");
chongqingKuaiGongInternational.addEventListener("click", function() {
Player.location = Locations.ChongqingKuaiGongInternational;
Engine.loadLocationContent();
return false;
});
chongqingSolarisSpaceSystems = document.getElementById("chongqing-solarisspacesystems");
let chongqingSolarisSpaceSystems = document.getElementById("chongqing-solarisspacesystems");
chongqingSolarisSpaceSystems.addEventListener("click", function() {
Player.location = Locations.ChongqingSolarisSpaceSystems;
Engine.loadLocationContent();
return false;
});
chongqingSlums = document.getElementById("chongqing-slums");
let chongqingSlums = document.getElementById("chongqing-slums");
chongqingSlums.addEventListener("click", function() {
Player.location = Locations.ChongqingSlums;
Engine.loadLocationContent();
return false;
});
sector12TravelAgency = document.getElementById("sector12-travelagency");
let sector12TravelAgency = document.getElementById("sector12-travelagency");
sector12TravelAgency.addEventListener("click", function() {
Player.location = Locations.Sector12TravelAgency;
Engine.loadLocationContent();
return false;
});
sector12Hospital = document.getElementById("sector12-hospital");
let sector12Hospital = document.getElementById("sector12-hospital");
sector12Hospital.addEventListener("click", function() {
Player.location = Locations.Hospital;
Engine.loadLocationContent();
return false;
});
sector12RothmanUniversity = document.getElementById("sector12-rothmanuniversity");
let sector12RothmanUniversity = document.getElementById("sector12-rothmanuniversity");
sector12RothmanUniversity.addEventListener("click", function() {
Player.location = Locations.Sector12RothmanUniversity;
Engine.loadLocationContent();
return false;
});
sector12MegaCorp = document.getElementById("sector12-megacorp");
let sector12MegaCorp = document.getElementById("sector12-megacorp");
sector12MegaCorp.addEventListener("click", function() {
Player.location = Locations.Sector12MegaCorp;
Engine.loadLocationContent();
return false;
});
sector12BladeIndustries = document.getElementById("sector12-bladeindustries");
let sector12BladeIndustries = document.getElementById("sector12-bladeindustries");
sector12BladeIndustries.addEventListener("click", function() {
Player.location = Locations.Sector12BladeIndustries;
Engine.loadLocationContent();
return false;
});
sector12FourSigma = document.getElementById("sector12-foursigma");
let sector12FourSigma = document.getElementById("sector12-foursigma");
sector12FourSigma.addEventListener("click", function() {
Player.location = Locations.Sector12FourSigma;
Engine.loadLocationContent();
return false;
});
sector12IcarusMicrosystems = document.getElementById("sector12-icarusmicrosystems");
let sector12IcarusMicrosystems = document.getElementById("sector12-icarusmicrosystems");
sector12IcarusMicrosystems.addEventListener("click", function() {
Player.location = Locations.Sector12IcarusMicrosystems;
Engine.loadLocationContent();
return false;
});
sector12UniversalEnergy = document.getElementById("sector12-universalenergy");
let sector12UniversalEnergy = document.getElementById("sector12-universalenergy");
sector12UniversalEnergy.addEventListener("click", function() {
Player.location = Locations.Sector12UniversalEnergy;
Engine.loadLocationContent();
return false;
});
sector12DeltaOne = document.getElementById("sector12-deltaone");
let sector12DeltaOne = document.getElementById("sector12-deltaone");
sector12DeltaOne.addEventListener("click", function() {
Player.location = Locations.Sector12DeltaOne;
Engine.loadLocationContent();
return false;
});
sector12CIA = document.getElementById("sector12-cia");
let sector12CIA = document.getElementById("sector12-cia");
sector12CIA.addEventListener("click", function() {
Player.location = Locations.Sector12CIA;
Engine.loadLocationContent();
return false;
});
sector12NSA = document.getElementById("sector12-nsa");
let sector12NSA = document.getElementById("sector12-nsa");
sector12NSA.addEventListener("click", function() {
Player.location = Locations.Sector12NSA;
Engine.loadLocationContent();
return false;
});
sector12AlphaEnterprises = document.getElementById("sector12-alphaenterprises");
let sector12AlphaEnterprises = document.getElementById("sector12-alphaenterprises");
sector12AlphaEnterprises.addEventListener("click", function() {
Player.location = Locations.Sector12AlphaEnterprises;
Engine.loadLocationContent();
return false;
});
sector12CarmichaelSecurity = document.getElementById("sector12-carmichaelsecurity");
let sector12CarmichaelSecurity = document.getElementById("sector12-carmichaelsecurity");
sector12CarmichaelSecurity.addEventListener("click", function() {
Player.location = Locations.Sector12CarmichaelSecurity;
Engine.loadLocationContent();
return false;
});
sector12FoodNStuff = document.getElementById("sector12-foodnstuff");
let sector12FoodNStuff = document.getElementById("sector12-foodnstuff");
sector12FoodNStuff.addEventListener("click", function() {
Player.location = Locations.Sector12FoodNStuff;
Engine.loadLocationContent();
return false;
});
sector12JoesGuns = document.getElementById("sector12-joesguns");
let sector12JoesGuns = document.getElementById("sector12-joesguns");
sector12JoesGuns.addEventListener("click", function() {
Player.location = Locations.Sector12JoesGuns;
Engine.loadLocationContent();
return false;
});
sector12IronGym = document.getElementById("sector12-irongym");
let sector12IronGym = document.getElementById("sector12-irongym");
sector12IronGym.addEventListener("click", function() {
Player.location = Locations.Sector12IronGym;
Engine.loadLocationContent();
return false;
});
sector12PowerhouseGym = document.getElementById("sector12-powerhousegym");
let sector12PowerhouseGym = document.getElementById("sector12-powerhousegym");
sector12PowerhouseGym.addEventListener("click", function() {
Player.location = Locations.Sector12PowerhouseGym;
Engine.loadLocationContent();
return false;
});
sector12Slums = document.getElementById("sector12-slums");
let sector12Slums = document.getElementById("sector12-slums");
sector12Slums.addEventListener("click", function() {
Player.location = Locations.Sector12Slums;
Engine.loadLocationContent();
return false;
});
newTokyoTravelAgency = document.getElementById("newtokyo-travelagency");
let newTokyoTravelAgency = document.getElementById("newtokyo-travelagency");
newTokyoTravelAgency.addEventListener("click", function() {
Player.location = Locations.NewTokyoTravelAgency;
Engine.loadLocationContent();
return false;
});
newTokyoHospital = document.getElementById("newtokyo-hospital");
let newTokyoHospital = document.getElementById("newtokyo-hospital");
newTokyoHospital.addEventListener("click", function() {
Player.location = Locations.Hospital;
Engine.loadLocationContent();
return false;
});
newTokyoDefComm = document.getElementById("newtokyo-defcomm");
let newTokyoDefComm = document.getElementById("newtokyo-defcomm");
newTokyoDefComm.addEventListener("click", function() {
Player.location = Locations.NewTokyoDefComm;
Engine.loadLocationContent();
return false;
});
newTokyoVitaLife = document.getElementById("newtokyo-vitalife");
let newTokyoVitaLife = document.getElementById("newtokyo-vitalife");
newTokyoVitaLife.addEventListener("click", function() {
Player.location = Locations.NewTokyoVitaLife;
Engine.loadLocationContent();
return false;
});
newTokyoGlobalPharmaceuticals = document.getElementById("newtokyo-globalpharmaceuticals");
let newTokyoGlobalPharmaceuticals = document.getElementById("newtokyo-globalpharmaceuticals");
newTokyoGlobalPharmaceuticals.addEventListener("click", function() {
Player.location = Locations.NewTokyoGlobalPharmaceuticals;
Engine.loadLocationContent();
return false;
});
newTokyoNoodleBar = document.getElementById("newtokyo-noodlebar");
let newTokyoNoodleBar = document.getElementById("newtokyo-noodlebar");
newTokyoNoodleBar.addEventListener("click", function() {
Player.location = Locations.NewTokyoNoodleBar;
Engine.loadLocationContent();
return false;
});
newTokyoSlums = document.getElementById("newtokyo-slums");
let newTokyoSlums = document.getElementById("newtokyo-slums");
newTokyoSlums.addEventListener("click", function() {
Player.location = Locations.NewTokyoSlums;
Engine.loadLocationContent();
return false;
});
ishimaTravelAgency = document.getElementById("ishima-travelagency");
let ishimaTravelAgency = document.getElementById("ishima-travelagency");
ishimaTravelAgency.addEventListener("click", function() {
Player.location = Locations.IshimaTravelAgency;
Engine.loadLocationContent();
return false;
});
ishimaHospital = document.getElementById("ishima-hospital");
let ishimaHospital = document.getElementById("ishima-hospital");
ishimaHospital.addEventListener("click", function() {
Player.location = Locations.Hospital;
Engine.loadLocationContent();
return false;
});
ishimaStormTechnologies = document.getElementById("ishima-stormtechnologies");
let ishimaStormTechnologies = document.getElementById("ishima-stormtechnologies");
ishimaStormTechnologies.addEventListener("click", function() {
Player.location = Locations.IshimaStormTechnologies;
Engine.loadLocationContent();
return false;
});
ishimaNovaMedical = document.getElementById("ishima-novamedical");
let ishimaNovaMedical = document.getElementById("ishima-novamedical");
ishimaNovaMedical.addEventListener("click", function() {
Player.location = Locations.IshimaNovaMedical;
Engine.loadLocationContent();
return false;
});
ishimaOmegaSoftware = document.getElementById("ishima-omegasoftware");
let ishimaOmegaSoftware = document.getElementById("ishima-omegasoftware");
ishimaOmegaSoftware.addEventListener("click", function() {
Player.location = Locations.IshimaOmegaSoftware;
Engine.loadLocationContent();
return false;
});
ishimaSlums = document.getElementById("ishima-slums");
let ishimaSlums = document.getElementById("ishima-slums");
ishimaSlums.addEventListener("click", function() {
Player.location = Locations.IshimaSlums;
Engine.loadLocationContent();
return false;
});
volhavenTravelAgency = document.getElementById("volhaven-travelagency");
let volhavenTravelAgency = document.getElementById("volhaven-travelagency");
volhavenTravelAgency.addEventListener("click", function() {
Player.location = Locations.VolhavenTravelAgency;
Engine.loadLocationContent();
return false;
});
volhavenHospital = document.getElementById("volhaven-hospital");
let volhavenHospital = document.getElementById("volhaven-hospital");
volhavenHospital.addEventListener("click", function() {
Player.location = Locations.Hospital;
Engine.loadLocationContent();
return false;
});
volhavenZBInstituteOfTechnology = document.getElementById("volhaven-zbinstituteoftechnology");
let volhavenZBInstituteOfTechnology = document.getElementById("volhaven-zbinstituteoftechnology");
volhavenZBInstituteOfTechnology.addEventListener("click", function() {
Player.location = Locations.VolhavenZBInstituteOfTechnology;
Engine.loadLocationContent();
return false;
});
volhavenOmniTekIncorporated = document.getElementById("volhaven-omnitekincorporated");
let volhavenOmniTekIncorporated = document.getElementById("volhaven-omnitekincorporated");
volhavenOmniTekIncorporated.addEventListener("click", function() {
Player.location = Locations.VolhavenOmniTekIncorporated;
Engine.loadLocationContent();
return false;
});
volhavenNWO = document.getElementById("volhaven-nwo");
let volhavenNWO = document.getElementById("volhaven-nwo");
volhavenNWO.addEventListener("click", function() {
Player.location = Locations.VolhavenNWO;
Engine.loadLocationContent();
return false;
});
volhavenHeliosLabs = document.getElementById("volhaven-helioslabs");
let volhavenHeliosLabs = document.getElementById("volhaven-helioslabs");
volhavenHeliosLabs.addEventListener("click", function() {
Player.location = Locations.VolhavenHeliosLabs;
Engine.loadLocationContent();
return false;
});
volhavenOmniaCybersystems = document.getElementById("volhaven-omniacybersystems");
let volhavenOmniaCybersystems = document.getElementById("volhaven-omniacybersystems");
volhavenOmniaCybersystems.addEventListener("click", function() {
Player.location = Locations.VolhavenOmniaCybersystems;
Engine.loadLocationContent();
return false;
});
volhavenLexoCorp = document.getElementById("volhaven-lexocorp");
let volhavenLexoCorp = document.getElementById("volhaven-lexocorp");
volhavenLexoCorp.addEventListener("click", function() {
Player.location = Locations.VolhavenLexoCorp;
Engine.loadLocationContent();
return false;
});
volhavenSysCoreSecurities = document.getElementById("volhaven-syscoresecurities");
let volhavenSysCoreSecurities = document.getElementById("volhaven-syscoresecurities");
volhavenSysCoreSecurities.addEventListener("click", function() {
Player.location = Locations.VolhavenSysCoreSecurities;
Engine.loadLocationContent();
return false;
});
volhavenCompuTek = document.getElementById("volhaven-computek");
let volhavenCompuTek = document.getElementById("volhaven-computek");
volhavenCompuTek.addEventListener("click", function() {
Player.location = Locations.VolhavenCompuTek;
Engine.loadLocationContent();
return false;
});
volhavenMilleniumFitnessGym = document.getElementById("volhaven-milleniumfitnessgym");
let volhavenMilleniumFitnessGym = document.getElementById("volhaven-milleniumfitnessgym");
volhavenMilleniumFitnessGym.addEventListener("click", function() {
Player.location = Locations.VolhavenMilleniumFitnessGym;
Engine.loadLocationContent();
return false;
});
volhavenSlums = document.getElementById("volhaven-slums");
let volhavenSlums = document.getElementById("volhaven-slums");
volhavenSlums.addEventListener("click", function() {
Player.location = Locations.VolhavenSlums;
Engine.loadLocationContent();
return false;
});
worldStockExchange = document.getElementById("generic-location-wse");
let worldStockExchange = document.getElementById("generic-location-wse");
worldStockExchange.addEventListener("click", function() {
Player.location = Locations.WorldStockExchange;
Engine.loadStockMarketContent();
@ -1811,7 +1839,8 @@ initLocationButtons = function() {
});
}
travelToCity = function(destCityName, cost) {
function travelToCity(destCityName, cost) {
Player.firstTimeTraveled = true;
if (Player.money.lt(cost)) {
dialogBoxCreate("You cannot afford to travel to " + destCityName);
return;
@ -1823,7 +1852,7 @@ travelToCity = function(destCityName, cost) {
Engine.loadWorldContent();
}
purchaseTorRouter = function() {
function purchaseTorRouter() {
if (Player.money.lt(CONSTANTS.TorRouterCost)) {
dialogBoxCreate("You cannot afford to purchase the Tor router");
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.");
}
displayUniversityLocationContent = function(costMult) {
function displayUniversityLocationContent(costMult) {
var studyComputerScienceButton = document.getElementById("location-study-computer-science");
var classDataStructuresButton = document.getElementById("location-data-structures-class");
var classNetworksButton = document.getElementById("location-networks-class");
@ -1870,7 +1899,7 @@ displayUniversityLocationContent = function(costMult) {
classLeadershipButton.innerHTML = "Take Leadership course ($" + leadershipCost + " / sec)";
}
setUniversityLocationButtons = function(costMult, expMult) {
function setUniversityLocationButtons(costMult, expMult) {
var newStudyCS = clearEventListeners("location-study-computer-science");
newStudyCS.addEventListener("click", function() {
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 gymDefButton = document.getElementById("location-gym-train-def");
var gymDexButton = document.getElementById("location-gym-train-dex");
@ -1928,7 +1957,7 @@ displayGymLocationContent = function(costMult) {
gymAgiButton.innerHTML = "Train Agility ($" + cost + " / sec)";
}
setGymLocationButtons = function(costMult, expMult) {
function setGymLocationButtons(costMult, expMult) {
var gymStr = clearEventListeners("location-gym-train-str");
gymStr.addEventListener("click", function() {
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.addEventListener("click", function() {
Engine.loadInfiltrationContent();
@ -2008,3 +2037,5 @@ function purchaseServerBoxCreate(ram, cost) {
"GB of RAM for $" + formatNumber(cost, 2) + "?<br><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 */
function Message(filename="", msg="") {
this.filename = filename;
@ -56,6 +66,11 @@ function checkForMessagesToSend() {
var bitrunnersTest = Messages[MessageFilenames.BitRunnersTest];
var redpill = Messages[MessageFilenames.RedPill];
var redpillOwned = false;
if (Augmentations[AugmentationNames.TheRedPill].owned) {
redpillOwned = true;
}
if (jumper0 && !jumper0.recvd && Player.hacking_skill >= 25) {
sendMessage(jumper0);
} else if (jumper1 && !jumper1.recvd && Player.hacking_skill >= 40) {
@ -75,7 +90,7 @@ function checkForMessagesToSend() {
} else if (jumper5 && !jumper5.recvd && Player.hacking_skill >= 1000) {
sendMessage(jumper5);
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);
}
}
@ -84,9 +99,13 @@ function AddToAllMessages(msg) {
Messages[msg.filename] = msg;
}
Messages = {}
let Messages = {}
MessageFilenames = {
function loadMessages(saveString) {
Messages = JSON.parse(saveString, Reviver);
}
let MessageFilenames = {
Jumper0: "j0.msg",
Jumper1: "j1.msg",
Jumper2: "j2.msg",
@ -160,3 +179,6 @@ function initMessages() {
"@_#(%_@#M(BDSPOMB__THE-CAVE_#)$(*@#$)@#BNBEGB<br>" +
"DFLSMFVMV)#@($*)@#*$MV)@#(*$V)M#(*$)M@(#*VM$)"));
}
export {Messages, checkForMessagesToSend, sendMessage, showMessage, loadMessages,
initMessages, Message};

@ -1,5 +1,6 @@
import {NetscriptFunctions} from "./NetscriptFunctions.js";
/* Environment
* NetScript program environment
* NetScript program environment
*/
function Environment(workerScript,parent) {
if (parent){
@ -16,7 +17,7 @@ Environment.prototype = {
extend: function() {
return new Environment(this);
},
//Finds the scope where the variable with the given name is defined
lookup: function(name) {
var scope = this;
@ -26,7 +27,7 @@ Environment.prototype = {
scope = scope.parent;
}
},
//Get the current value of a variable
get: function(name) {
if (name in this.vars) {
@ -34,7 +35,7 @@ Environment.prototype = {
}
throw new Error("Undefined variable " + name);
},
//Sets the value of a variable in any scope
set: function(name, value) {
var scope = this.lookup(name);
@ -48,7 +49,7 @@ Environment.prototype = {
}
return (scope || this).vars[name] = value;
},
setArrayElement: function(name, idx, value) {
var scope = this.lookup(name);
if (!scope && this.parent) {
@ -61,9 +62,11 @@ Environment.prototype = {
}
return (scope || this).vars[name][idx] = value;
},
//Creates (or overwrites) a variable in the current scope
def: function(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
* Evaluates the Abstract Syntax Tree for Netscript
* generated by the Parser class
@ -20,7 +34,7 @@ function evaluate(exp, workerScript) {
evaluateProgPromise.then(function(w) {
resolve(workerScript);
}, function(e) {
if (typeof e === 'string' || e instanceof String) {
if (isString(e)) {
workerScript.errorMessage = e;
reject(workerScript);
} else if (e instanceof WorkerScript) {
@ -35,7 +49,7 @@ function evaluate(exp, workerScript) {
break;
case "Identifier":
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))
break;
@ -172,7 +186,7 @@ function evaluate(exp, workerScript) {
}
resolve(env.get(exp.argument.name))
} else {
reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.argument.name + " not definied"));
reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.argument.name + " not defined"));
}
} else {
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)){
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);
@ -347,7 +361,7 @@ function evalAssignment(exp, workerScript) {
//Index designated by exp.left.property
var name = exp.left.object.name;
if (!(name in env.vars)){
reject(makeRuntimeRejectMsg(workerScript, "variable " + name + " not definied"));
reject(makeRuntimeRejectMsg(workerScript, "variable " + name + " not defined"));
}
var arr = env.get(name);
if (arr.constructor === Array || arr instanceof Array) {
@ -631,7 +645,8 @@ function runScriptFromScript(server, scriptname, args, workerScript, threads=1)
}
function isScriptErrorMessage(msg) {
splitMsg = msg.split("|");
if (!isString(msg)) {return false;}
let splitMsg = msg.split("|");
if (splitMsg.length != 4){
return false;
}
@ -666,7 +681,7 @@ function scriptCalculateExpGain(server) {
if (server.baseDifficulty == null) {
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
@ -676,7 +691,7 @@ function scriptCalculatePercentMoneyHacked(server) {
var percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / 240;
if (percentMoneyHacked < 0) {return 0;}
if (percentMoneyHacked > 1) {return 1;}
return percentMoneyHacked;
return percentMoneyHacked * BitNodeMultipliers.ScriptHackMoney;
}
//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
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) {
return {
hacknetnodes : Player.hacknetNodes,
@ -172,6 +224,12 @@ function NetscriptFunctions(workerScript) {
}
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() {
workerScript.scriptRef.clearLog();
},
@ -208,6 +266,7 @@ function NetscriptFunctions(workerScript) {
throw makeRuntimeRejectMsg(workerScript, "Cannot call brutessh(). Invalid IP or hostname passed in: " + ip);
}
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!");
}
if (!server.sshPortOpen) {
@ -864,7 +923,784 @@ function NetscriptFunctions(workerScript) {
throw makeRuntimeRejectMsg(workerScript, "getWeakenTime() failed. Invalid IP or hostname passed in: " + ip);
}
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) {
this.name = runningScriptObj.filename;
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
var workerScripts = [];
let workerScripts = [];
var NetscriptPorts = {
let NetscriptPorts = {
Port1: [],
Port2: [],
Port3: [],
@ -38,6 +48,14 @@ var NetscriptPorts = {
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
function runScriptsLoop() {
//Run any scripts that haven't been started
@ -45,7 +63,7 @@ function runScriptsLoop() {
//If it isn't running, start the script
if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) {
try {
var ast = acorn.parse(workerScripts[i].code);
var ast = parse(workerScripts[i].code);
//console.log(ast);
} catch (e) {
console.log("Error parsing script: " + workerScripts[i].name);
@ -64,9 +82,10 @@ function runScriptsLoop() {
w.env.stopFlag = true;
w.scriptRef.log("Script finished running");
}, function(w) {
//console.log(w);
if (w instanceof Error) {
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;
} else if (w instanceof WorkerScript) {
if (isScriptErrorMessage(w.errorMessage)) {
@ -92,7 +111,7 @@ function runScriptsLoop() {
} else if (isScriptErrorMessage(w)) {
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;
} else {
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
function prestigeAugmentation() {
initBitNodeMultipliers();
//Crime statistics
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();
Player.prestigeAugmentation();
//Delete all Worker Scripts objects
for (var i = 0; i < workerScripts.length; ++i) {
deleteActiveScriptsItem(workerScripts[i]);
workerScripts[i].env.stopFlag = true;
}
workerScripts.length = 0;
prestigeWorkerScripts();
var homeComp = Player.getHomeComputer();
//Delete all servers except home computer
for (var member in AllServers) {
delete AllServers[member];
}
AllServers = {};
prestigeAllServers();
//Delete Special Server IPs
for (var member in SpecialServerIps) {
delete SpecialServerIps[member];
}
SpecialServersIps = null;
prestigeSpecialServerIps(); //Must be done before initForeignServers()
//Reset home computer (only the programs) and add to AllServers
homeComp.programs.length = 0;
homeComp.runningScripts = [];
homeComp.serversOnNetwork = [];
homeComp.isConnectedTo = true;
homeComp.ramUsed = 0;
homeComp.programs.push(Programs.NukeProgram);
prestigeHomeComputer(homeComp);
if (augmentationExists(AugmentationNames.Neurolink) &&
Augmentations[AugmentationNames.Neurolink].owned) {
homeComp.programs.push(Programs.FTPCrackProgram);
@ -115,31 +51,18 @@ function prestigeAugmentation() {
}
if (augmentationExists(AugmentationNames.CashRoot) &&
Augmentations[AugmentationNames.CashRoot].owned) {
Player.money = new Decimal(1000000);
Player.setMoney(new Decimal(1000000));
homeComp.programs.push(Programs.BruteSSHProgram);
}
Player.currentServer = homeComp.ip;
Player.homeComputer = homeComp.ip;
AddToAllServers(homeComp);
//Re-create foreign servers
SpecialServerIps = new SpecialServerIpsMap(); //Must be done before initForeignServers()
initForeignServers();
//Darkweb is purchase-able
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
for (var member in Companies) {
if (Companies.hasOwnProperty(member)) {
@ -177,7 +100,7 @@ function prestigeAugmentation() {
if (Player.hasWseAccount) {
initStockMarket();
initSymbolToStockMap();
stockMarketContentCreated = false;
setStockMarketContentCreated(false);
var stockMarketList = document.getElementById("stock-market-list");
while(stockMarketList.firstChild) {
stockMarketList.removeChild(stockMarketList.firstChild);
@ -192,8 +115,6 @@ function prestigeAugmentation() {
}
}
Player.playtimeSinceLastAug = 0;
var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible";
Engine.loadTerminalContent();
@ -216,110 +137,22 @@ function prestigeSourceFile() {
initBitNodeMultipliers();
//Crime statistics
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.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();
Player.prestigeSourceFile();
//Delete all Worker Scripts objects
for (var i = 0; i < workerScripts.length; ++i) {
deleteActiveScriptsItem(workerScripts[i]);
workerScripts[i].env.stopFlag = true;
}
workerScripts.length = 0;
prestigeWorkerScripts();
var homeComp = Player.getHomeComputer();
//Delete all servers except home computer
for (var member in AllServers) {
delete AllServers[member];
}
AllServers = {};
prestigeAllServers(); //Must be done before initForeignServers()
//Delete Special Server IPs
for (var member in SpecialServerIps) {
delete SpecialServerIps[member];
}
SpecialServersIps = null;
prestigeSpecialServerIps();
//Reset home computer (only the programs) and add to AllServers
homeComp.programs.length = 0;
homeComp.runningScripts = [];
homeComp.serversOnNetwork = [];
homeComp.isConnectedTo = true;
homeComp.ramUsed = 0;
homeComp.programs.push(Programs.NukeProgram);
prestigeHomeComputer(homeComp);
var srcFile1Owned = false;
for (var i = 0; i < Player.sourceFiles.length; ++i) {
if (Player.sourceFiles[i].n == 1) {
@ -327,32 +160,19 @@ function prestigeSourceFile() {
}
}
if (srcFile1Owned) {
homeComp.maxRam = 32;
homeComp.setMaxRam(32);
} else {
homeComp.maxRam = 8;
homeComp.setMaxRam(8);
}
Player.currentServer = homeComp.ip;
Player.homeComputer = homeComp.ip;
AddToAllServers(homeComp);
//Re-create foreign servers
SpecialServerIps = new SpecialServerIpsMap(); //Must be done before initForeignServers()
initForeignServers();
//Darkweb is purchase-able
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
for (var member in Companies) {
if (Companies.hasOwnProperty(member)) {
@ -393,16 +213,9 @@ function prestigeSourceFile() {
//Messages
initMessages();
//Gang
Player.gang = null;
//Reset Stock market
Player.hasWseAccount = false;
Player.hasTixApiAccess = false;
Player.playtimeSinceLastAug = 0;
var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible";
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
* 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) {
redPillFlag = true;
Engine.loadRedPillContent();
@ -193,7 +206,7 @@ function loadBitVerse(destroyedBitNodeNum) {
var elemId = "bitnode-" + i.toString();
var elem = clearEventListeners(elemId);
if (elem == null) {return;}
if (i == 1 || i == 2) {
if (i === 1 || i === 2 || i === 4 || i === 11) {
elem.addEventListener("click", function() {
var bitNodeKey = "BitNode" + i;
var bitNode = BitNodes[bitNodeKey];
@ -282,6 +295,7 @@ function createBitNodeYesNoEventListeners(newBitNode, destroyedBitNode) {
//Set new Bit Node
Player.bitNodeN = newBitNode;
console.log("Entering Bit Node " + Player.bitNodeN);
//Reenable terminal
$("#hack-progress-bar").attr('id', "old-hack-progress-bar");
@ -293,7 +307,6 @@ function createBitNodeYesNoEventListeners(newBitNode, destroyedBitNode) {
prestigeSourceFile();
yesNoBoxClose();
//TODO Dialog box for going ot new Bit node
});
var noBtn = yesNoBoxGetNoButton();
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
* Defines the object used to save/load games
*/
var saveObject = new BitburnerSaveObject();
let saveObject = new BitburnerSaveObject();
function BitburnerSaveObject() {
this.PlayerSave = "";
@ -53,7 +79,7 @@ BitburnerSaveObject.prototype.saveGame = function() {
Engine.createStatusText("Game saved!");
}
loadGame = function(saveObj) {
function loadGame(saveObj) {
if (!window.localStorage.getItem("bitburnerSave")) {
console.log("No save file to load");
return false;
@ -61,39 +87,33 @@ loadGame = function(saveObj) {
var saveString = decodeURIComponent(escape(atob(window.localStorage.getItem("bitburnerSave"))));
saveObj = JSON.parse(saveString, Reviver);
Player = JSON.parse(saveObj.PlayerSave, Reviver);
//Parse Decimal.js objects
Player.money = new Decimal(Player.money);
Player.total_money = new Decimal(Player.total_money);
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);
loadPlayer(saveObj.PlayerSave);
loadAllServers(saveObj.AllServersSave);
loadCompanies(saveObj.CompaniesSave);
loadFactions(saveObj.FactionsSave);
loadSpecialServerIps(saveObj.SpecialServerIpsSave);
if (saveObj.hasOwnProperty("AliasesSave")) {
try {
Aliases = JSON.parse(saveObj.AliasesSave, Reviver);
loadAliases(saveObj.AliasesSave);
} catch(e) {
Aliases = {};
loadAliases("");
}
} else {
Aliases = {};
loadAliases("");
}
if (saveObj.hasOwnProperty("GlobalAliasesSave")) {
try {
GlobalAliases = JSON.parse(saveObj.GlobalAliasesSave, Reviver);
loadGlobalAliases(saveObj.GlobalAliasesSave);
} catch(e) {
GlobalAliases = {};
loadGlobalAliases("");
}
} else {
GlobalAliases = {};
loadGlobalAliases("");
}
if (saveObj.hasOwnProperty("MessagesSave")) {
try {
Messages = JSON.parse(saveObj.MessagesSave, Reviver);
loadMessages(saveObj.MessagesSave);
} catch(e) {
initMessages();
}
@ -102,17 +122,18 @@ loadGame = function(saveObj) {
}
if (saveObj.hasOwnProperty("StockMarketSave")) {
try {
StockMarket = JSON.parse(saveObj.StockMarketSave, Reviver);
loadStockMarket(saveObj.StockMarketSave);
} catch(e) {
StockMarket = {};
loadStockMarket("");
}
} else {
StockMarket = {};
loadStockMarket("");
}
if (saveObj.hasOwnProperty("SettingsSave")) {
try {
Settings = JSON.parse(saveObj.SettingsSave, Reviver);
loadSettings(saveObj.SettingsSave);
} catch(e) {
console.log("ERROR: Failed to parse Settings. Re-initing default values");
initSettings();
}
} else {
@ -121,13 +142,30 @@ loadGame = function(saveObj) {
if (saveObj.hasOwnProperty("VersionSave")) {
try {
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");
if (Player.bitNodeN == null || Player.bitNodeN == 0) {
Player.bitNodeN = 1;
}
if (Player.sourceFiles == null) {
Player.sourceFiles = [];
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) {
@ -141,7 +179,7 @@ loadGame = function(saveObj) {
}
if (Player.bitNodeN == 2 && Player.inGang() && saveObj.hasOwnProperty("AllGangsSave")) {
try {
AllGangs = JSON.parse(saveObj.AllGangsSave, Reviver);
loadAllGangs(saveObj.AllGangsSave);
} catch(e) {
console.log("ERROR: Failed to parse AllGangsSave: " + e);
}
@ -150,24 +188,26 @@ loadGame = function(saveObj) {
return true;
}
loadImportedGame = function(saveObj, saveString) {
function loadImportedGame(saveObj, saveString) {
var tempSaveObj = null;
var tempPlayer = null;
var tempAllServers = null;
var tempCompanies = null;
var tempFactions = null;
var tempSpecialServerIps = null;
var tempAugmentations = null;
var tempAliases = null;
var tempGlobalAliases = null;
var tempMessages = 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
tempPlayer.money = new Decimal(tempPlayer.money);
@ -178,11 +218,11 @@ loadImportedGame = function(saveObj, saveString) {
tempCompanies = JSON.parse(tempSaveObj.CompaniesSave, Reviver);
tempFactions = JSON.parse(tempSaveObj.FactionsSave, Reviver);
tempSpecialServerIps = JSON.parse(tempSaveObj.SpecialServerIpsSave, Reviver);
tempAugmentations = JSON.parse(tempSaveObj.AugmentationsSave, Reviver);
if (tempSaveObj.hasOwnProperty("AliasesSave")) {
try {
tempAliases = JSON.parse(tempSaveObj.AliasesSave, Reviver);
} catch(e) {
console.log("Parsing Aliases save failed: " + e);
tempAliases = {};
}
} else {
@ -192,6 +232,7 @@ loadImportedGame = function(saveObj, saveString) {
try {
tempGlobalAliases = JSON.parse(tempSaveObj.AliasesSave, Reviver);
} catch(e) {
console.log("Parsing Global Aliases save failed: " + e);
tempGlobalAliases = {};
}
} else {
@ -201,6 +242,7 @@ loadImportedGame = function(saveObj, saveString) {
try {
tempMessages = JSON.parse(tempSaveObj.MessagesSave, Reviver);
} catch(e) {
console.log("Parsing Messages save failed: " + e);
initMessages();
}
} else {
@ -210,6 +252,7 @@ loadImportedGame = function(saveObj, saveString) {
try {
tempStockMarket = JSON.parse(saveObj.StockMarketSave, Reviver);
} catch(e) {
console.log("Parsing StockMarket save failed: " + e);
tempStockMarket = {};
}
} else {
@ -218,7 +261,7 @@ loadImportedGame = function(saveObj, saveString) {
if (tempSaveObj.hasOwnProperty("VersionSave")) {
try {
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) {
tempPlayer.bitNodeN = 1;
}
@ -227,13 +270,14 @@ loadImportedGame = function(saveObj, saveString) {
}
}
if (ver != CONSTANTS.Version) {
createNewUpdateText();
//createNewUpdateText();
}
} catch(e) {
createNewUpdateText();
console.log("Parsing Version save failed: " + e);
//createNewUpdateText();
}
} else {
createNewUpdateText();
//createNewUpdateText();
}
if (tempPlayer.bitNodeN == 2 && tempPlayer.inGang() && saveObj.hasOwnProperty("AllGangsSave")) {
try {
@ -243,31 +287,110 @@ loadImportedGame = function(saveObj, saveString) {
}
}
} catch(e) {
dialogBoxCreate("Error importing game");
dialogBoxCreate("Error importing game: " + e.toString());
return false;
}
saveObj = tempSaveObj;
Player = tempPlayer;
AllServers = tempAllServers;
Companies = tempCompanies;
Factions = tempFactions;
SpecialServerIps = tempSpecialServerIps;
Augmentations = tempAugmentations;
if (tempAliases) {
Aliases = tempAliases;
}
//Since the save file is valid, load everything for real
saveString = decodeURIComponent(escape(atob(saveString)));
saveObj = JSON.parse(saveString, Reviver);
if (tempGlobalAliases) {
GlobalAliases = tempGlobalAliases;
}
loadPlayer(saveObj.PlayerSave);
loadAllServers(saveObj.AllServersSave);
loadCompanies(saveObj.CompaniesSave);
loadFactions(saveObj.FactionsSave);
loadSpecialServerIps(saveObj.SpecialServerIpsSave);
if (tempMessages) {
Messages = tempMessages;
if (saveObj.hasOwnProperty("AliasesSave")) {
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 " +
@ -337,7 +460,6 @@ BitburnerSaveObject.prototype.exportGame = function() {
this.CompaniesSave = JSON.stringify(Companies);
this.FactionsSave = JSON.stringify(Factions);
this.SpecialServerIpsSave = JSON.stringify(SpecialServerIps);
this.AugmentationsSave = JSON.stringify(Augmentations);
this.AliasesSave = JSON.stringify(Aliases);
this.GlobalAliasesSave = JSON.stringify(GlobalAliases);
this.MessagesSave = JSON.stringify(Messages);
@ -380,7 +502,7 @@ BitburnerSaveObject.prototype.deleteGame = function() {
Engine.createStatusText("Game deleted!");
}
createNewUpdateText = function() {
function createNewUpdateText() {
dialogBoxCreate("New update!<br>" +
"Please report any bugs/issues through the github repository " +
"or the Bitburner subreddit (reddit.com/r/bitburner).<br><br>" +
@ -414,3 +536,5 @@ function openImportFileHandler(evt) {
};
reader.readAsText(file);
}
export {saveObject, loadGame};

@ -1,6 +1,22 @@
/* Script.js
* Script object
*/
var ace = require('brace');
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() {
//Initialize save and close button
@ -22,7 +38,7 @@ function scriptEditorInit() {
var end = this.selectionEnd;
//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);
//Put caret at after the four spaces
@ -34,15 +50,13 @@ function scriptEditorInit() {
document.addEventListener("DOMContentLoaded", scriptEditorInit, false);
//Updates line number and RAM usage in script
function upgradeScriptEditorContent() {
var txt = $("#script-editor-text")[0];
var lineNum = txt.value.substr(0, txt.selectionStart).split("\n").length;
var code = document.getElementById("script-editor-text").value;
function updateScriptEditorContent() {
var editor = ace.edit('javascript-editor');
var code = editor.getValue();
var codeCopy = code.repeat(1);
var ramUsage = calculateRamUsage(codeCopy);
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.)
@ -63,7 +77,8 @@ function saveAndCloseScriptEditor() {
dialogBoxCreate("Leave the script name as 'foodnstuff'!");
return;
}
var code = document.getElementById("script-editor-text").value;
var editor = ace.edit('javascript-editor');
var code = editor.getValue();
code = code.replace(/\s/g, "");
if (code.indexOf("while(true){hack('foodnstuff');}") == -1) {
dialogBoxCreate("Please copy and paste the code from the tutorial!");
@ -122,7 +137,8 @@ function Script() {
Script.prototype.saveScript = function() {
if (Engine.currentPage == Engine.Page.ScriptEditor) {
//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, '');
var filename = document.getElementById("script-editor-filename").value + ".script";
@ -200,6 +216,30 @@ function calculateRamUsage(codeCopy) {
var getHackTimeCount = numOccurrences(codeCopy, "getHackTime(") +
numOccurrences(codeCopy, "getGrowTime(") +
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 +
((whileCount * CONSTANTS.ScriptWhileRamCost) +
@ -238,8 +278,11 @@ function calculateRamUsage(codeCopy) {
(scriptWriteCount * CONSTANTS.ScriptReadWriteRamCost) +
(scriptReadCount * CONSTANTS.ScriptReadWriteRamCost) +
(arbScriptCount * CONSTANTS.ScriptArbScriptRamCost) +
(getScriptCount * CONSTANTS.ScriptGetScriptCost) +
(getHackTimeCount * CONSTANTS.ScriptGetHackTimeCost));
(getScriptCount * CONSTANTS.ScriptGetScriptRamCost) +
(getHackTimeCount * CONSTANTS.ScriptGetHackTimeRamCost) +
(singFn1Count * CONSTANTS.ScriptSingularityFn1RamCost) +
(singFn2Count * CONSTANTS.ScriptSingularityFn2RamCost) +
(singFn3Count * CONSTANTS.ScriptSingularityFn3RamCost));
}
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)
//into worker scripts so that they will start running
loadAllRunningScripts = function() {
function loadAllRunningScripts() {
var count = 0;
var total = 0;
for (var property in AllServers) {
@ -278,7 +321,7 @@ loadAllRunningScripts = function() {
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
var thisUpdate = new Date().getTime();
var lastUpdate = Player.lastUpdate;
@ -473,6 +516,8 @@ RunningScript.fromJSON = function(value) {
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
//a key. Initializes every key with a specified value that can either by a number or an array
function AllServersMap(arr=false) {
@ -517,3 +562,6 @@ AllServersMap.fromJSON = function(value) {
}
Reviver.constructors.AllServersMap = AllServersMap;
export {updateScriptEditorContent, loadAllRunningScripts, findRunningScript,
RunningScript, Script, AllServersMap};

@ -1,6 +1,14 @@
//Netburner Server class
//TODO Make a map of all IPS in the game so far so that we don't accidentally
// get duplicate IPs..however unlikely it is
import {BitNodeMultipliers} from "./BitNode.js";
import {CONSTANTS} from "./Constants.js";
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="",
isConnectedTo=false, adminRights=false, purchasedByPlayer=false, maxRam=0) {
/* Properties */
@ -67,9 +75,9 @@ Server.prototype.setHackingParameters = function(requiredHackingSkill, moneyAvai
if (isNaN(moneyAvailable)) {
this.moneyAvailable = 1000000;
} 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.baseDifficulty = hackDifficulty;
this.minDifficulty = Math.max(1, Math.round(hackDifficulty / 3));
@ -82,6 +90,10 @@ Server.prototype.setPortProperties = function(numOpenPortsReq) {
this.numOpenPortsRequired = numOpenPortsReq;
}
Server.prototype.setMaxRam = function(ram) {
this.maxRam = ram;
}
//The serverOnNetwork array holds the IP of all the servers. This function
//returns the actual Server objects
Server.prototype.getServerOnNetwork = function(i) {
@ -110,7 +122,7 @@ Server.prototype.fortify = 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 < 1) {this.hackDifficulty = 1;}
}
@ -126,7 +138,7 @@ Server.fromJSON = function(value) {
Reviver.constructors.Server = Server;
initForeignServers = function() {
function initForeignServers() {
//MegaCorporations
var ECorpServer = new Server(createRandomIp(), "ecorp", "ECorp", false, false, false, 0);
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
processSingleServerGrowth = function(server, numCycles) {
function processSingleServerGrowth(server, numCycles) {
//Server growth processed once every 450 game cycles
var numServerGrowthCycles = Math.max(Math.floor(numCycles / 450), 0);
@ -645,11 +657,10 @@ processSingleServerGrowth = function(server, numCycles) {
var growthRate = CONSTANTS.ServerBaseGrowthRate;
var adjGrowthRate = 1 + (growthRate - 1) / server.hackDifficulty;
if (adjGrowthRate > CONSTANTS.ServerMaxGrowthRate) {adjGrowthRate = CONSTANTS.ServerMaxGrowthRate;}
//console.log("Adjusted growth rate: " + adjGrowthRate);
//Calculate adjusted server growth rate based on parameters
var serverGrowthPercentage = server.serverGrowth / 100;
var numServerGrowthCyclesAdjusted = numServerGrowthCycles * serverGrowthPercentage;
var numServerGrowthCyclesAdjusted = numServerGrowthCycles * serverGrowthPercentage * BitNodeMultipliers.ServerGrowthRate;
//Apply serverGrowth for the calculated number of growth cycles
var serverGrowth = Math.pow(adjGrowthRate, numServerGrowthCyclesAdjusted * Player.hacking_grow_mult);
@ -666,14 +677,38 @@ processSingleServerGrowth = function(server, numCycles) {
server.moneyAvailable = server.moneyMax;
return 1;
}
//Growing increases server security twice as much as hacking
server.fortify(2 * CONSTANTS.ServerFortifyAmount * numServerGrowthCycles);
return serverGrowth;
}
//List of all servers that exist in the game, indexed by their ip
AllServers = {};
function prestigeHomeComputer(homeComp) {
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;
for (key in AllServers) {
if (AllServers.hasOwnProperty(key)) size++;
@ -682,7 +717,7 @@ SizeOfAllServers = function() {
}
//Add a server onto the map of all servers in the game
AddToAllServers = function(server) {
function AddToAllServers(server) {
var serverIp = server.ip;
if (ipExists(serverIp)) {
console.log("IP of server that's being added: " + serverIp);
@ -696,7 +731,7 @@ AddToAllServers = function(server) {
//Returns server object with corresponding hostname
// Relatively slow, would rather not use this a lot
GetServerByHostname = function(hostname) {
function GetServerByHostname(hostname) {
for (var ip in AllServers) {
if (AllServers.hasOwnProperty(ip)) {
if (AllServers[ip].hostname == hostname) {
@ -708,7 +743,7 @@ GetServerByHostname = function(hostname) {
}
//Get server by IP or hostname. Returns null if invalid
getServer = function(s) {
function getServer(s) {
if (!isValidIPAddress(s)) {
return GetServerByHostname(s);
} else {
@ -717,10 +752,14 @@ getServer = function(s) {
}
//Debugging tool
PrintAllServers = function() {
function PrintAllServers() {
for (var ip in AllServers) {
if (AllServers.hasOwnProperty(ip)) {
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:
* Purchasing new servers
* Purchasing more RAM for home computer
*/
purchaseServer = function(ram, cost) {
function purchaseServer(ram, cost) {
//Check if player has enough money
if (Player.money.lt(cost)) {
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)) {
dialogBoxCreate("You do not have enough money to purchase additional RAM for your home computer");
return;
@ -54,3 +60,5 @@ purchaseRamForHomeComputer = function(cost) {
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 = {
let Settings = {
CodeInstructionRunTime: 100,
MaxLogCapacity: 50,
MaxPortCapacity: 50,
@ -7,6 +7,10 @@ Settings = {
SuppressFactionInvites: false,
}
function loadSettings(saveString) {
Settings = JSON.parse(saveString);
}
function initSettings() {
Settings.CodeInstructionRunTime = 100;
Settings.MaxLogCapacity = 50;
@ -16,14 +20,42 @@ function initSettings() {
}
function setSettingsLabels() {
document.getElementById("settingsNSExecTimeRangeValLabel").innerHTML
= Settings.CodeInstructionRunTime + "ms";
document.getElementById("settingsNSLogRangeValLabel").innerHTML
= Settings.MaxLogCapacity;
document.getElementById("settingsNSPortRangeValLabel").innerHTML
= Settings.MaxPortCapacity;
document.getElementById("settingsSuppressMessages").checked
= Settings.SuppressMessages;
document.getElementById("settingsSuppressFactionInvites").checked
= Settings.SuppressFactionInvites;
var nsExecTime = document.getElementById("settingsNSExecTimeRangeValLabel");
var nsLogLimit = document.getElementById("settingsNSLogRangeValLabel");
var nsPortLimit = document.getElementById("settingsNSPortRangeValLabel");
var suppressMsgs = document.getElementById("settingsSuppressMessages");
var suppressFactionInv = document.getElementById("settingsSuppressFactionInvites")
//Initialize values on labels
nsExecTime.innerHTML = Settings.CodeInstructionRunTime + "ms";
nsLogLimit.innerHTML = Settings.MaxLogCapacity;
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
function SourceFile(number, info="") {
var bitnodeKey = "BitNode" + number;
@ -15,27 +17,33 @@ function SourceFile(number, info="") {
this.owned = false;
}
SourceFiles = {
SourceFile1: new SourceFile(1, "This Source-File lets the player start with 32GB of RAM on his/her " +
let SourceFiles = {};
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>" +
"Level 1: 16%<br>" +
"Level 2: 24%<br>" +
"Level 3: 28%"),
SourceFile2: new SourceFile(2, "This Source-File increases the player's crime success rate, crime money, and charisma " +
"Level 3: 28%");
SourceFiles["SourceFile2"] = new SourceFile(2, "This Source-File increases the player's crime success rate, crime money, and charisma " +
"multipliers by:<br><br>" +
"Level 1: 20%<br>" +
"Level 2: 30%<br>" +
"Level 3: 35%"),
SourceFile3: new SourceFile(3),
SourceFile4: new SourceFile(4),
SourceFile5: new SourceFile(5),
SourceFile6: new SourceFile(6),
SourceFile7: new SourceFile(7),
SourceFile8: new SourceFile(8),
SourceFile9: new SourceFile(9),
SourceFile10: new SourceFile(10),
SourceFile11: new SourceFile(11),
SourceFile12: new SourceFile(12),
"Level 3: 35%");
SourceFiles["SourceFile3"] = new SourceFile(3);
SourceFiles["SourceFile4"] = new SourceFile(4, "This Source-File lets you access and use the Singularity Functions in every BitNode. Every " +
"level of this Source-File opens up more of the Singularity Functions you can use.");
SourceFiles["SourceFile5"] = new SourceFile(5);
SourceFiles["SourceFile6"] = new SourceFile(6);
SourceFiles["SourceFile7"] = new SourceFile(7);
SourceFiles["SourceFile8"] = new SourceFile(8);
SourceFiles["SourceFile9"] = new SourceFile(9);
SourceFiles["SourceFile10"] = new SourceFile(10);
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) {
@ -97,6 +105,18 @@ function applySourceFile(srcFile) {
Player.crime_success_mult *= incMult;
Player.charisma_mult *= incMult;
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:
console.log("ERROR: Invalid source file number: " + srcFile.n);
break;
@ -105,18 +125,4 @@ function applySourceFile(srcFile) {
sourceFileObject.owned = true;
}
PlayerObject.prototype.reapplyAllSourceFiles = function() {
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]);
}
}
export {SourceFiles, PlayerOwnedSourceFile, applySourceFile, initSourceFiles};

@ -1,5 +1,8 @@
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js";
/* Holds IP of Special Servers */
SpecialServerNames = {
let SpecialServerNames = {
FulcrumSecretTechnologies: "Fulcrum Secret Technologies Server",
CyberSecServer: "CyberSec Server",
NiteSecServer: "NiteSec Server",
@ -23,6 +26,25 @@ SpecialServerIpsMap.fromJSON = function(value) {
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 */
function Stock(name, symbol, mv, b, otlkMag, initPrice=10000) {
this.symbol = symbol;
@ -11,10 +22,27 @@ function Stock(name, symbol, mv, b, otlkMag, initPrice=10000) {
this.otlkMag = otlkMag;
}
Stock.prototype.toJSON = function() {
return Generic_toJSON("Stock", this);
}
StockMarket = {} //Full name to stock object
StockSymbols = {} //Full name to symbol
SymbolToStockMap = {}; //Symbol to Stock object
Stock.fromJSON = function(value) {
return Generic_fromJSON(Stock, value.data);
}
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() {
//Stocks for companies at which you can work
@ -51,7 +79,6 @@ function initStockSymbols() {
StockSymbols["Sigma Cosmetics"] = "SGC";
StockSymbols["Joes Guns"] = "JGN";
StockSymbols["Catalyst Ventures"] = "CTYS";
StockSymbols["Taiyang Digital"] = "TAI";
StockSymbols["Microdyne Technologies"] = "MDYN";
StockSymbols["Titan Laboratories"] = "TITN";
}
@ -119,10 +146,6 @@ function initStockMarket() {
var universalenergyStk = new Stock(universalenergy, StockSymbols[universalenergy], 0.55, true, 10, getRandomInt(20000, 25000));
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 aerocorpStk = new Stock(aerocorp, StockSymbols[aerocorp], 0.6, true, 6, getRandomInt(10000, 15000));
StockMarket[aerocorp] = aerocorpStk;
@ -191,10 +214,6 @@ function initStockMarket() {
var catalystStk = new Stock(catalyst, StockSymbols[catalyst], 1.25, true, 0, getRandomInt(1000, 1500));
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 microdyneStk = new Stock(microdyne, StockSymbols[microdyne], 0.75, true, 8, getRandomInt(20000, 25000));
StockMarket[microdyne] = microdyneStk;
@ -330,6 +349,10 @@ function updateStockPrices() {
}
}
function setStockMarketContentCreated(b) {
stockMarketContentCreated = b;
}
var stockMarketContentCreated = false;
function displayStockMarketContent() {
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
function updateStockTicker(stock, increase) {
var tickerId = "stock-market-ticker-" + stock.symbol;
stkName = document.getElementById(tickerId + "-name");
stkSym = document.getElementById(tickerId + "-sym");
stkPrice = document.getElementById(tickerId + "-price");
let stkName = document.getElementById(tickerId + "-name");
let stkSym = document.getElementById(tickerId + "-sym");
let stkPrice = document.getElementById(tickerId + "-price");
if (stkName == null || stkSym == null || stkPrice == null) {
console.log("ERROR, couldn't find elements with tickerId " + tickerId);
@ -584,3 +607,9 @@ function updateStockPlayerPosition(stock) {
avgPriceTxt.innerText = "$" + formatNumber(stock.playerAvgPx, 2);
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 */
var post = function(input, replace=true) {
function post(input, replace=true) {
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>');
} 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
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>');
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>');
updateTerminalScroll();
}
@ -28,7 +56,7 @@ function updateTerminalScroll() {
element.scrollTop = element.scrollHeight;
}
var postNetburnerText = function() {
function postNetburnerText() {
post("Bitburner v" + CONSTANTS.Version);
}
@ -134,7 +162,7 @@ $(document).keydown(function(event) {
});
//Keep terminal in focus
terminalCtrlPressed = false;
let terminalCtrlPressed = false;
$(document).ready(function() {
if (Engine.currentPage == Engine.Page.Terminal) {
$('.terminal-input').focus();
@ -346,7 +374,7 @@ function determineAllPossibilitiesForTabCompletion(input, index=0) {
return allPos;
}
var Terminal = {
let Terminal = {
//Flags to determine whether the player is currently running a hack or an analyze
hackFlag: false,
analyzeFlag: false,
@ -1592,5 +1620,6 @@ var Terminal = {
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
* Alt-t - Terminal
* Alt-c - Character
@ -60,7 +122,7 @@ $(document).keydown(function(e) {
}
});
var Engine = {
let Engine = {
version: "",
Debug: true,
@ -125,9 +187,6 @@ var Engine = {
//Character info
characterInfo: null,
//Script editor text
scriptEditorText: null,
},
//Current page status
@ -177,12 +236,13 @@ var Engine = {
loadScriptEditorContent: function(filename = "", code = "") {
Engine.hideAllContent();
Engine.Display.scriptEditorContent.style.visibility = "visible";
var editor = ace.edit('javascript-editor');
if (filename != "") {
document.getElementById("script-editor-filename").value = filename;
document.getElementById("script-editor-text").value = code;
editor.setValue(code);
}
document.getElementById("script-editor-text").focus();
upgradeScriptEditorContent();
editor.focus();
updateScriptEditorContent();
Engine.currentPage = Engine.Page.ScriptEditor;
document.getElementById("create-script-menu-link").classList.add("active");
},
@ -324,7 +384,7 @@ var Engine = {
loadGangContent: function() {
Engine.hideAllContent();
if (document.getElementById("gang-container") || Player.gang) {
if (document.getElementById("gang-container") || Player.inGang()) {
displayGangContent();
Engine.currentPage = Engine.Page.Gang;
} else {
@ -383,7 +443,6 @@ var Engine = {
if (Player.hp == null) {Player.hp = Player.max_hp;}
document.getElementById("character-overview-text").innerHTML =
("Hp: " + Player.hp + " / " + Player.max_hp + "<br>" +
//"Money: $" + formatNumber(Player.money.toNumber(), 2) + "<br>" +
"Money: " + numeral(Player.money.toNumber()).format('($0.000a)') + "<br>" +
"Hack: " + (Player.hacking_skill).toLocaleString() + "<br>" +
"Str: " + (Player.strength).toLocaleString() + "<br>" +
@ -473,7 +532,6 @@ var Engine = {
document.getElementById("world-city-name").innerHTML = Player.city;
var cityDesc = document.getElementById("world-city-desc"); //TODO
switch(Player.city) {
case Locations.Aevum:
Engine.aevumLocationsList.style.display = "inline";
break;
@ -857,6 +915,7 @@ var Engine = {
if (Engine.Counters.checkFactionInvitations <= 0) {
var invitedFactions = Player.checkForFactionInvitations();
if (invitedFactions.length > 0) {
Player.firstFacInvRecvd = true;
var randFaction = invitedFactions[Math.floor(Math.random() * invitedFactions.length)];
inviteToFaction(randFaction);
}
@ -891,7 +950,7 @@ var Engine = {
if (Engine.Counters.updateScriptEditorDisplay <= 0) {
if (Engine.currentPage == Engine.Page.ScriptEditor) {
upgradeScriptEditorContent();
updateScriptEditorContent();
}
Engine.Counters.updateScriptEditorDisplay = 5;
}
@ -960,6 +1019,13 @@ var Engine = {
},
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"
var terminal = document.getElementById("terminal-tab");
var createScript = document.getElementById("create-script-tab");
@ -978,7 +1044,9 @@ var Engine = {
//Load game from save or create new game
if (loadGame(saveObject)) {
console.log("Loaded game from save");
initBitNodes();
initBitNodeMultipliers();
initSourceFiles();
Engine.setDisplayElements(); //Sets variables for important DOM elements
Engine.init(); //Initialize buttons, work, etc.
CompanyPositions.init();
@ -989,6 +1057,7 @@ var Engine = {
initSymbolToStockMap();
}
initLiterature();
initSingularitySFFlags();
//Calculate the number of cycles have elapsed while offline
Engine._lastUpdate = new Date().getTime();
@ -1081,8 +1150,10 @@ var Engine = {
} else {
//No save found, start new game
console.log("Initializing new game");
initBitNodes();
initBitNodeMultipliers();
SpecialServerIps = new SpecialServerIpsMap();
initSourceFiles();
initSpecialServerIps();
Engine.setDisplayElements(); //Sets variables for important DOM elements
Engine.start(); //Run main game loop and Scripts loop
Player.init();
@ -1094,6 +1165,7 @@ var Engine = {
initMessages();
initStockSymbols();
initLiterature();
initSingularitySFFlags();
//Open main menu accordions for new game
//Main menu accordions
@ -1212,9 +1284,6 @@ var Engine = {
//Init Location buttons
initLocationButtons();
//Script editor
Engine.Display.scriptEditorText = document.getElementById("script-editor-text");
//Tutorial buttons
Engine.Clickables.tutorialNetworkingButton = document.getElementById("tutorial-networking-link");
Engine.Clickables.tutorialNetworkingButton.addEventListener("click", function() {
@ -1233,7 +1302,12 @@ var Engine = {
Engine.Clickables.tutorialNetscriptButton = document.getElementById("tutorial-netscript-link");
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");
@ -1269,6 +1343,11 @@ var Engine = {
/* Initialization */
init: function() {
//Import game link
document.getElementById("import-game-link").onclick = function() {
saveObject.importGame();
};
//Main menu accordions
var hackingHdr = document.getElementById("hacking-menu-header");
//hackingHdr.classList.toggle("opened");
@ -1603,9 +1682,9 @@ var Engine = {
cancelButton.addEventListener("click", function() {
if (Player.workType == CONSTANTS.WorkTypeFaction) {
var fac = Factions[Player.currentWorkFactionName];
Player.finishFactionWork(true, fac);
Player.finishFactionWork(true);
} else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) {
Player.finishCreateProgramWork(true, Player.createProgramName);
Player.finishCreateProgramWork(true);
} else if (Player.workType == CONSTANTS.WorkTypeStudyClass) {
Player.finishClass();
} else if (Player.workType == CONSTANTS.WorkTypeCrime) {
@ -1661,3 +1740,5 @@ var Engine = {
window.onload = function() {
Engine.load();
};
export {Engine};

@ -1,5 +1,5 @@
/* Pop up Dialog Box */
dialogBoxes = [];
let dialogBoxes = [];
//Close dialog box when clicking outside
$(document).click(function(event) {
@ -32,31 +32,33 @@ $(document).on('click', '.dialog-box-close-button', function( event ) {
var dialogBoxOpened = false;
dialogBoxCreate = function(txt) {
function dialogBoxCreate(txt) {
var container = document.createElement("div");
container.setAttribute("class", "dialog-box-container");
var content = document.createElement("div");
content.setAttribute("class", "dialog-box-content");
var closeButton = document.createElement("span");
closeButton.setAttribute("class", "dialog-box-close-button");
closeButton.innerHTML = "&times;"
var textE = document.createElement("p");
textE.innerHTML = txt;
content.appendChild(closeButton);
content.appendChild(textE);
container.appendChild(content);
document.body.appendChild(container);
if (dialogBoxes.length >= 1) {
container.style.visibility = "hidden";
}
dialogBoxes.push(container);
setTimeout(function() {
dialogBoxOpened = true;
}, 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 */
factionInvitationBoxClose = function() {
function factionInvitationBoxClose() {
var factionInvitationBox = document.getElementById("faction-invitation-box-container");
factionInvitationBox.style.display = "none";
}
factionInvitationBoxOpen = function() {
function factionInvitationBoxOpen() {
var factionInvitationBox = document.getElementById("faction-invitation-box-container");
factionInvitationBox.style.display = "block";
}
factionInvitationSetText = function(txt) {
function factionInvitationSetText(txt) {
var textBox = document.getElementById("faction-invitation-box-text");
textBox.innerHTML = txt;
}
factionInvitationSetMessage = function(msg) {
function factionInvitationSetMessage(msg) {
var msgBox = document.getElementById("faction-invitation-box-message");
msgBox.innerHTML = msg;
}
//ram argument is in GB
factionInvitationBoxCreate = function(faction) {
function factionInvitationBoxCreate(faction) {
factionInvitationSetText("You have received a faction invitation from " + faction.name);
//TODO Faction invitation message
@ -41,3 +45,5 @@ factionInvitationBoxCreate = function(faction) {
factionInvitationBoxOpen();
}
export {factionInvitationBoxCreate};

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

@ -10,13 +10,13 @@ function sizeOfObject(obj) {
}
//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;
function addOffset(n, percentage) {
if (percentage < 0 || percentage > 100) {return;}
var offset = n * (percentage / 100);
return n + ((Math.random() * (2 * offset)) - offset);
}
@ -41,7 +41,7 @@ function compareArrays(a1, a2) {
if (a1.length != a2.length) {
return false;
}
for (var i = 0; i < a1.length; ++i) {
if (a1[i] != a2[i]) {return false;}
}
@ -56,4 +56,7 @@ function printArray(a) {
function powerOfTwo(n) {
if (isNaN(n)) {return false;}
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*/
//Generate a random IP address
//Will not return an IP address that already exists in the AllServers array
createRandomIp = function() {
function createRandomIp() {
var ip = createRandomByte(99) +'.' +
createRandomByte(9) +'.' +
createRandomByte(9) +'.' +
createRandomByte(9);
//If the Ip already exists, recurse to create a new one
if (ipExists(ip)) {
return createRandomIp();
@ -16,7 +17,7 @@ createRandomIp = function() {
}
//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) {
if (AllServers.hasOwnProperty(property)) {
if (property == ip) {
@ -27,14 +28,16 @@ ipExists = function(ip) {
return false;
}
createRandomByte = function(n=9) {
function createRandomByte(n=9) {
return Math.round(Math.random()*n);
}
isValidIPAddress = function(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))
{
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))
{
return true;
}
}
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 */
infiltrationBoxClose = function() {
function infiltrationBoxClose() {
var box = document.getElementById("infiltration-box-container");
box.style.display = "none";
}
infiltrationBoxOpen = function() {
function infiltrationBoxOpen() {
var box = document.getElementById("infiltration-box-container");
box.style.display = "block";
}
infiltrationSetText = function(txt) {
function infiltrationSetText(txt) {
var textBox = document.getElementById("infiltration-box-text");
textBox.innerHTML = txt;
}
//ram argument is in GB
infiltrationBoxCreate = function(inst) {
function infiltrationBoxCreate(inst) {
var totalValue = 0;
for (var i = 0; i < inst.secretsStolen.length; ++i) {
totalValue += inst.secretsStolen[i];
}
if (totalValue == 0) {
dialogBoxCreate("You successfully escaped the facility but you did not steal " +
"anything of worth when infiltrating.<br><br>" +
"You gained:<br>" +
formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" +
formatNumber(inst.strExpGained, 3) + " str exp<br>" +
formatNumber(inst.defExpGained, 3) + " def exp<br>" +
formatNumber(inst.dexExpGained, 3) + " dex exp<br>" +
formatNumber(inst.agiExpGained, 3) + " agi exp<br>" +
dialogBoxCreate("You successfully escaped the facility but you did not steal " +
"anything of worth when infiltrating.<br><br>" +
"You gained:<br>" +
formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" +
formatNumber(inst.strExpGained, 3) + " str exp<br>" +
formatNumber(inst.defExpGained, 3) + " def exp<br>" +
formatNumber(inst.dexExpGained, 3) + " dex exp<br>" +
formatNumber(inst.agiExpGained, 3) + " agi exp<br>" +
formatNumber(inst.chaExpGained, 3) + " cha exp<br>");
return;
}
var facValue = totalValue * Player.faction_rep_mult * 1.2
var moneyValue = totalValue * CONSTANTS.InfiltrationMoneyValue;
infiltrationSetText("You can sell the classified documents and secrets " +
"you stole from " + inst.companyName + " for $" +
formatNumber(moneyValue, 2) + " on the black market or you can give it " +
"to a faction to gain " + formatNumber(facValue, 3) + " reputation with " +
infiltrationSetText("You can sell the classified documents and secrets " +
"you stole from " + inst.companyName + " for $" +
formatNumber(moneyValue, 2) + " on the black market or you can give it " +
"to a faction to gain " + formatNumber(facValue, 3) + " reputation with " +
"that faction.");
var selector = document.getElementById("infiltration-faction-select");
selector.innerHTML = "";
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>";
}
var sellButton = clearEventListeners("infiltration-box-sell");
setTimeout(function() {
sellButton.addEventListener("click", function() {
Player.gainMoney(moneyValue);
dialogBoxCreate("You sold the classified information you stole from " + inst.companyName +
" for $" + moneyValue + " on the black market!<br><br>" +
"You gained:<br>" +
formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" +
formatNumber(inst.strExpGained, 3) + " str exp<br>" +
formatNumber(inst.defExpGained, 3) + " def exp<br>" +
formatNumber(inst.dexExpGained, 3) + " dex exp<br>" +
formatNumber(inst.agiExpGained, 3) + " agi exp<br>" +
" for $" + moneyValue + " on the black market!<br><br>" +
"You gained:<br>" +
formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" +
formatNumber(inst.strExpGained, 3) + " str exp<br>" +
formatNumber(inst.defExpGained, 3) + " def exp<br>" +
formatNumber(inst.dexExpGained, 3) + " dex exp<br>" +
formatNumber(inst.agiExpGained, 3) + " agi exp<br>" +
formatNumber(inst.chaExpGained, 3) + " cha exp<br>");
infiltrationBoxClose();
return false;
});
}, 750);
var factionButton = clearEventListeners("infiltration-box-faction");
setTimeout(function() {
factionButton.addEventListener("click", function() {
@ -74,18 +81,20 @@ infiltrationBoxCreate = function(inst) {
return false;
}
faction.playerReputation += facValue;
dialogBoxCreate("You gave the classified information you stole from " + inst.companyName +
" to " + facName + " and gained " + formatNumber(facValue, 3) + " reputation with the faction. <br><br>" +
"You gained:<br>" +
formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" +
formatNumber(inst.strExpGained, 3) + " str exp<br>" +
formatNumber(inst.defExpGained, 3) + " def exp<br>" +
formatNumber(inst.dexExpGained, 3) + " dex exp<br>" +
formatNumber(inst.agiExpGained, 3) + " agi exp<br>" +
dialogBoxCreate("You gave the classified information you stole from " + inst.companyName +
" to " + facName + " and gained " + formatNumber(facValue, 3) + " reputation with the faction. <br><br>" +
"You gained:<br>" +
formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" +
formatNumber(inst.strExpGained, 3) + " str exp<br>" +
formatNumber(inst.defExpGained, 3) + " def exp<br>" +
formatNumber(inst.dexExpGained, 3) + " dex exp<br>" +
formatNumber(inst.agiExpGained, 3) + " agi exp<br>" +
formatNumber(inst.chaExpGained, 3) + " cha exp<br>");
infiltrationBoxClose();
return false;
});
}, 750);
infiltrationBoxOpen();
}
}
export {infiltrationBoxCreate};

@ -17,13 +17,13 @@ function Reviver(key, value) {
ctor = Reviver.constructors[value.ctor] || window[value.ctor];
if (typeof ctor === "function" &&
typeof ctor.fromJSON === "function") {
return ctor.fromJSON(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
// by Reviver.
@ -67,3 +67,5 @@ function Generic_fromJSON(ctor, data) {
}
return obj;
}
export {Reviver, Generic_toJSON, Generic_fromJSON};

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

@ -1,3 +1,5 @@
import {dialogBoxCreate} from "./DialogBox.js";
//Netburner String helper functions
//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) {
//Convert ms to seconds, since we only have second-level precision
time = Math.floor(time / 1000);
var days = Math.floor(time / 86400);
time %= 86400;
var hours = Math.floor(time / 3600);
time %= 3600;
var minutes = Math.floor(time / 60);
time %= 60;
var seconds = time;
var res = "";
if (days) {res += days + " days ";}
if (hours) {res += hours + " hours ";}
@ -55,8 +57,8 @@ function convertTimeMsToTimeElapsedString(time) {
function longestCommonStart(strings) {
if (!containsAllStrings(strings)) {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;
while(i<L && a1.charAt(i)=== a2.charAt(i)) i++;
return a1.substring(0, i);
@ -126,3 +128,7 @@ function numNetscriptOperators(string) {
}
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
* 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");
}
}
export {yesNoBoxCreate, yesNoTxtInpBoxCreate,
yesNoBoxGetYesButton, yesNoBoxGetNoButton,
yesNoTxtInpBoxGetYesButton, yesNoTxtInpBoxGetNoButton,
yesNoTxtInpBoxGetInput, yesNoBoxClose,
yesNoTxtInpBoxClose, yesNoBoxOpen};