Convert Locations and Faction implementations to TypeScript. Also restructed directory. Implemented Sleeve, but untested

This commit is contained in:
danielyxie 2018-12-07 02:54:26 -08:00
parent 8fcb1706cc
commit 48c694c9c1
29 changed files with 171104 additions and 487 deletions

58892
dist/engine.bundle.js vendored

File diff suppressed because one or more lines are too long

111064
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Bitburner</title> <title>Bitburner - development</title>
<link rel="apple-touch-icon" sizes="180x180" href="dist/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="dist/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="dist/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="32x32" href="dist/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png"> <link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png">
@ -112,7 +112,7 @@
<div id="script-editor-filename-wrapper"> <div id="script-editor-filename-wrapper">
<p id="script-editor-filename-tag"> <strong style="background-color:#555;">Script name: </strong></p> <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 id="script-editor-filename" type="text" maxlength="30" tabindex="1" />
</div> </div>
<div id="javascript-editor"></div> <div id="javascript-editor"></div>
@ -162,7 +162,7 @@
<fieldset> <fieldset>
<label for="script-editor-option-maxerr" class="tooltip">Max Error Count</label> <label for="script-editor-option-maxerr" class="tooltip">Max Error Count</label>
<input type="range" max="1000" min="50" value="200" step="1" name="script-editor-option-maxerr" id="script-editor-option-maxerr"/> <input type="range" max="1000" min="50" value="200" step="1" name="script-editor-option-maxerr" id="script-editor-option-maxerr" />
<em id="script-editor-option-maxerror-value-label" style="font-style: normal;"></em> <em id="script-editor-option-maxerror-value-label" style="font-style: normal;"></em>
</fieldset> </fieldset>
</div> <!-- End script editor options panel --> </div> <!-- End script editor options panel -->
@ -173,7 +173,7 @@
<table id="terminal"> <table id="terminal">
<tr id="terminal-input"> <tr id="terminal-input">
<td id="terminal-input-td" tabindex="2">$ <td id="terminal-input-td" tabindex="2">$
<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" onfocus="this.value = this.value;"/> <input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" onfocus="this.value = this.value;" />
</td> </td>
</tr> </tr>
</table> </table>
@ -190,7 +190,7 @@
provides information about each script's production. The scripts are categorized by the hostname of the servers on which provides information about each script's production. The scripts are categorized by the hostname of the servers on which
they are running. </p> they are running. </p>
<p id="active-scripts-total-prod">Total online production of <p id="active-scripts-total-prod">Total online production of
Active scripts: <span class="money-gold"><span id="active-scripts-total-production-active">$0.000</span> / sec</span><br/> Active scripts: <span class="money-gold"><span id="active-scripts-total-production-active">$0.000</span> / sec</span><br />
Total online production since last Aug installation: <span id="active-scripts-total-prod-aug-total" class="money-gold">$0.000</span> Total online production since last Aug installation: <span id="active-scripts-total-prod-aug-total" class="money-gold">$0.000</span>
(<span class="money-gold"><span id="active-scripts-total-prod-aug-avg" class="money-gold">$0.000</span> / sec</span>)</p> (<span class="money-gold"><span id="active-scripts-total-prod-aug-avg" class="money-gold">$0.000</span> / sec</span>)</p>
<ul class="active-scripts-list" id="active-scripts-list" style="list-style: none;"> <ul class="active-scripts-list" id="active-scripts-list" style="list-style: none;">
@ -204,19 +204,19 @@
The Hacknet is a global, decentralized network of machines. It is used by hackers all around The Hacknet is a global, decentralized network of machines. It is used by hackers all around
the world to anonymously share computing power and perform distributed cyberattacks without the the world to anonymously share computing power and perform distributed cyberattacks without the
fear of being traced. fear of being traced.
<br/><br/> <br /><br />
Here, you can purchase a Hacknet Node, a specialized machine that can connect and contribute its Here, you can purchase a Hacknet Node, a specialized machine that can connect and contribute its
resources to the Hacknet network. This allows you to take a small percentage of profits resources to the Hacknet network. This allows you to take a small percentage of profits
from hacks performed on the network. Essentially, you are renting out your Node's computing power. from hacks performed on the network. Essentially, you are renting out your Node's computing power.
<br/><br/> <br /><br />
Each Hacknet Node you purchase will passively earn you money. Each Hacknet Node can be upgraded Each Hacknet Node you purchase will passively earn you money. Each Hacknet Node can be upgraded
in order to increase its computing power and thereby increase the profit you earn from it. in order to increase its computing power and thereby increase the profit you earn from it.
</p> </p>
<a id="hacknet-nodes-purchase-button" class="a-link-button"> Purchase Hacknet Node </a> <a id="hacknet-nodes-purchase-button" class="a-link-button"> Purchase Hacknet Node </a>
<br/> <br />
<div id="hacknet-nodes-money-multipliers-div"> <div id="hacknet-nodes-money-multipliers-div">
<p id="hacknet-nodes-money"> <p id="hacknet-nodes-money">
<span>Money:</span><span id="hacknet-nodes-player-money" class="money-gold"></span><br/> <span>Money:</span><span id="hacknet-nodes-player-money" class="money-gold"></span><br />
<span>Total Hacknet Node Production:</span><span id="hacknet-nodes-total-production" class="money-gold"></span> <span>Total Hacknet Node Production:</span><span id="hacknet-nodes-total-production" class="money-gold"></span>
</p> </p>
<span id="hacknet-nodes-multipliers"> <span id="hacknet-nodes-multipliers">
@ -474,7 +474,8 @@
<!-- Tutorial content --> <!-- Tutorial content -->
<div id="tutorial-container" class="generic-menupage-container"> <div id="tutorial-container" class="generic-menupage-container">
<a id="tutorial-getting-started-link" class="a-link-button" href="http://bitburner.wikia.com/wiki/Chapt3rs_Guide_to_Getting_Started_with_Bitburner" target="_blank"> Getting Started </a> <a id="tutorial-getting-started-link" class="a-link-button"
href="http://bitburner.wikia.com/wiki/Chapt3rs_Guide_to_Getting_Started_with_Bitburner" target="_blank"> Getting Started </a>
<a id="tutorial-networking-link" class="a-link-button"> Servers & Networking </a> <a id="tutorial-networking-link" class="a-link-button"> Servers & Networking </a>
<a id="tutorial-hacking-link" class="a-link-button"> Hacking </a> <a id="tutorial-hacking-link" class="a-link-button"> Hacking </a>
<a id="tutorial-scripts-link" class="a-link-button"> Scripts </a> <a id="tutorial-scripts-link" class="a-link-button"> Scripts </a>
@ -483,7 +484,8 @@
<a id="tutorial-jobs-link" class="a-link-button"> Companies and Infiltration </a> <a id="tutorial-jobs-link" class="a-link-button"> Companies and Infiltration </a>
<a id="tutorial-factions-link" class="a-link-button"> Factions </a> <a id="tutorial-factions-link" class="a-link-button"> Factions </a>
<a id="tutorial-augmentations-link" class="a-link-button"> Augmentations </a> <a id="tutorial-augmentations-link" class="a-link-button"> Augmentations </a>
<a id="tutorial-shortcuts-link" class="a-link-button" href="https://bitburner.wikia.com/wiki/Shortcuts" target="_blank"> Keyboard Shortcuts </a> <a id="tutorial-shortcuts-link" class="a-link-button"
href="https://bitburner.wikia.com/wiki/Shortcuts" target="_blank"> Keyboard Shortcuts </a>
<a id="tutorial-back-button" class="a-link-button"> Back </a> <a id="tutorial-back-button" class="a-link-button"> Back </a>
<p id="tutorial-text"> </p> <p id="tutorial-text"> </p>
@ -574,7 +576,7 @@
<p id="location-slums-description"> <p id="location-slums-description">
You have entered the Slums, a poverty-ridden district filled with gangs, criminals, and You have entered the Slums, a poverty-ridden district filled with gangs, criminals, and
other shadowy entities. The city's government and police have neglected this area for years... other shadowy entities. The city's government and police have neglected this area for years...
<br/><br/><br/> <br /><br /><br />
In the Slums, you can commit crimes to earn money and experience. Crime attempts are not always In the Slums, you can commit crimes to earn money and experience. Crime attempts are not always
successful. Your chance at successfully committing a crime is determined by your stats. successful. Your chance at successfully committing a crime is determined by your stats.
</p> </p>
@ -621,7 +623,7 @@
<div id="stock-market-container" class="generic-menupage-container"> <div id="stock-market-container" class="generic-menupage-container">
<p> <p>
Welcome to the World Stock Exchange (WSE)! <br/><br/> Welcome to the World Stock Exchange (WSE)! <br /><br />
To begin trading, you must first purchase an account. WSE accounts will persist To begin trading, you must first purchase an account. WSE accounts will persist
after you 'reset' by installing Augmentations. after you 'reset' by installing Augmentations.
@ -634,7 +636,7 @@
TIX, short for Trade Information eXchange, is the communications protocol supported by the WSE. TIX, short for Trade Information eXchange, is the communications protocol supported by the WSE.
Purchasing access to the TIX API lets you write code to create your own algorithmic/automated Purchasing access to the TIX API lets you write code to create your own algorithmic/automated
trading strategies. trading strategies.
<br/><br/> <br /><br />
If you purchase access to the TIX API, you will retain that access even after If you purchase access to the TIX API, you will retain that access even after
you 'reset' by installing Augmentations. you 'reset' by installing Augmentations.
</p> </p>
@ -644,7 +646,7 @@
<p> <p>
Four Sigma's (4S) Market Data Feed provides information about stocks Four Sigma's (4S) Market Data Feed provides information about stocks
that will help your trading strategies. that will help your trading strategies.
<br/><br/> <br /><br />
If you purchase access to 4S Market Data and/or the 4S TIX API, you will If you purchase access to 4S Market Data and/or the 4S TIX API, you will
retain that access even after you 'reset' by installing Augmentations. retain that access even after you 'reset' by installing Augmentations.
</p> </p>
@ -662,7 +664,7 @@
<a id="stock-market-mode" class="a-link-button tooltip"></a> <a id="stock-market-mode" class="a-link-button tooltip"></a>
<a id="stock-market-expand-tickers" class="a-link-button tooltip">Expand tickers</a> <a id="stock-market-expand-tickers" class="a-link-button tooltip">Expand tickers</a>
<a id="stock-market-collapse-tickers" class="a-link-button tooltip">Collapse tickers</a> <a id="stock-market-collapse-tickers" class="a-link-button tooltip">Collapse tickers</a>
<br/><br/> <br /><br />
<input id="stock-market-watchlist-filter" type="text" placeholder="Filter Stocks by symbol (comma-separated list)"/> <input id="stock-market-watchlist-filter" type="text" placeholder="Filter Stocks by symbol (comma-separated list)"/>
<a id="stock-market-watchlist-filter-update" class="a-link-button"> Update Watchlist </a> <a id="stock-market-watchlist-filter-update" class="a-link-button"> Update Watchlist </a>
<ul id="stock-market-list" style="list-style:none;"> <ul id="stock-market-list" style="list-style:none;">
@ -692,7 +694,7 @@
<div id="yes-no-text-input-box-container" class="popup-box-container"> <div id="yes-no-text-input-box-container" class="popup-box-container">
<div id="yes-no-text-input-box-content" class="popup-box-content"> <div id="yes-no-text-input-box-content" class="popup-box-content">
<p id="yes-no-text-input-box-text"> </p> <p id="yes-no-text-input-box-text"> </p>
<input type="text" id="yes-no-text-input-box-input" pattern="[a-zA-Z0-9-_]" maxlength="30"/> <input type="text" id="yes-no-text-input-box-input" pattern="[a-zA-Z0-9-_]" maxlength="30" />
<button id="yes-no-text-input-box-yes" class="popup-box-button"> Yes </button> <button id="yes-no-text-input-box-yes" class="popup-box-button"> Yes </button>
<button id="yes-no-text-input-box-no" class="popup-box-button"> No </button> <button id="yes-no-text-input-box-no" class="popup-box-button"> No </button>
</div> </div>
@ -704,7 +706,7 @@
<p id="faction-invitation-box-text"> </p> <p id="faction-invitation-box-text"> </p>
<p id="faction-invitation-box-message"> </p> <p id="faction-invitation-box-message"> </p>
<p id="faction-invitation-box-warning"> <p id="faction-invitation-box-warning">
Would you like to join? <br/> <br/> Would you like to join? <br /> <br />
Warning: Joining this faction may prevent you from joining other factions during this run! Warning: Joining this faction may prevent you from joining other factions during this run!
</p> </p>
<button id="faction-invitation-box-yes" class="popup-box-button"> Yes </button> <button id="faction-invitation-box-yes" class="popup-box-button"> Yes </button>
@ -717,8 +719,8 @@
<div id="infiltration-box-content" class="popup-box-content"> <div id="infiltration-box-content" class="popup-box-content">
<p id="infiltration-box-text"> </p> <p id="infiltration-box-text"> </p>
<button id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </button> <br/><br/> <button id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </button> <br /><br />
<select id="infiltration-faction-select"> </select> <br/> <select id="infiltration-faction-select"> </select> <br />
<button id="infiltration-box-faction" class="a-link-button"> Give to Faction for Reputation </button> <button id="infiltration-box-faction" class="a-link-button"> Give to Faction for Reputation </button>
</div> </div>
@ -804,7 +806,7 @@
<div id="game-options-content" class="game-options-box"> <div id="game-options-content" class="game-options-box">
<button id="game-options-close-button">&times;</button> <button id="game-options-close-button">&times;</button>
<h1> Game Options </h1> <h1> Game Options </h1>
<br/> <br />
<div id="game-options-left-panel"> <div id="game-options-left-panel">
<!-- Netscript execution time --> <!-- Netscript execution time -->
<fieldset> <fieldset>
@ -816,7 +818,7 @@
</span> </span>
</label> </label>
<input type="range" max="100" min="10" step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="25"/> <input type ="range" max="100" min="10" step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="25" />
<em id="settingsNSExecTimeRangeValLabel" style="font-style: normal;"></em> <em id="settingsNSExecTimeRangeValLabel" style="font-style: normal;"></em>
</fieldset> </fieldset>
@ -830,7 +832,7 @@
</span> </span>
</label> </label>
<input type="range" max="100" min="20" step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50"/> <input type="range" max="100" min="20" step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50" />
<em id="settingsNSLogRangeValLabel" style="font-style: normal;"></em> <em id="settingsNSLogRangeValLabel" style="font-style: normal;"></em>
</fieldset> </fieldset>
@ -844,7 +846,7 @@
</span> </span>
</label> </label>
<input type="range" max="100" min="20" step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50"/> <input type="range" max="100" min="20" step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50" />
<em id="settingsNSPortRangeValLabel" style="font-style: normal;"></em> <em id="settingsNSPortRangeValLabel" style="font-style: normal;"></em>
</fieldset> </fieldset>
@ -856,7 +858,7 @@
</span> </span>
</label> </label>
<input type="range" max="600" min="0" step="1" name="settingsAutosaveIntervalVal" id="settingsAutosaveIntervalVal" value="60"/> <input type="range" max="600" min="0" step="1" name="settingsAutosaveIntervalVal" id="settingsAutosaveIntervalVal" value="60" />
<em id="settingsAutosaveIntervalValLabel" style="font-style: normal;"></em> <em id="settingsAutosaveIntervalValLabel" style="font-style: normal;"></em>
</fieldset> </fieldset>
@ -968,7 +970,7 @@
<a id="save-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Save Game </a> <a id="save-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Save Game </a>
<a id="delete-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Delete Game </a> <a id="delete-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Delete Game </a>
<a id="export-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Export Game </a> <a id="export-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Export Game </a>
<input type="file" id="import-game-file-selector" name="file"/> <input type="file" id="import-game-file-selector" name="file" />
<a id="import-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Import Game </a> <a id="import-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Import Game </a>
<a id="debug-delete-scripts-link" class="a-link-button tooltip" style="display:block;width:46%;"> <a id="debug-delete-scripts-link" class="a-link-button tooltip" style="display:block;width:46%;">
(DEBUG) Delete Active Scripts (DEBUG) Delete Active Scripts

@ -1,26 +1,27 @@
import {BitNodeMultipliers} from "./BitNodeMultipliers"; import { BitNodeMultipliers } from "./BitNodeMultipliers";
import {CONSTANTS} from "./Constants"; import { CONSTANTS } from "./Constants";
import {Engine} from "./engine"; import { Engine } from "./engine";
import {Factions, factionExists} from "./Faction"; import { Factions,
import {hasBladeburnerSF} from "./NetscriptFunctions"; factionExists } from "./Faction/Factions";
import {addWorkerScript} from "./NetscriptWorker"; import { hasBladeburnerSF } from "./NetscriptFunctions";
import {Player} from "./Player"; import { addWorkerScript } from "./NetscriptWorker";
import {prestigeAugmentation} from "./Prestige"; import { Player } from "./Player";
import {saveObject} from "./SaveObject"; import { prestigeAugmentation } from "./Prestige";
import {Script, RunningScript} from "./Script"; import { saveObject } from "./SaveObject";
import {Server} from "./Server"; import { Script , RunningScript} from "./Script";
import {OwnedAugmentationsOrderSetting} from "./SettingEnums"; import { Server } from "./Server";
import {Settings} from "./Settings"; import { OwnedAugmentationsOrderSetting } from "./SettingEnums";
import { Settings } from "./Settings";
import {SourceFiles} from "./SourceFile"; import { SourceFiles } from "./SourceFile";
import {dialogBoxCreate} from "../utils/DialogBox"; import { dialogBoxCreate } from "../utils/DialogBox";
import {createAccordionElement} from "../utils/uiHelpers/createAccordionElement"; import { createAccordionElement } from "../utils/uiHelpers/createAccordionElement";
import {Reviver, Generic_toJSON, import { Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver"; Generic_fromJSON } from "../utils/JSONReviver";
import {clearObject} from "../utils/helpers/clearObject"; import { clearObject } from "../utils/helpers/clearObject";
import {createElement} from "../utils/uiHelpers/createElement"; import { createElement } from "../utils/uiHelpers/createElement";
import {isString} from "../utils/helpers/isString"; import { isString } from "../utils/helpers/isString";
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement"; import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
//Augmentations //Augmentations
function Augmentation(params) { function Augmentation(params) {
@ -1569,13 +1570,13 @@ function initAugmentations() {
//Do this before adding special Augmentations that become available in later BitNodes //Do this before adding special Augmentations that become available in later BitNodes
if (Player.bitNodeN === 2) { if (Player.bitNodeN === 2) {
console.log("Adding all augmentations to crime factions for Bit node 2"); console.log("Adding all augmentations to crime factions for Bit node 2");
Factions["Slum Snakes"].addAllAugmentations(); Factions["Slum Snakes"].addAllAugmentations(Augmentations);
Factions["Tetrads"].addAllAugmentations(); Factions["Tetrads"].addAllAugmentations(Augmentations);
Factions["The Syndicate"].addAllAugmentations(); Factions["The Syndicate"].addAllAugmentations(Augmentations);
Factions["The Dark Army"].addAllAugmentations(); Factions["The Dark Army"].addAllAugmentations(Augmentations);
Factions["Speakers for the Dead"].addAllAugmentations(); Factions["Speakers for the Dead"].addAllAugmentations(Augmentations);
Factions["NiteSec"].addAllAugmentations(); Factions["NiteSec"].addAllAugmentations(Augmentations);
Factions["The Black Hand"].addAllAugmentations(); Factions["The Black Hand"].addAllAugmentations(Augmentations);
} }
//Special Bladeburner Augmentations //Special Bladeburner Augmentations

@ -1,32 +1,33 @@
import {Augmentations, AugmentationNames} from "./Augmentations"; import { Augmentations , AugmentationNames } from "./Augmentations";
import {BitNodeMultipliers} from "./BitNodeMultipliers"; import { BitNodeMultipliers } from "./BitNodeMultipliers";
import {CONSTANTS} from "./Constants"; import { CONSTANTS } from "./Constants";
import {Engine} from "./engine"; import { Engine } from "./engine";
import {Faction, Factions, factionExists, import { Faction } from "./Faction/Faction";
joinFaction, displayFactionContent} from "./Faction"; import { Factions, factionExists } from "./Faction/Factions";
import {Locations} from "./Locations"; import { joinFaction, displayFactionContent } from "./Faction/FactionHelpers";
import {Player} from "./Player"; import { Locations } from "./Locations";
import {hackWorldDaemon, redPillFlag} from "./RedPill"; import { Player } from "./Player";
import {numeralWrapper} from "./ui/numeralFormat"; import { hackWorldDaemon, redPillFlag } from "./RedPill";
import {KEY} from "../utils/helpers/keyCodes"; import { numeralWrapper } from "./ui/numeralFormat";
import { KEY } from "../utils/helpers/keyCodes";
import {createProgressBarText} from "../utils/helpers/createProgressBarText"; import { createProgressBarText } from "../utils/helpers/createProgressBarText";
import {dialogBoxCreate} from "../utils/DialogBox"; import { dialogBoxCreate } from "../utils/DialogBox";
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement"; import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
import {Reviver, Generic_toJSON, import { Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver"; Generic_fromJSON } from "../utils/JSONReviver";
import {addOffset} from "../utils/helpers/addOffset"; import { addOffset } from "../utils/helpers/addOffset";
import {appendLineBreaks} from "../utils/uiHelpers/appendLineBreaks"; import { appendLineBreaks } from "../utils/uiHelpers/appendLineBreaks";
import {clearObject} from "../utils/helpers/clearObject"; import { clearObject } from "../utils/helpers/clearObject";
import {createElement} from "../utils/uiHelpers/createElement"; import { createElement } from "../utils/uiHelpers/createElement";
import {createPopup} from "../utils/uiHelpers/createPopup"; import { createPopup } from "../utils/uiHelpers/createPopup";
import {Page, routing} from "./ui/navigationTracking"; import { Page, routing } from "./ui/navigationTracking";
import {exceptionAlert} from "../utils/helpers/exceptionAlert"; import { exceptionAlert } from "../utils/helpers/exceptionAlert";
import {formatNumber} from "../utils/StringHelperFunctions"; import { formatNumber } from "../utils/StringHelperFunctions";
import {getRandomInt} from "../utils/helpers/getRandomInt"; import { getRandomInt } from "../utils/helpers/getRandomInt";
import {getTimestamp} from "../utils/helpers/getTimestamp"; import { getTimestamp } from "../utils/helpers/getTimestamp";
import {removeElement} from "../utils/uiHelpers/removeElement"; import { removeElement } from "../utils/uiHelpers/removeElement";
import {removeElementById} from "../utils/uiHelpers/removeElementById"; import { removeElementById } from "../utils/uiHelpers/removeElementById";
var CityNames = ["Aevum", "Chongqing", "Sector-12", "New Tokyo", "Ishima", "Volhaven"]; var CityNames = ["Aevum", "Chongqing", "Sector-12", "New Tokyo", "Ishima", "Volhaven"];
@ -2105,7 +2106,7 @@ Bladeburner.prototype.createBlackOpsContent = function() {
"Each Black Op must be unlocked successively by completing " + "Each Black Op must be unlocked successively by completing " +
"the one before it.<br><br>" + "the one before it.<br><br>" +
"<b>Your ultimate goal to climb through the ranks of Bladeburners is to complete " + "<b>Your ultimate goal to climb through the ranks of Bladeburners is to complete " +
"all of the Black Ops.</b><br><br>" + "all of the Black Ops.</b><br><br>" +
"Like normal operations, you may use a team for Black Ops. Failing " + "Like normal operations, you may use a team for Black Ops. Failing " +
"a black op will incur heavy HP and rank losses."; "a black op will incur heavy HP and rank losses.";

@ -1,12 +1,12 @@
import {CodingContract, import { CodingContract,
CodingContractRewardType, CodingContractRewardType,
CodingContractTypes} from "./CodingContracts"; CodingContractTypes } from "./CodingContracts";
import {Factions} from "./Faction"; import { Factions } from "./Faction/Factions";
import {Player} from "./Player"; import { Player } from "./Player";
import {GetServerByHostname, import { GetServerByHostname,
AllServers} from "./Server"; AllServers } from "./Server";
import {getRandomInt} from "../utils/helpers/getRandomInt"; import { getRandomInt } from "../utils/helpers/getRandomInt";
export function generateRandomContract() { export function generateRandomContract() {
// First select a random problem type // First select a random problem type

@ -125,7 +125,7 @@ export class Company {
} }
/** /**
* Serialize the current file to a JSON save state. * Serialize the current object to a JSON save state.
*/ */
toJSON(): any { toJSON(): any {
return Generic_toJSON("Company", this); return Generic_toJSON("Company", this);

@ -1,29 +1,34 @@
import {BitNodeMultipliers} from "./BitNodeMultipliers"; import { BitNodeMultipliers } from "./BitNodeMultipliers";
import {Factions} from "./Faction"; import { Factions } from "./Faction/Factions";
import {showLiterature} from "./Literature"; import { showLiterature } from "./Literature";
import {Locations} from "./Locations"; import { Locations } from "./Locations";
import {Player} from "./Player"; import { Player } from "./Player";
import Decimal from "decimal.js"; import Decimal from "decimal.js";
import {numeralWrapper} from "./ui/numeralFormat"; import { numeralWrapper } from "./ui/numeralFormat";
import {dialogBoxCreate} from "../utils/DialogBox"; import { dialogBoxCreate } from "../utils/DialogBox";
import {clearSelector} from "../utils/uiHelpers/clearSelector"; import { clearSelector } from "../utils/uiHelpers/clearSelector";
import {Reviver, Generic_toJSON, import { Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver"; Generic_fromJSON } from "../utils/JSONReviver";
import {createElement} from "../utils/uiHelpers/createElement"; import { createElement } from "../utils/uiHelpers/createElement";
import {createPopup} from "../utils/uiHelpers/createPopup"; import { createPopup } from "../utils/uiHelpers/createPopup";
import {Page, routing} from "./ui/navigationTracking"; import { Page, routing } from "./ui/navigationTracking";
import {formatNumber, generateRandomString} from "../utils/StringHelperFunctions"; import { formatNumber, generateRandomString } from "../utils/StringHelperFunctions";
import {getRandomInt} from "../utils/helpers/getRandomInt"; import { getRandomInt } from "../utils/helpers/getRandomInt";
import {isString} from "../utils/helpers/isString"; import { isString } from "../utils/helpers/isString";
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement"; import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
import {removeElementById} from "../utils/uiHelpers/removeElementById"; import { removeElementById } from "../utils/uiHelpers/removeElementById";
import {yesNoBoxCreate, yesNoTxtInpBoxCreate, import { yesNoBoxCreate,
yesNoBoxGetYesButton, yesNoBoxGetNoButton, yesNoTxtInpBoxCreate,
yesNoTxtInpBoxGetYesButton, yesNoTxtInpBoxGetNoButton, yesNoBoxGetYesButton,
yesNoTxtInpBoxGetInput, yesNoBoxClose, yesNoBoxGetNoButton,
yesNoTxtInpBoxClose, yesNoBoxOpen} from "../utils/YesNoBox"; yesNoTxtInpBoxGetYesButton,
yesNoTxtInpBoxGetNoButton,
yesNoTxtInpBoxGetInput,
yesNoBoxClose,
yesNoTxtInpBoxClose,
yesNoBoxOpen } from "../utils/YesNoBox";
/* State */ /* State */
var companyStates = ["START", "PURCHASE", "PRODUCTION", "SALE", "EXPORT"]; var companyStates = ["START", "PURCHASE", "PRODUCTION", "SALE", "EXPORT"];

@ -1,19 +1,19 @@
import {AugmentationNames} from "./Augmentations"; import { AugmentationNames } from "./Augmentations";
import {generateRandomContract} from "./CodingContractGenerator"; import { generateRandomContract } from "./CodingContractGenerator";
import {Programs} from "./CreateProgram"; import { Programs } from "./CreateProgram";
import {Factions} from "./Faction"; import { Factions } from "./Faction/Factions";
import {Player} from "./Player"; import { Player } from "./Player";
import {AllServers} from "./Server"; import { AllServers } from "./Server";
import {hackWorldDaemon} from "./RedPill"; import { hackWorldDaemon } from "./RedPill";
import {StockMarket, import { StockMarket,
SymbolToStockMap} from "./StockMarket"; SymbolToStockMap } from "./StockMarket";
import {Stock} from "./Stock"; import { Stock } from "./Stock";
import {Terminal} from "./Terminal"; import { Terminal } from "./Terminal";
import {numeralWrapper} from "./ui/numeralFormat"; import { numeralWrapper } from "./ui/numeralFormat";
import {dialogBoxCreate} from "../utils/DialogBox"; import { dialogBoxCreate } from "../utils/DialogBox";
import {exceptionAlert} from "../utils/helpers/exceptionAlert"; import { exceptionAlert } from "../utils/helpers/exceptionAlert";
import {createElement} from "../utils/uiHelpers/createElement"; import { createElement } from "../utils/uiHelpers/createElement";
import {removeElementById} from "../utils/uiHelpers/removeElementById"; import { removeElementById } from "../utils/uiHelpers/removeElementById";
const devMenuContainerId = "dev-menu-container"; const devMenuContainerId = "dev-menu-container";

118
src/Faction/Faction.ts Normal file

@ -0,0 +1,118 @@
import { CONSTANTS } from "../Constants";
import { FactionInfo,
FactionInfos } from "./FactionInfo";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
export class Faction {
/**
* Initiatizes a Faction object from a JSON save state.
*/
static fromJSON(value: any): Faction {
return Generic_fromJSON(Faction, value.data);
}
/**
* Flag signalling whether the player has already received an invitation
* to this faction
*/
alreadyInvited: boolean = false;
/**
* Holds names of all augmentations that this Faction offers
*/
augmentations: string[] = [];
/**
* Amount of favor the player has with this faction.
*/
favor: number = 0;
/**
* Flag signalling whether player has been banned from this faction
*/
isBanned: boolean = false;
/**
* Flag signalling whether player is a member of this faction
*/
isMember: boolean = false;
/**
* Name of faction
*/
name: string = "";
/**
* Amount of reputation player has with this faction
*/
playerReputation: number = 0;
/**
* Reputation from the last "prestige" that was not converted to favor.
* This reputation rolls over and is used for the next favor calculation
*/
rolloverRep: number = 0;
constructor(name: string="") {
this.name = name;
}
getInfo(): FactionInfo {
const info = FactionInfos[this.name];
if (info == null) {
throw new Error(`Missing faction from FactionInfos: ${this.name} this probably means the faction got corrupted somehow`);
}
return info;
}
gainFavor(): void {
if (this.favor == null) { this.favor = 0; }
if (this.rolloverRep == null) { this.rolloverRep = 0; }
const res = this.getFavorGain();
if (res.length !== 2) {
console.error("Invalid result from getFavorGain() function");
return;
}
this.favor += res[0];
this.rolloverRep = res[1];
}
//Returns an array with [How much favor would be gained, how much rep would be left over]
getFavorGain(): number[] {
if (this.favor == null) { this.favor = 0; }
if (this.rolloverRep == null) { this.rolloverRep = 0; }
var favorGain = 0, rep = this.playerReputation + this.rolloverRep;
let reqdRep = CONSTANTS.FactionReputationToFavorBase *
Math.pow(CONSTANTS.FactionReputationToFavorMult, this.favor);
while(rep > 0) {
if (rep >= reqdRep) {
++favorGain;
rep -= reqdRep;
} else {
break;
}
reqdRep *= CONSTANTS.FactionReputationToFavorMult;
}
return [favorGain, rep];
}
//Adds all Augmentations to this faction.
addAllAugmentations(augs: object): void {
this.augmentations.length = 0;
for (const name in augs) {
if (augs.hasOwnProperty(name)) {
this.augmentations.push(name);
}
}
}
/**
* Serialize the current object to a JSON save state.
*/
toJSON(): any {
return Generic_toJSON("Faction", this);
}
}
Reviver.constructors.Faction = Faction;

@ -1,139 +1,26 @@
import {Augmentations, AugmentationNames, import {Augmentations, AugmentationNames,
PlayerOwnedAugmentation} from "./Augmentations"; PlayerOwnedAugmentation} from "../Augmentations";
import {BitNodeMultipliers} from "./BitNodeMultipliers"; import {BitNodeMultipliers} from "../BitNodeMultipliers";
import {CONSTANTS} from "./Constants"; import {CONSTANTS} from "../Constants";
import {Engine} from "./engine"; import {Engine} from "../engine";
import {FactionInfos} from "./FactionInfo"; import {FactionInfos} from "./FactionInfo";
import {Locations} from "./Location"; import {Locations} from "../Location";
import {HackingMission, setInMission} from "./Missions"; import {HackingMission, setInMission} from "../Missions";
import {Player} from "./Player"; import {Player} from "../Player";
import {PurchaseAugmentationsOrderSetting} from "./SettingEnums"; import {PurchaseAugmentationsOrderSetting} from "../SettingEnums";
import {Settings} from "./Settings"; import {Settings} from "../Settings";
import {Page, routing} from "./ui/navigationTracking"; import {Page, routing} from "../ui/navigationTracking";
import {numeralWrapper} from "./ui/numeralFormat"; import {numeralWrapper} from "../ui/numeralFormat";
import {dialogBoxCreate} from "../utils/DialogBox"; import {dialogBoxCreate} from "../../utils/DialogBox";
import {factionInvitationBoxCreate} from "../utils/FactionInvitationBox"; import {factionInvitationBoxCreate} from "../../utils/FactionInvitationBox";
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement"; import {removeChildrenFromElement} from "../../utils/uiHelpers/removeChildrenFromElement";
import {createElement} from "../utils/uiHelpers/createElement"; import {createElement} from "../../utils/uiHelpers/createElement";
import {Reviver, Generic_toJSON, import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver"; Generic_fromJSON} from "../../utils/JSONReviver";
import {formatNumber} from "../utils/StringHelperFunctions"; import {formatNumber} from "../../utils/StringHelperFunctions";
import {yesNoBoxCreate, yesNoBoxGetYesButton, import {yesNoBoxCreate, yesNoBoxGetYesButton,
yesNoBoxGetNoButton, yesNoBoxClose} from "../utils/YesNoBox"; yesNoBoxGetNoButton, yesNoBoxClose} from "../../utils/YesNoBox";
function Faction(name="") {
this.name = name;
this.augmentations = []; //Name of augmentation only
//Player-related properties for faction
this.isMember = false; //Whether player is member
this.isBanned = false; //Whether or not player is banned from joining this faction
this.playerReputation = 0; //"Reputation" within faction
this.alreadyInvited = false;
//Faction favor
this.favor = 0;
this.rolloverRep = 0;
};
Faction.prototype.getInfo = function() {
const info = FactionInfos[this.name];
if(info == null) {
throw new Error("Missing faction from FactionInfos: " + this.name+" this probably means the faction got corrupted somehow");
}
return info;
}
Faction.prototype.gainFavor = function() {
if (this.favor == null || this.favor == undefined) {this.favor = 0;}
if (this.rolloverRep == null || this.rolloverRep == undefined) {this.rolloverRep = 0;}
var res = this.getFavorGain();
if (res.length != 2) {
console.log("Error: invalid result from getFavorGain() function");
return;
}
this.favor += res[0];
this.rolloverRep = res[1];
}
//Returns an array with [How much favor would be gained, how much rep would be left over]
Faction.prototype.getFavorGain = function() {
if (this.favor == null || this.favor == undefined) {this.favor = 0;}
if (this.rolloverRep == null || this.rolloverRep == undefined) {this.rolloverRep = 0;}
var favorGain = 0, rep = this.playerReputation + this.rolloverRep;
var reqdRep = CONSTANTS.FactionReputationToFavorBase *
Math.pow(CONSTANTS.FactionReputationToFavorMult, this.favor);
while(rep > 0) {
if (rep >= reqdRep) {
++favorGain;
rep -= reqdRep;
} else {
break;
}
reqdRep *= CONSTANTS.FactionReputationToFavorMult;
}
return [favorGain, rep];
}
//Adds all Augmentations to this faction.
Faction.prototype.addAllAugmentations = function() {
this.augmentations.length = 0;
for (var name in Augmentations) {
if (Augmentations.hasOwnProperty(name)) {
this.augmentations.push(name);
}
}
}
Faction.prototype.toJSON = function() {
return Generic_toJSON("Faction", this);
}
Faction.fromJSON = function(value) {
return Generic_fromJSON(Faction, value.data);
}
Reviver.constructors.Faction = Faction;
//Map of factions indexed by faction name
let Factions = {}
function loadFactions(saveString) {
Factions = JSON.parse(saveString, Reviver);
}
function AddToFactions(faction) {
var name = faction.name;
Factions[name] = faction;
}
function factionExists(name) {
return Factions.hasOwnProperty(name);
}
//TODO Augmentation price and rep requirement mult are 1 for everything right now,
// This might change in the future for balance
function initFactions() {
for(const name in FactionInfos) {
resetFaction(new Faction(name));
}
}
//Resets a faction during (re-)initialization. Saves the favor in the new
//Faction object and deletes the old Faction Object from "Factions". Then
//reinserts the new Faction object
function resetFaction(newFactionObject) {
if (!(newFactionObject instanceof Faction)) {
throw new Error("Invalid argument 'newFactionObject' passed into resetFaction()");
}
var factionName = newFactionObject.name;
if (factionExists(factionName)) {
newFactionObject.favor = Factions[factionName].favor;
delete Factions[factionName];
}
AddToFactions(newFactionObject);
}
function inviteToFaction(faction) { function inviteToFaction(faction) {
if (Settings.SuppressFactionInvites) { if (Settings.SuppressFactionInvites) {
@ -783,6 +670,6 @@ function processPassiveFactionRepGain(numCycles) {
} }
} }
export {getNextNeurofluxLevel, Factions, initFactions, inviteToFaction, export {getNextNeurofluxLevel, inviteToFaction,
joinFaction, displayFactionContent, processPassiveFactionRepGain, joinFaction, displayFactionContent, processPassiveFactionRepGain,
loadFactions, Faction, purchaseAugmentation, factionExists}; purchaseAugmentation};

@ -1,9 +1,9 @@
import { IMap } from "./types"; import { IMap } from "../types";
/** /**
* Contains the "information" property for all the Factions, which is just a description of each faction * Contains the "information" property for all the Factions, which is just a description of each faction
*/ */
class FactionInfo { export class FactionInfo {
/** /**
* The multiplier to apply to augmentation base purchase price. * The multiplier to apply to augmentation base purchase price.
*/ */

@ -0,0 +1,6 @@
export enum FactionWorkType {
Field,
Hacking,
None,
Security,
}

47
src/Faction/Factions.ts Normal file

@ -0,0 +1,47 @@
/**
* Initialization and manipulation of the Factions object, which stores data
* about all Factions in the game
*/
import { Faction } from "./Faction";
import { FactionInfos } from "./FactionInfo";
import { IMap } from "../types";
import { Reviver } from "../../utils/JSONReviver";
export let Factions: IMap<Faction> = {};
export function loadFactions(saveString: string): void {
Factions = JSON.parse(saveString, Reviver);
}
export function AddToFactions(faction: Faction) {
const name: string = faction.name;
Factions[name] = faction;
}
export function factionExists(name: string): boolean {
return Factions.hasOwnProperty(name);
}
export function initFactions(bitNode: number=1) {
for (const name in FactionInfos) {
resetFaction(new Faction(name));
}
}
//Resets a faction during (re-)initialization. Saves the favor in the new
//Faction object and deletes the old Faction Object from "Factions". Then
//reinserts the new Faction object
export function resetFaction(newFactionObject: Faction) {
if (!(newFactionObject instanceof Faction)) {
throw new Error("Invalid argument 'newFactionObject' passed into resetFaction()");
}
const factionName: string = newFactionObject.name;
if (factionExists(factionName)) {
newFactionObject.favor = Factions[factionName].favor;
delete Factions[factionName];
}
AddToFactions(newFactionObject);
}

1
src/Faction/README.md Normal file

@ -0,0 +1 @@
Implementation of Faction-related mechanics

@ -3,32 +3,39 @@ Also add police clashes
balance point to keep them from running out of control balance point to keep them from running out of control
*/ */
import {gangMemberTasksMetadata} from "./data/gangmembertasks"; import { gangMemberTasksMetadata } from "./data/gangmembertasks";
import {gangMemberUpgradesMetadata} from "./data/gangmemberupgrades"; import { gangMemberUpgradesMetadata } from "./data/gangmemberupgrades";
import {Engine} from "./engine"; import { Engine } from "./engine";
import {Faction, Factions, import { Faction } from "./Faction/Faction";
displayFactionContent} from "./Faction"; import { Factions } from "./Faction/Factions";
import {numeralWrapper} from "./ui/numeralFormat"; import { displayFactionContent } from "./Faction/FactionHelpers";
import {dialogBoxCreate} from "../utils/DialogBox"; import { numeralWrapper } from "./ui/numeralFormat";
import {Reviver, Generic_toJSON, import { dialogBoxCreate } from "../utils/DialogBox";
Generic_fromJSON} from "../utils/JSONReviver"; import { Reviver, Generic_toJSON,
import {KEY} from "../utils/helpers/keyCodes"; Generic_fromJSON } from "../utils/JSONReviver";
import {createAccordionElement} from "../utils/uiHelpers/createAccordionElement"; import { KEY } from "../utils/helpers/keyCodes";
import {createElement} from "../utils/uiHelpers/createElement"; import { createAccordionElement } from "../utils/uiHelpers/createAccordionElement";
import {createPopup} from "../utils/uiHelpers/createPopup"; import { createElement } from "../utils/uiHelpers/createElement";
import {Page, routing} from "./ui/navigationTracking"; import { createPopup } from "../utils/uiHelpers/createPopup";
import {formatNumber} from "../utils/StringHelperFunctions"; import { Page,
import {exceptionAlert} from "../utils/helpers/exceptionAlert"; routing } from "./ui/navigationTracking";
import {getRandomInt} from "../utils/helpers/getRandomInt"; import { formatNumber } from "../utils/StringHelperFunctions";
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement"; import { exceptionAlert } from "../utils/helpers/exceptionAlert";
import {removeElement} from "../utils/uiHelpers/removeElement"; import { getRandomInt } from "../utils/helpers/getRandomInt";
import {removeElementById} from "../utils/uiHelpers/removeElementById"; import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
import {yesNoBoxCreate, yesNoTxtInpBoxCreate, import { removeElement } from "../utils/uiHelpers/removeElement";
yesNoBoxGetYesButton, yesNoBoxGetNoButton, import { removeElementById } from "../utils/uiHelpers/removeElementById";
yesNoTxtInpBoxGetYesButton, yesNoTxtInpBoxGetNoButton, import { yesNoBoxCreate,
yesNoTxtInpBoxGetInput, yesNoBoxClose, yesNoTxtInpBoxCreate,
yesNoTxtInpBoxClose, yesNoBoxOpen} from "../utils/YesNoBox"; yesNoBoxGetYesButton,
yesNoBoxGetNoButton,
yesNoTxtInpBoxGetYesButton,
yesNoTxtInpBoxGetNoButton,
yesNoTxtInpBoxGetInput,
yesNoBoxClose,
yesNoTxtInpBoxClose,
yesNoBoxOpen } from "../utils/YesNoBox";
// Constants // Constants
const GangRespectToReputationRatio = 5; // Respect is divided by this to get rep gain const GangRespectToReputationRatio = 5; // Respect is divided by this to get rep gain

14
src/Locations/Cities.ts Normal file

@ -0,0 +1,14 @@
import { IMap } from "../types";
/**
* Display Location Content when visiting somewhere in the World
*/
// tslint:disable-next-line:variable-name
export const Cities: IMap<string> = {
Aevum: "Aevum",
Chongqing: "Chongqing",
Ishima: "Ishima",
NewTokyo: "New Tokyo",
Sector12: "Sector-12",
Volhaven: "Volhaven",
};

@ -1,14 +1,14 @@
import {CONSTANTS} from "./Constants"; import { CONSTANTS } from "./Constants";
import {Engine} from "./engine"; import { Engine } from "./engine";
import {displayFactionContent} from "./Faction"; import { displayFactionContent } from "./Faction/FactionHelpers";
import {Player} from "./Player"; import { Player } from "./Player";
import {dialogBoxCreate} from "../utils/DialogBox"; import { dialogBoxCreate } from "../utils/DialogBox";
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners"; import { clearEventListeners } from "../utils/uiHelpers/clearEventListeners";
import {addOffset} from "../utils/helpers/addOffset"; import { addOffset } from "../utils/helpers/addOffset";
import {formatNumber} from "../utils/StringHelperFunctions"; import { formatNumber } from "../utils/StringHelperFunctions";
import {getRandomInt} from "../utils/helpers/getRandomInt"; import { getRandomInt } from "../utils/helpers/getRandomInt";
import {isString} from "../utils/helpers/isString"; import { isString } from "../utils/helpers/isString";
import jsplumb from 'jsplumb' import jsplumb from 'jsplumb'
let inMission = false; //Flag to denote whether a mission is running let inMission = false; //Flag to denote whether a mission is running
let currMission = null; let currMission = null;

@ -22,9 +22,13 @@ import {calculateHackingChance,
calculateGrowTime, calculateGrowTime,
calculateWeakenTime} from "./Hacking"; calculateWeakenTime} from "./Hacking";
import {AllGangs} from "./Gang"; import {AllGangs} from "./Gang";
import {Factions, Faction, joinFaction, import { Faction } from "./Faction/Faction";
factionExists, purchaseAugmentation} from "./Faction"; import { Factions,
import {getCostOfNextHacknetNode, purchaseHacknet} from "./HacknetNode"; factionExists } from "./Faction/Factions";
import { joinFaction,
purchaseAugmentation } from "./Faction/FactionHelpers";
import { getCostOfNextHacknetNode,
purchaseHacknet } from "./HacknetNode";
import {Locations} from "./Locations"; import {Locations} from "./Locations";
import {Message, Messages} from "./Message"; import {Message, Messages} from "./Message";
import {inMission} from "./Missions"; import {inMission} from "./Missions";

268
src/PersonObjects/Person.ts Normal file

@ -0,0 +1,268 @@
// Base class representing a person-like object
import { BitNodeMultipliers } from "../BitNodeMultipliers";
import { Cities } from "../Locations/Cities";
import { CONSTANTS } from "../Constants";
// Interface for an object that represents the player (PlayerObject)
// Used because at the time of implementation, the PlayerObject
// cant be converted to TypeScript.
//
// Only contains the needed properties for Sleeve implementation
export interface IPlayer {
companyName: string;
factions: string[];
money: any;
gainHackingExp(exp: number): void;
gainStrengthExp(exp: number): void;
gainDefenseExp(exp: number): void;
gainDexterityExp(exp: number): void;
gainAgilityExp(exp: number): void;
gainCharismaExp(exp: number): void;
gainMoney(money: number): void;
loseMoney(money: number): void;
}
// Interface for a Crime object
// Used because at the time of implementation, the Crime object has not been converted
// to Typescript
export interface ICrime {
name: string;
type: string;
time: number;
money: number;
difficulty: number;
karma: number;
hacking_success_weight: number;
strength_success_weight: number;
defense_success_weight: number;
dexterity_success_weight: number;
agility_success_weight: number;
charisma_success_weight: number;
hacking_exp: number;
strength_exp: number;
defense_exp: number;
dexterity_exp: number;
agility_exp: number;
charisma_exp: number;
intelligence_exp: number;
kills: number;
}
// Interface for Faction object
// Used because at the time of implementation, the Faction object has not been
// converted to TypeScript
export interface IFaction {
name: string;
playerReputation: number;
}
// Interface that defines a generic object used to track experience/money
// earnings for tasks
export interface ITaskTracker {
hack: number;
str: number;
def: number;
dex: number;
agi: number;
cha: number;
money: number;
}
export function createTaskTracker(): ITaskTracker {
return {
hack: 0,
str: 0,
def: 0,
dex: 0,
agi: 0,
cha: 0,
money: 0,
}
}
export abstract class Person {
/**
* Stats
*/
hacking_skill: number;
strength: number;
defense: number;
dexterity: number;
agility: number;
charisma: number;
hp: number;
max_hp: number;
/**
* Multipliers
*/
hacking_exp: number;
strength_exp: number;
defense_exp: number;
dexterity_exp: number;
agility_exp: number;
charisma_exp: number;
intelligence_exp: number;
hacking_mult: number;
strength_mult: number;
defense_mult: number;
dexterity_mult: number;
agility_mult: number;
charisma_mult: number;
hacking_exp_mult: number;
strength_exp_mult: number;
defense_exp_mult: number;
dexterity_exp_mult: number;
agility_exp_mult: number;
charisma_exp_mult: number;
company_rep_mult: number;
faction_rep_mult: number;
crime_money_mult: number;
crime_success_mult: number;
work_money_mult: number;
/**
* City that the person is in
*/
city: string;
constructor() {
this.hacking_skill = 1;
this.strength = 1;
this.defense = 1;
this.dexterity = 1;
this.agility = 1;
this.charisma = 1;
this.hp = 10;
this.max_hp = 10;
// Multipliers
this.hacking_exp = 0;
this.strength_exp = 0;
this.defense_exp = 0;
this.dexterity_exp = 0;
this.agility_exp = 0;
this.charisma_exp = 0;
this.intelligence_exp = 0;
this.hacking_mult = 1;
this.strength_mult = 1;
this.defense_mult = 1;
this.dexterity_mult = 1;
this.agility_mult = 1;
this.charisma_mult = 1;
this.hacking_exp_mult = 1;
this.strength_exp_mult = 1;
this.defense_exp_mult = 1;
this.dexterity_exp_mult = 1;
this.agility_exp_mult = 1;
this.charisma_exp_mult = 1;
this.company_rep_mult = 1;
this.faction_rep_mult = 1;
this.crime_money_mult = 1;
this.crime_success_mult = 1;
this.work_money_mult = 1;
this.city = Cities.Sector12;
}
/**
* Given an experience amount and stat multiplier, calculates the
* stat level. Stat-agnostic (same formula for every stat)
*/
calculateStat(exp: number, mult: number=1): number {
return Math.max(Math.floor(mult*(32 * Math.log(exp + 534.5) - 200)), 1);
}
/**
* Calculate and return the amount of faction reputation earned per cycle
* when doing Field Work for a faction
*/
getFactionFieldWorkRepGain(): number {
const t = 0.9 * (this.hacking_skill / CONSTANTS.MaxSkillLevel +
this.strength / CONSTANTS.MaxSkillLevel +
this.defense / CONSTANTS.MaxSkillLevel +
this.dexterity / CONSTANTS.MaxSkillLevel +
this.agility / CONSTANTS.MaxSkillLevel +
this.charisma / CONSTANTS.MaxSkillLevel) / 5.5;
return t * this.faction_rep_mult;
}
/**
* Calculate and return the amount of faction reputation earned per cycle
* when doing Hacking Work for a faction
*/
getFactionHackingWorkRepGain(): number {
return this.hacking_skill / CONSTANTS.MaxSkillLevel * this.faction_rep_mult;
}
/**
* Calculate and return the amount of faction reputation earned per cycle
* when doing Security Work for a faction
*/
getFactionSecurityWorkRepGain(): number {
const t = 0.9 * (this.hacking_skill / CONSTANTS.MaxSkillLevel +
this.strength / CONSTANTS.MaxSkillLevel +
this.defense / CONSTANTS.MaxSkillLevel +
this.dexterity / CONSTANTS.MaxSkillLevel +
this.agility / CONSTANTS.MaxSkillLevel) / 4.5;
return t * this.faction_rep_mult;
}
/**
* Reset all multipliers to 1
*/
resetMultipliers(): void {
this.hacking_mult = 1;
this.strength_mult = 1;
this.defense_mult = 1;
this.dexterity_mult = 1;
this.agility_mult = 1;
this.charisma_mult = 1;
this.hacking_exp_mult = 1;
this.strength_exp_mult = 1;
this.defense_exp_mult = 1;
this.dexterity_exp_mult = 1;
this.agility_exp_mult = 1;
this.charisma_exp_mult = 1;
this.company_rep_mult = 1;
this.faction_rep_mult = 1;
this.crime_money_mult = 1;
this.crime_success_mult = 1;
this.work_money_mult = 1;
}
/**
* Update all stat levels
*/
updateStatLevels(): void {
this.hacking_skill = Math.max(1, Math.floor(this.calculateStat(this.hacking_exp, this.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier)));
this.strength = Math.max(1, Math.floor(this.calculateStat(this.strength_exp, this.strength_mult)));
this.defense = Math.max(1, Math.floor(this.calculateStat(this.defense_exp, this.defense_mult)));
this.dexterity = Math.max(1, Math.floor(this.calculateStat(this.dexterity_exp, this.dexterity_mult)));
this.agility = Math.max(1, Math.floor(this.calculateStat(this.agility_exp, this.agility_mult)));
this.charisma = Math.max(1, Math.floor(this.calculateStat(this.charisma_exp, this.charisma_mult)));
const ratio: number = this.hp / this.max_hp;
this.max_hp = Math.floor(10 + this.defense / 10);
this.hp = Math.round(this.max_hp * ratio);
}
}

@ -0,0 +1,2 @@
Implementation of all Person-type objects, including but not limited to
the "PlayerObject" and Sleeves.

@ -0,0 +1,598 @@
/**
* Sleeves are clones of the player that can be used to perform
* different tasks synchronously.
*
* Each sleeve is its own individual, meaning it has its own stats/exp
*
* Sleeves are unlocked in BitNode-10.
*/
import { SleeveTaskType } from "./SleeveTaskTypesEnum";
import { Person,
IPlayer,
ICrime,
IFaction,
ITaskTracker,
createTaskTracker } from "../Person";
import { BitNodeMultipliers } from "../../BitNodeMultipliers";
import { Cities } from "../../Locations/Cities";
import { Companies } from "../../Company/Companies";
import { Company } from "../../Company/Company";
import { CONSTANTS } from "../../Constants";
import { Faction } from "../../Faction/Faction";
import { Factions } from "../../Faction/Factions";
import { FactionWorkType } from "../../Faction/FactionWorkTypeEnum";
import { Locations } from "../../Locations";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../../utils/JSONReviver";
export class Sleeve extends Person {
/**
* Initiatizes a Sleeve object from a JSON save state.
*/
static fromJSON(value: any): Sleeve {
return Generic_fromJSON(Sleeve, value.data);
}
/**
* Enum value for current task
*/
currentTask: SleeveTaskType = SleeveTaskType.Idle;
/**
* Description of current task. Used only for logging purposes
*/
currentTaskDescription: string = "";
/**
* For what company/faction the current task is assigned to.
* Only applicable when working for faction or company, obviously
*/
currentTaskLocation: string = "";
/**
* Maximum amount of time (in milliseconds) that can be spent on current task.
*/
currentTaskMaxTime: number = 0;
/**
* Milliseconds spent on current task
*/
currentTaskTime: number = 0;
/**
* Keeps track of experience earned for other sleeves
*/
earningsForSleeves: ITaskTracker = createTaskTracker();
/**
* Keeps track of experience + money earned for player
*/
earningsForPlayer: ITaskTracker = createTaskTracker();
/**
* Keeps track of experienced earned in the current task/action
*/
earningsForTask: ITaskTracker = createTaskTracker();
/**
* Keeps track of what type of work sleeve is doing for faction, if applicable
*/
factionWorkType: FactionWorkType = FactionWorkType.None;
/**
* Records experience gain rate for the current task
*/
gainRatesForTask: ITaskTracker = createTaskTracker();
/**
* Keeps track of events/notifications for this sleeve
*/
logs: string[] = [];
/**
* Clone retains memory% of exp upon prestige. If exp would be lower than previously
* kept exp, nothing happens
*/
memory: number = 0;
/**
* Sleeve shock. Number between 1 and 100
* Trauma/shock that comes with being in a sleeve. Experience earned
* is multipled by shock%. This gets applied before synchronization
*/
shock: number = 1;
/**
* Stored number of game "loop" cycles
*/
storedCycles: number = 0;
/**
* Synchronization. Number between 0 and 100
* When experience is earned by sleeve, both the player and the sleeve get
* sync% of the experience earned. Other sleeves get sync^2% of exp
*/
sync: number = 1;
constructor() {
super();
/*
this.currentTask = SleeveTaskType.Idle;
this.currentTaskDescription = "";
this.currentTaskTime = 0;
this.currentTaskMaxTime = 0;
this.earningsForSleeves = createTaskTracker();
this.earningsForPlayer = createTaskTracker();
this.earningsForTask = createTaskTracker();
this.gainRatesForTask = createTaskTracker();
this.logs = [];
this.memory = 0;
this.shock = 1;
this.storedCycles = 0;
this.sync = 1;
*/
}
/**
* Commit crimes
*/
commitCrime(p: IPlayer, crime: ICrime): void {
if (this.currentTask !== SleeveTaskType.Idle) {
this.finishTask();
} else {
this.resetTaskStatus();
}
this.gainRatesForTask.hack = crime.hacking_exp * this.hacking_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.str = crime.strength_exp * this.strength_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.def = crime.defense_exp * this.defense_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.dex = crime.dexterity_exp * this.dexterity_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.agi = crime.agility_exp * this.agility_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.gainRatesForTask.cha = crime.charisma_exp * this.charisma_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.currentTaskMaxTime = crime.time;
this.currentTask = SleeveTaskType.Crime;
}
/**
* Called to stop the current task
*/
finishTask(): void {
if (this.currentTask === SleeveTaskType.Crime) {
} else {
}
this.resetTaskStatus();
}
/**
* Earn experience for any stats (supports multiple)
* This function also handles experience propogating to Player and other sleeves
*/
gainExperience(p: IPlayer, exp: ITaskTracker, numCycles: number=1): ITaskTracker {
// Experience is first multiplied by shock. Then 'synchronization'
// is accounted for
const multFac = (this.shock / 100) * (this.sync / 100) * numCycles;
const pHackExp = exp.hack * multFac;
const pStrExp = exp.str * multFac;
const pDefExp = exp.def * multFac;
const pDexExp = exp.dex * multFac;
const pAgiExp = exp.agi * multFac;
const pChaExp = exp.cha * multFac;
// Experience is gained by both this sleeve and player
if (pHackExp > 0) {
this.hacking_exp += pHackExp;
p.gainHackingExp(pHackExp);
this.earningsForPlayer.hack += pHackExp;
this.earningsForTask.hack += pHackExp;
}
if (pStrExp > 0) {
this.strength_exp += pStrExp;
p.gainStrengthExp(pStrExp);
this.earningsForPlayer.str += pStrExp;
this.earningsForTask.str += pStrExp;
}
if (pDefExp > 0) {
this.defense_exp += pDefExp;
p.gainDefenseExp(pDefExp);
this.earningsForPlayer.def += pDefExp;
this.earningsForTask.dex += pDefExp;
}
if (pDexExp > 0) {
this.dexterity_exp += pDexExp;
p.gainDexterityExp(pDexExp);
this.earningsForPlayer.dex += pDexExp;
this.earningsForTask.dex += pDexExp;
}
if (pAgiExp > 0) {
this.agility_exp += pAgiExp;
p.gainAgilityExp(pAgiExp);
this.earningsForPlayer.agi += pAgiExp;
this.earningsForTask.agi += pAgiExp;
}
if (pChaExp > 0) {
this.charisma_exp += pChaExp;
p.gainCharismaExp(pChaExp);
this.earningsForPlayer.cha += pChaExp;
this.earningsForTask.cha += pChaExp;
}
// Record earnings for other sleeves
this.earningsForSleeves.hack += (pHackExp * (this.sync / 100));
this.earningsForSleeves.str += (pStrExp * (this.sync / 100));
this.earningsForSleeves.def += (pDefExp * (this.sync / 100));
this.earningsForSleeves.dex += (pDexExp * (this.sync / 100));
this.earningsForSleeves.agi += (pAgiExp * (this.sync / 100));
this.earningsForSleeves.cha += (pChaExp * (this.sync / 100));
// Return the experience to be gained by other sleeves
return {
hack: pHackExp * (this.sync / 100),
str: pStrExp * (this.sync / 100),
def: pDefExp * (this.sync / 100),
dex: pDexExp * (this.sync / 100),
agi: pAgiExp * (this.sync / 100),
cha: pChaExp * (this.sync / 100),
money: 0,
}
}
/**
* Earn money for player
*/
gainMoney(p: IPlayer, task: ITaskTracker, numCycles: number=1): void {
p.gainMoney(task.money * numCycles);
}
/**
* Gets reputation gain for the current task
* Only applicable when working for company or faction
*/
getRepGain(): number {
if (this.currentTask === SleeveTaskType.Faction) {
switch (this.factionWorkType) {
case FactionWorkType.Hacking:
return this.getFactionHackingWorkRepGain();
case FactionWorkType.Field:
return this.getFactionFieldWorkRepGain();
case FactionWorkType.Security:
return this.getFactionSecurityWorkRepGain();
default:
console.warn(`Invalid Sleeve.factionWorkType property in Sleeve.getRepGain(): ${this.factionWorkType}`);
return 0;
}
} else if (this.currentTask === SleeveTaskType.Company) {
return 0;
} else {
console.warn(`Sleeve.getRepGain() called for invalid task type: ${this.currentTask}`);
return 0;
}
}
log(entry: string): void {
const MaxLogSize: number = 50;
this.logs.push(entry);
if (this.logs.length > MaxLogSize) {
this.logs.shift();
}
}
/**
* Process loop
* Returns an object containing the amount of experience that should be
* transferred to all other sleeves
*/
process(p: IPlayer, numCycles: number=1): ITaskTracker | null {
// Only process once every second (5 cycles)
const CyclesPerSecond = 1000 / CONSTANTS.MilliPerCycle;
this.storedCycles += numCycles;
if (this.storedCycles < CyclesPerSecond) { return null; }
// Shock gradually goes towards 100
this.shock = Math.max(100, this.shock + (0.0001 * this.storedCycles));
if (this.currentTask === SleeveTaskType.Idle) { return null; }
let time = this.storedCycles * CONSTANTS.MilliPerCycle;
let cyclesUsed = this.storedCycles;
if (this.currentTaskTime + time > this.currentTaskMaxTime) {
time = this.currentTaskMaxTime - this.currentTaskTime;
cyclesUsed = Math.floor(time / CONSTANTS.MilliPerCycle);
if (time < 0 || cyclesUsed < 0) {
console.warn(`Sleeve.process() calculated negative cycle usage`);
time = 0;
cyclesUsed = 0;
}
}
this.currentTaskTime += time;
let retValue: ITaskTracker = createTaskTracker();
switch (this.currentTask) {
case SleeveTaskType.Class:
retValue = this.gainExperience(p, this.gainRatesForTask, cyclesUsed);
this.gainMoney(p, this.gainRatesForTask, cyclesUsed);
break;
case SleeveTaskType.Faction:
retValue = this.gainExperience(p, this.gainRatesForTask, cyclesUsed);
this.gainMoney(p, this.gainRatesForTask, cyclesUsed);
// TODO REP for both this and company
const fac = Factions[this.currentTaskLocation];
if (!(fac instanceof Faction)) {
console.error(`Invalid faction for Sleeve task: ${this.currentTaskLocation}`);
break;
}
break;
case SleeveTaskType.Company:
retValue = this.gainExperience(p, this.gainRatesForTask, cyclesUsed);
this.gainMoney(p, this.gainRatesForTask, cyclesUsed);
break;
case SleeveTaskType.Recovery:
this.shock = Math.max(100, this.shock + (0.001 * this.storedCycles));
break;
case SleeveTaskType.Sync:
this.sync = Math.max(100, this.sync + (0.001 * this.storedCycles));
break;
default:
break;
}
if (this.currentTaskMaxTime !== 0 && this.currentTaskTime >= this.currentTaskMaxTime) {
this.finishTask();
}
this.storedCycles -= cyclesUsed;
// TODO Finish this
return retValue;
}
/**
* Resets all parameters used to keep information about the current task
*/
resetTaskStatus(): void {
this.earningsForTask = createTaskTracker();
this.gainRatesForTask = createTaskTracker();
this.currentTask = SleeveTaskType.Idle;
this.currentTaskTime = 0;
this.currentTaskMaxTime = 0;
this.factionWorkType = FactionWorkType.None;
}
/**
* Take a course at a university
*/
takeUniversityCourse(p: IPlayer, universityName: string, className: string): boolean {
if (this.currentTask !== SleeveTaskType.Idle) {
this.finishTask();
} else {
this.resetTaskStatus();
}
// Set exp/money multipliers based on which university.
// Also check that the sleeve is in the right city
let costMult: number = 1;
let expMult: number = 1;
switch (universityName.toLowerCase()) {
case Locations.AevumSummitUniversity.toLowerCase():
if (this.city !== Cities.Aevum) { return false; }
costMult = 4;
expMult = 3;
break;
case Locations.Sector12RothmanUniversity.toLowerCase():
if (this.city !== Cities.Sector12) { return false; }
costMult = 3;
expMult = 2;
break;
case Locations.VolhavenZBInstituteOfTechnology.toLowerCase():
if (this.city !== Cities.Volhaven) { return false; }
costMult = 5;
expMult = 4;
break;
default:
return false;
}
// Number of game cycles in a second
const cps: number = 1000 / CONSTANTS.MilliPerCycle;
// Set experience/money gains based on class
// TODO Refactor University Courses into its own class or something
const baseStudyComputerScienceExp: number = 0.5;
const baseDataStructuresExp: number = 1;
const baseNetworksExp: number = 2;
const baseAlgorithmsExp: number = 4;
const baseManagementExp: number = 2;
const baseLeadershipExp: number = 4;
switch (className.toLowerCase()) {
case "study computer science":
this.gainRatesForTask.hack = (baseStudyComputerScienceExp * expMult * this.hacking_exp_mult);
break;
case "data structures":
this.gainRatesForTask.hack = (baseDataStructuresExp * expMult * this.hacking_exp_mult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassDataStructuresBaseCost * costMult);
break;
case "networks":
this.gainRatesForTask.hack = (baseNetworksExp * expMult * this.hacking_exp_mult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassNetworksBaseCost * costMult);
break;
case "algorithms":
this.gainRatesForTask.hack = (baseAlgorithmsExp * expMult * this.hacking_exp_mult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassAlgorithmsBaseCost * costMult);
break;
case "management":
this.gainRatesForTask.cha = (baseManagementExp * expMult * this.charisma_exp_mult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassManagementBaseCost * costMult);
break;
case "leadership":
this.gainRatesForTask.cha = (baseLeadershipExp * expMult * this.charisma_exp_mult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassLeadershipBaseCost * costMult);
break;
default:
return false;
}
this.currentTask = SleeveTaskType.Class;
return true;
}
/**
* Travel to another City. Costs money from player
*/
travel(p: IPlayer, newCity: string): boolean {
if (Cities[newCity] == null) {
console.error(`Invalid city ${newCity} passed into Sleeve.travel()`);
return false;
}
p.loseMoney(CONSTANTS.TravelCost);
this.city = newCity;
return true;
}
/**
* Work for a company
*/
workForCompany(p: IPlayer): boolean {
return true;
}
/**
* Work for one of the player's factions
*/
workForFaction(p: IPlayer, factionName: string, workType: string): boolean {
if (!(Factions[factionName] instanceof Faction) || !p.factions.includes(factionName)) {
return false;
}
if (this.currentTask !== SleeveTaskType.Idle) {
this.finishTask();
} else {
this.resetTaskStatus();
}
// Set type of work (hacking/field/security), and the experience gains
const sanitizedWorkType: string = workType.toLowerCase();
if (sanitizedWorkType.includes("hack")) {
this.factionWorkType = FactionWorkType.Hacking;
this.gainRatesForTask.hack = .15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
} else if (sanitizedWorkType.includes("field")) {
this.factionWorkType = FactionWorkType.Field;
this.gainRatesForTask.hack = .1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.str = .1 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.def = .1 * this.defense_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.dex = .1 * this.dexterity_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.agi = .1 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.cha = .1 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
} else if (sanitizedWorkType.includes("security")) {
this.factionWorkType = FactionWorkType.Security;
this.gainRatesForTask.hack = .1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.str = .15 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.def = .15 * this.defense_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.dex = .15 * this.dexterity_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.agi = .15 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
} else {
return false;
}
this.currentTaskLocation = factionName;
this.currentTask = SleeveTaskType.Faction;
return true;
}
/**
* Begin a gym workout task
*/
workoutAtGym(p: IPlayer, gymName: string, stat: string): boolean {
if (this.currentTask !== SleeveTaskType.Idle) {
this.finishTask();
} else {
this.resetTaskStatus();
}
// Set exp/money multipliers based on which university.
// Also check that the sleeve is in the right city
let costMult: number = 1;
let expMult: number = 1;
switch (gymName.toLowerCase()) {
case Locations.AevumCrushFitnessGym.toLowerCase():
if (this.city != Cities.Aevum) { return false; }
costMult = 3;
expMult = 2;
break;
case Locations.AevumSnapFitnessGym.toLowerCase():
if (this.city != Cities.Aevum) { return false; }
costMult = 10;
expMult = 5;
break;
case Locations.Sector12IronGym.toLowerCase():
if (this.city != Cities.Sector12) { return false; }
costMult = 1;
expMult = 1;
break;
case Locations.Sector12PowerhouseGym.toLowerCase():
if (this.city != Cities.Sector12) { return false; }
costMult = 20;
expMult = 10;
break;
case Locations.VolhavenMilleniumFitnessGym:
if (this.city != Cities.Volhaven) { return false; }
costMult = 7;
expMult = 4;
break;
default:
return false;
}
// Number of game cycles in a second
const cps = 1000 / CONSTANTS.MilliPerCycle;
// Set experience/money gains based on class
// TODO Refactor University Courses into its own class or something
const baseGymExp: number = 1;
const sanitizedStat: string = stat.toLowerCase();
// Set cost
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassGymBaseCost * costMult);
// Set stat gain rate
if (sanitizedStat.includes("str")) {
this.gainRatesForTask.str = (baseGymExp * expMult);
} else if (sanitizedStat.includes("def")) {
this.gainRatesForTask.def = (baseGymExp * expMult);
} else if (sanitizedStat.includes("dex")) {
this.gainRatesForTask.dex = (baseGymExp * expMult);
} else if (sanitizedStat.includes("agi")) {
this.gainRatesForTask.agi = (baseGymExp * expMult);
} else {
return false;
}
this.currentTask = SleeveTaskType.Class;
return true;
}
/**
* Serialize the current object to a JSON save state.
*/
toJSON(): any {
return Generic_toJSON("Sleeve", this);
}
}
Reviver.constructors.Sleeve = Sleeve;

@ -0,0 +1,12 @@
/**
* Enum for different types of tasks that a Sleeve can perform
*/
export enum SleeveTaskType {
Class,
Company,
Crime,
Faction,
Idle,
Recovery,
Sync,
}

@ -14,8 +14,9 @@ import {Corporation} from "./CompanyManagement";
import {Programs} from "./CreateProgram"; import {Programs} from "./CreateProgram";
import {determineCrimeSuccess, Crimes} from "./Crimes"; import {determineCrimeSuccess, Crimes} from "./Crimes";
import {Engine} from "./engine"; import {Engine} from "./engine";
import {Factions, Faction, import { Faction } from "./Faction/Faction";
displayFactionContent} from "./Faction"; import { Factions } from "./Faction/Factions";
import { displayFactionContent } from "./Faction/FactionHelpers";
import {Gang, resetGangs} from "./Gang"; import {Gang, resetGangs} from "./Gang";
import {Locations} from "./Locations"; import {Locations} from "./Locations";
import {hasBn11SF, hasWallStreetSF,hasAISF} from "./NetscriptFunctions"; import {hasBn11SF, hasWallStreetSF,hasAISF} from "./NetscriptFunctions";
@ -41,10 +42,10 @@ function PlayerObject() {
//Combat stats //Combat stats
this.hp = 10; this.hp = 10;
this.max_hp = 10; this.max_hp = 10;
this.strength = 1; //Damage dealt this.strength = 1;
this.defense = 1; //Damage received this.defense = 1;
this.dexterity = 1; //Accuracy this.dexterity = 1;
this.agility = 1; //Dodge % this.agility = 1;
//Labor stats //Labor stats
this.charisma = 1; this.charisma = 1;
@ -594,7 +595,7 @@ PlayerObject.prototype.gainIntelligenceExp = function(exp) {
//Given a string expression like "str" or "strength", returns the given stat //Given a string expression like "str" or "strength", returns the given stat
PlayerObject.prototype.queryStatFromString = function(str) { PlayerObject.prototype.queryStatFromString = function(str) {
var tempStr = str.toLowerCase(); const tempStr = str.toLowerCase();
if (tempStr.includes("hack")) {return Player.hacking_skill;} if (tempStr.includes("hack")) {return Player.hacking_skill;}
if (tempStr.includes("str")) {return Player.strength;} if (tempStr.includes("str")) {return Player.strength;}
if (tempStr.includes("def")) {return Player.defense;} if (tempStr.includes("def")) {return Player.defense;}

@ -7,8 +7,10 @@ import {writeCinematicText} from "./CinematicText";
import {Companies, initCompanies} from "./Company/Companies"; import {Companies, initCompanies} from "./Company/Companies";
import {Programs} from "./CreateProgram"; import {Programs} from "./CreateProgram";
import {Engine} from "./engine"; import {Engine} from "./engine";
import {Factions, Faction, initFactions, import { Faction } from "./Faction/Faction";
joinFaction} from "./Faction"; import { Factions,
initFactions } from "./Faction/Factions";
import { joinFaction } from "./Faction/FactionHelpers";
import {deleteGangDisplayContent} from "./Gang"; import {deleteGangDisplayContent} from "./Gang";
import {Locations} from "./Location"; import {Locations} from "./Location";
import {initMessages, Messages, Message} from "./Message"; import {initMessages, Messages, Message} from "./Message";

@ -4,8 +4,9 @@ import {Companies, loadCompanies} from "./Company/Companies";
import {CompanyPosition} from "./Company/CompanyPosition"; import {CompanyPosition} from "./Company/CompanyPosition";
import {CONSTANTS} from "./Constants"; import {CONSTANTS} from "./Constants";
import {Engine} from "./engine"; import {Engine} from "./engine";
import {loadFactions, Factions, import { Factions,
processPassiveFactionRepGain} from "./Faction"; loadFactions } from "./Faction/Factions";
import { processPassiveFactionRepGain } from "./Faction/FactionHelpers";
import {FconfSettings, loadFconf} from "./Fconf"; import {FconfSettings, loadFconf} from "./Fconf";
import {loadAllGangs, AllGangs} from "./Gang"; import {loadAllGangs, AllGangs} from "./Gang";
import {processAllHacknetNodeEarnings} from "./HacknetNode"; import {processAllHacknetNodeEarnings} from "./HacknetNode";

@ -34,9 +34,10 @@ import {displayCreateProgramContent,
initCreateProgramButtons, initCreateProgramButtons,
Programs} from "./CreateProgram"; Programs} from "./CreateProgram";
import {createDevMenu, closeDevMenu} from "./DevMenu"; import {createDevMenu, closeDevMenu} from "./DevMenu";
import {displayFactionContent, joinFaction, import { Factions, initFactions } from "./Faction/Factions";
processPassiveFactionRepGain, Factions, import { displayFactionContent, joinFaction,
inviteToFaction, initFactions} from "./Faction"; processPassiveFactionRepGain,
inviteToFaction } from "./Faction/FactionHelpers";
import {FconfSettings} from "./Fconf"; import {FconfSettings} from "./Fconf";
import {displayLocationContent, import {displayLocationContent,
initLocationButtons} from "./Location"; initLocationButtons} from "./Location";

@ -1,4 +1,4 @@
import {joinFaction} from "../src/Faction"; import {joinFaction} from "../src/Faction/FactionHelpers";
import {Engine} from "../src/engine"; import {Engine} from "../src/engine";
import {Player} from "../src/Player"; import {Player} from "../src/Player";
import {clearEventListeners} from "./uiHelpers/clearEventListeners"; import {clearEventListeners} from "./uiHelpers/clearEventListeners";

@ -1,10 +1,11 @@
import {BitNodeMultipliers} from "../src/BitNodeMultipliers"; import { BitNodeMultipliers } from "../src/BitNodeMultipliers";
import {CONSTANTS} from "../src/Constants"; import { CONSTANTS } from "../src/Constants";
import {Factions, Faction} from "../src/Faction"; import { Faction } from "../src/Faction/Faction";
import {Player} from "../src/Player"; import { Factions } from "../src/Faction/Factions";
import {dialogBoxCreate} from "./DialogBox"; import { Player } from "../src/Player";
import {clearEventListeners} from "./uiHelpers/clearEventListeners"; import { dialogBoxCreate } from "./DialogBox";
import {formatNumber} from "./StringHelperFunctions"; import { clearEventListeners } from "./uiHelpers/clearEventListeners";
import { formatNumber } from "./StringHelperFunctions";
//Keep track of last faction //Keep track of last faction
var lastFac = ""; var lastFac = "";