StockMarket and Infiltration implementations

This commit is contained in:
Daniel Xie 2017-07-03 14:42:11 -05:00
parent c0fc4e381d
commit 36e3a3b5d2
19 changed files with 2037 additions and 305 deletions

@ -75,7 +75,7 @@
}
#script-editor-filename {
background-color: #555;
background-color: #555;
display: inline-block;
float: center;
resize: none;
@ -274,15 +274,9 @@ background-color: #555;
padding: 10px;
}
#hacknet-nodes-container li{
padding: 6px;
margin: 6px;
width: 70%;
}
#hacknet-nodes-text,
#hacknet-nodes-money {
#hacknet-nodes-money,
#hacknet-nodes-container li {
width: 70%;
margin: 10px;
padding: 10px;
@ -344,10 +338,7 @@ background-color: #555;
padding-top: 10px;
}
#create-program-page-text {
width: 70%;
}
#create-program-page-text,
#create-program-list {
width: 70%;
}
@ -510,6 +501,12 @@ div.faction-clear {
#location-container {
position: fixed;
padding: 6px;
overflow-x: hidden;
}
#location-container a {
display:inline-block;
width: 30%;
}
#location-slums-description {
@ -535,3 +532,66 @@ div.faction-clear {
position: fixed;
padding: 6px;
}
#infiltration-left-panel,
#infiltration-right-panel {
display:inline-block;
border: 1px solid white;
width: 35%;
height: 75%;
top: 10px;
overflow-y: auto;
overflow-x: auto;
}
#infiltration-faction-select {
color:white;
}
#infiltration-left-panel p,
#infiltration-right-panel p {
margin: 4px;
}
#infiltration-buttons .a-link-button {
display:inline;
width: 25%;
}
/* Stock market */
#stock-market-container {
position: fixed;
padding: 6px;
}
#stock-market-container p {
padding: 10px;
margin: 10px;
width: 70%;
}
#stock-market-container a {
margin: 10px;
}
.stock-market-qty-input {
border: 1px solid white;
color: var(--my-font-color);
padding: 4px;
margin: 4px;
}
.stock-market-buy-sell-button {
color: #aaa;
font-size: 16px;
font-weight: bold;
padding: 2px;
margin: 6px;
border: 1px solid white;
}
.stock-market-buy-sell-button:hover,
.stock-market-buy-sell-button:focus {
color: var(--my-font-color);
text-decoration: none;
cursor: pointer;
}

@ -5,14 +5,38 @@
z-index: 1; /* Sit on top */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
width: 100%;
height: 100%;
overflow: auto; /* Enable scroll if needed */
/*background-color: black; /* Fallback color */
/*background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
background-color: rbga(var(--my-background-color), 0.4);
}
.popup-box-content {
background-color: var(--my-background-color);
margin: 15% auto;
padding: 12px;
border: 5px solid var(--my-highlight-color);
width: 70%;
color: var(--my-font-color);
}
.popup-box-button {
color: #aaa;
float: right;
font-size: 16px;
font-weight: bold;
padding: 2px;
margin: 6px;
border: 1px solid white;
}
.popup-box-button:hover,
.popup-box-button:focus {
color: var(--my-font-color);
text-decoration: none;
cursor: pointer;
}
.dialog-box-container,
#log-box-container {
display: block;
@ -69,207 +93,45 @@
transition: opacity 400ms ease-in;
}
#purchase-server-box-content {
background-color: var(--my-background-color);
margin: 15% auto; /* 15% from the top and centered */
padding: 12px;
border: 5px solid var(--my-highlight-color);;
width: 80%; /* Could be more or less, depending on screen size */
color: var(--my-font-color);
}
#purchase-server-box-input {
color: white;
}
#purchase-server-box-confirm,
#purchase-server-box-cancel {
color: #aaa;
float: right;
font-size: 16px;
font-weight: bold;
padding: 2px;
margin: 6px;
border: 1px solid white;
}
#purchase-server-box-confirm:hover,
#purchase-server-box-confirm:focus {
color: var(--my-font-color);
text-decoration: none;
cursor: pointer;
}
#purchase-server-box-cancel:hover,
#purchase-server-box-cancel:focus {
color: var(--my-font-color);
text-decoration: none;
cursor: pointer;
}
/* Purchase RAM for Home computer pop-up box */
#purchase-ram-for-home-box-container {
transition: opacity 400ms ease-in;
}
#purchase-ram-for-home-box-content {
background-color: var(--my-background-color);
margin: 15% auto; /* 15% from the top and centered */
padding: 12px;
border: 5px solid var(--my-highlight-color);
width: 50%; /* Could be more or less, depending on screen size */
color: var(--my-font-color);
}
#purchase-ram-for-home-box-confirm,
#purchase-ram-for-home-box-cancel {
color: #aaa;
float: right;
font-size: 16px;
font-weight: bold;
padding: 2px;
margin: 6px;
border: 1px solid white;
}
#purchase-ram-for-home-box-confirm:hover,
#purchase-ram-for-home-box-confirm:focus {
color: var(--my-font-color);
text-decoration: none;
cursor: pointer;
}
#purchase-ram-for-home-box-cancel:hover,
#purchase-ram-for-home-box-cancel:focus {
color: var(--my-font-color);
text-decoration: none;
cursor: pointer;
}
/* Purchase Invitation Box */
#purchase-augmentation-box-container {
transition: opacity 400ms ease-in;
}
#purchase-augmentation-box-content {
background-color: var(--my-background-color);
margin: 15% auto; /* 15% from the top and centered */
padding: 8px;
border: 5px solid var(--my-highlight-color);;
width: 80%; /* Could be more or less, depending on screen size */
color: var(--my-font-color);
}
#purchase-augmentation-box-confirm,
#purchase-augmentation-box-cancel {
color: #aaa;
float: right;
font-size: 16px;
font-weight: bold;
padding: 4px;
margin: 6px;
border: 1px solid white;
}
#purchase-augmentation-box-confirm:hover,
#purchase-augmentation-box-confirm:focus {
color: var(--my-font-color);
text-decoration: none;
cursor: pointer;
}
#purchase-augmentation-box-cancel:hover,
#purchase-augmentation-box-cancel:focus {
color: var(--my-font-color);
text-decoration: none;
cursor: pointer;
}
/* Faction invitation box */
#faction-invitation-box-container {
transition: opacity 400ms ease-in;
}
#faction-invitation-box-content {
background-color: var(--my-background-color);
margin: 15% auto; /* 15% from the top and centered */
padding: 10px;
border: 5px solid var(--my-highlight-color);;
width: 80%; /* Could be more or less, depending on screen size */
color: var(--my-font-color);
}
#faction-invitation-box-warning {
margin: 4px;
padding: 4px;
}
#faction-invitation-box-yes,
#faction-invitation-box-no {
color: #aaa;
font-size: 20px;
font-weight: bold;
padding: 2px;
margin: 6px;
border: 1px solid white;
}
#faction-invitation-box-yes:hover,
#faction-invitation-box-yes:focus {
color: white;
text-decoration: none;
cursor: pointer;
}
#faction-invitation-box-no:hover,
#faction-invitation-box-no:focus {
color: white;
text-decoration: none;
cursor: pointer;
}
/* Travel Pop-up Box */
#travel-box-container {
transition: opacity 400ms ease-in;
}
#travel-box-content {
background-color: var(--my-background-color);
margin: 15% auto; /* 15% from the top and centered */
padding: 10px;
border: 5px solid var(--my-highlight-color);;
width: 50%; /* Could be more or less, depending on screen size */
color: var(--my-font-color);
}
#travel-box-text {
margin: 8px;
}
#travel-box-confirm,
#travel-box-cancel {
color: #aaa;
float: right;
font-size: 16px;
font-weight: bold;
padding: 2px;
margin: 6px;
border: 1px solid white;
}
#travel-box-confirm:hover,
#travel-box-confirm:focus {
color: white;
text-decoration: none;
cursor: pointer;
}
#travel-box-cancel:hover,
#travel-box-cancel:focus {
color: white;
text-decoration: none;
cursor: pointer;
/* Infiltration-box */
#infiltration-box-sell,
#infiltration-box-faction {
display: block;
padding: 8px;
margin: 8px;
}
/* Game Options */

@ -32,7 +32,7 @@ h2 {
}
ul {
padding: 6px;
padding: 2px;
list-style-type: none;
}
@ -252,7 +252,7 @@ tr:focus {
position: absolute; /* Stay in place */
right: 0;
top: 0;
height: 185px; /* Full height */
height: 195px; /* Full height */
/*margin: 50% auto;*/
padding: 5px;
border: 2px solid var(--my-highlight-color);
@ -264,7 +264,7 @@ tr:focus {
#character-overview-text {
padding: 4px;
margin: 10px;
margin: 8px;
color: white;
background-color: #444;
}
@ -272,7 +272,7 @@ tr:focus {
#character-overview-save-button,
#character-overview-options-button {
color: #aaa;
font-size: 16px;
font-size: 14px;
font-weight: bold;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;

@ -26,6 +26,7 @@
<script src="utils/PurchaseRamForHomeBox.js"></script>
<script src="utils/GameOptions.js"></script>
<script src="utils/LogBox.js"></script>
<script src="utils/InfiltrationBox.js"></script>
<!-- Netscript -->
<script src="src/NetscriptWorker.js"></script>
@ -61,6 +62,8 @@
<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/engine.js"></script>
@ -115,7 +118,7 @@
</li>
<li class="augmentations-tab">
<a id="augmentations-menu-link"> Augmentations </a>
<a id="augmentations-menu-link" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"> Augmentations </a>
</li>
<li class="tutorial-tab">
@ -212,6 +215,9 @@
<li id="aevum-travelagency-li">
<a id="aevum-travelagency" class="a-link-button"> Travel Agency </a>
</li>
<li id="aevum-hospital-li">
<a id="aevum-hospital" class="a-link-button">Hospital</a>
</li>
<li id="aevum-summituniversity-li">
<a id="aevum-summituniversity" class="a-link-button"> Summit University </a>
</li>
@ -260,6 +266,9 @@
<li id="chongqing-travelagency-li">
<a id="chongqing-travelagency" class="a-link-button"> Travel Agency </a>
</li>
<li id="chongqing-hospital-li">
<a id="chongqing-hospital" class="a-link-button">Hospital</a>
</li>
<li id="chonqging-kuaigonginternational-li">
<a id="chongqing-kuaigonginternational" class="a-link-button">KuaiGong International </a>
</li>
@ -275,6 +284,9 @@
<li id="sector12-travelagency-li">
<a id="sector12-travelagency" class="a-link-button">Travel Agency </a>
</li>
<li id="sector12-hospital-li">
<a id="sector12-hospital" class="a-link-button">Hospital</a>
</li>
<li id="sector12-rothmanuniversity-li">
<a id="sector12-rothmanuniversity" class="a-link-button"> Rothman University</a>
</li>
@ -329,6 +341,9 @@
<li id="newtokyo-travelagency-li">
<a id="newtokyo-travelagency" class="a-link-button"> Travel Agency</a>
</li>
<li id="newtokyo-hospital-li">
<a id="newtokyo-hospital" class="a-link-button">Hospital</a>
</li>
<li id="newtokyo-defcomm-li">
<a id="newtokyo-defcomm" class="a-link-button"> DefComm</a>
</li>
@ -350,6 +365,9 @@
<li id="ishima-travelagency-li">
<a id="ishima-travelagency" class="a-link-button">Travel Agency </a>
</li>
<li id="ishima-hospital-li">
<a id="ishima-hospital" class="a-link-button">Hospital</a>
</li>
<li id="ishima-stormtechnologies-li">
<a id="ishima-stormtechnologies" class="a-link-button">Storm Technologies</a>
</li>
@ -368,6 +386,9 @@
<li id="volhaven-travelagency-li">
<a id="volhaven-travelagency" class="a-link-button">Travel Agency </a>
</li>
<li id="volhaven-hospital-li">
<a id="volhaven-hospital" class="a-link-button">Hospital</a>
</li>
<li id="volhaven-zbinstituteoftechnology-li">
<a id="volhaven-zbinstituteoftechnology" class="a-link-button">ZB Insitute of Technology</a>
</li>
@ -399,6 +420,12 @@
<a id="volhaven-slums" class="a-link-button">The Slums</a>
</li>
</ul>
<ul id="generic-locations-list">
<li id="generic-location-wse-li">
<a id="generic-location-wse" class="a-link-button">World Stock Exchange </a>
</li>
</ul>
</div>
<!-- Create a program(executable) -->
@ -559,7 +586,8 @@
Scripts on every computer but your home computer<br>
Purchased servers <br>
Hacknet Nodes <br>
Faction/Company reputation <br><br>
Faction/Company reputation <br>
Stocks<br><br>
Purchasing an Augmentation lets you start over with the perks and benefits granted by all
of the Augmentations you have ever purchased. Also, you will keep any scripts and RAM upgrades
on your home computer (but you will lose all programs besides NUKE.exe).
@ -583,7 +611,7 @@
<a id="tutorial-scripts-link" class="a-link-button"> Scripts </a>
<a id="tutorial-netscript-link" class="a-link-button"> Netscript Programming Language </a>
<a id="tutorial-traveling-link" class="a-link-button"> Traveling </a>
<a id="tutorial-jobs-link" class="a-link-button"> Jobs </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-augmentations-link" class="a-link-button"> Augmentations </a>
@ -649,6 +677,17 @@
<a id="location-purchase-tor" class="a-link-button"> Purchase TOR Router - $100,000</a>
<a id="location-purchase-home-ram" class="a-link-button"> Purchase additional RAM for Home computer </a>
<!-- Infiltrate -->
<a id="location-infiltrate" class="a-link-button tooltip"> Infiltrate Company
<span class="tooltiptext">
Infiltrate this company's facility to try and steal their classified secrets!
Warning: You may end up hospitalized if you are unsuccessful!
</span>
</a>
<!-- Hospital -->
<a id="location-hospital-treatment" class="a-link-button"> Get Treatment for Wounds </a>
<!-- Travel agency -->
<p id="location-travel-agency-text">
From here, you can travel to any other city! A ticket costs $200,000.
@ -700,6 +739,35 @@
</div>
</div>
<div id="stock-market-container" class="generic-menupage-container">
<p>
Welcome to the World Stock Exchange (WSE)! <br><br>
To begin trading, you must first purchase an account. WSE accounts will persist
after you 'reset' by installing Augmentations.
</p>
<a id="stock-market-buy-account" class="a-link-button-inactive"> Buy WSE Account </a>
<p>
You can also purchase access to the World Stock Exchange's TIX API! TIX, short for
Trade Information eXchange, is the communications protocol supported by the WSE.
<br><br>
Gaining access to the TIX API lets you write code to build automated trading
systems. In other words, you can create your own algorithmic trading strategies!
<br><br>
If you purchase access to the TIX API, you will retain that access even after
you 'reset' by installing Augmentations.
</p>
<a id="stock-market-buy-tix-api" class="a-link-button-inactive">
Buy Trade Information eXchange (TEX) API Access - COMING SOON
</a>
<p id="stock-market-commission"> </p>
<ul id="stock-market-list" style="list-style:none;">
</ul>
</div>
<!-- Log Box -->
<div id="log-box-container">
<div id="log-box-content">
@ -710,55 +778,67 @@
<!-- Purchase Server Pop-up Box -->
<div id="purchase-server-box-container" class="popup-box-container">
<div id="purchase-server-box-content">
<div id="purchase-server-box-content" class="popup-box-content">
<p id="purchase-server-box-text"> </p>
<p id="purchase-server-box-enter-name"> Enter new server hostname: </p>
<input type="text" id="purchase-server-box-input" pattern="[a-zA-Z0-9-_]+ maxlength="30"> </input>
<span id="purchase-server-box-confirm"> Purchase </span>
<span id="purchase-server-box-cancel"> Cancel </span>
<span id="purchase-server-box-confirm" class="popup-box-button"> Purchase </span>
<span id="purchase-server-box-cancel" class="popup-box-button"> Cancel </span>
</div>
</div>
<!-- Purchase RAM for Home Computer Pop-up Box -->
<div id="purchase-ram-for-home-box-container" class="popup-box-container">
<div id="purchase-ram-for-home-box-content">
<div id="purchase-ram-for-home-box-content" class="popup-box-content">
<p id="purchase-ram-for-home-box-text"> </p>
<span id="purchase-ram-for-home-box-confirm"> Purchase </span>
<span id="purchase-ram-for-home-box-cancel"> Cancel </span>
<span id="purchase-ram-for-home-box-confirm" class="popup-box-button"> Purchase </span>
<span id="purchase-ram-for-home-box-cancel" class="popup-box-button"> Cancel </span>
</div>
</div>
<!-- Travel Pop-up Box -->
<div id="travel-box-container" class="popup-box-container">
<div id="travel-box-content">
<div id="travel-box-content" class="popup-box-content">
<p id="travel-box-text"> </p>
<span id="travel-box-confirm"> Yes </span>
<span id="travel-box-cancel"> No </span>
<span id="travel-box-confirm" class="popup-box-button"> Yes </span>
<span id="travel-box-cancel" class="popup-box-button"> No </span>
</div>
</div>
<!-- Purchase Augmentation Pop-up Box -->
<div id="purchase-augmentation-box-container" class="popup-box-container">
<div id="purchase-augmentation-box-content">
<div id="purchase-augmentation-box-content" class="popup-box-content">
<h2 id="purchase-augmentation-box-aug-name"> </h2>
<p id="purchase-augmentation-box-aug-info"> </p>
<p id="purchase-augmentation-box-text"> </p>
<span id="purchase-augmentation-box-confirm"> Purchase </span>
<span id="purchase-augmentation-box-cancel"> Cancel </span>
<span id="purchase-augmentation-box-confirm" class="popup-box-button"> Purchase </span>
<span id="purchase-augmentation-box-cancel" class="popup-box-button"> Cancel </span>
</div>
</div>
<!-- Faction Invitation Pop-up Box -->
<div id="faction-invitation-box-container" class="popup-box-container">
<div id="faction-invitation-box-content">
<div id="faction-invitation-box-content" class="popup-box-content">
<p id="faction-invitation-box-text"> </p>
<p id="faction-invitation-box-message"> </p>
<p id="faction-invitation-box-warning">
Would you like to join? <br> <br>
Warning: Joining this faction may prevent you from joining other factions during this run!
</p>
<span id="faction-invitation-box-yes"> Yes </span>
<span id="faction-invitation-box-no"> No </span>
<span id="faction-invitation-box-yes" class="popup-box-button"> Yes </span>
<span id="faction-invitation-box-no" class="popup-box-button"> No </span>
</div>
</div>
<!-- End of Infiltration pop up box -->
<div id="infiltration-box-container" class="popup-box-container">
<div id="infiltration-box-content" class="popup-box-content">
<p id="infiltration-box-text"> </p>
<span id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </span> <br><br>
<select id="infiltration-faction-select"> </select> <br>
<span id="infiltration-box-faction" class="a-link-button"> Give to Faction for Reputation </span>
</div>
</div>

@ -246,7 +246,7 @@ initAugmentations = function() {
var CombatRib2 = new Augmentation(AugmentationNames.CombatRib2);
CombatRib2.setRequirements(7000, 12000000);
CombatRib2.setInfo("This is an upgrade to the Combat Rib I augmentation, and is capable of releasing even more potent combat-enhancing " +
"drugs into the bloodstream<br><br>. This upgrade increases the player's strength and defense by an additional 15%.")
"drugs into the bloodstream.<br><br>This upgrade increases the player's strength and defense by an additional 15%.")
CombatRib2.addToFactions(["The Dark Army", "The Syndicate", "Sector-12", "Volhaven", "Ishima",
"OmniTek Incorporated", "KuaiGong International", "Blade Industries"]);
if (augmentationExists(AugmentationNames.CombatRib2)) {

@ -665,7 +665,8 @@ initCompanies = function() {
CompanyPositions.ITAnalyst, CompanyPositions.ITManager, CompanyPositions.SysAdmin,
CompanyPositions.SecurityEngineer, CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator,
CompanyPositions.HeadOfSoftware, CompanyPositions.HeadOfEngineering,
CompanyPositions.VicePresident, CompanyPositions.CTO, CompanyPositions.BusinessAnalyst,
CompanyPositions.VicePresident, CompanyPositions.CTO,
CompanyPositions.BusinessIntern, CompanyPositions.BusinessAnalyst,
CompanyPositions.BusinessManager, CompanyPositions.OperationsManager, CompanyPositions.CFO,
CompanyPositions.CEO]);
if (companyExists(Locations.IshimaStormTechnologies)) {
@ -681,7 +682,7 @@ initCompanies = function() {
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.CFO, CompanyPositions.CEO]);
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.CEO]);
if (companyExists(Locations.NewTokyoDefComm)) {
DefComm.favor = Companies[Locations.NewTokyoDefComm].favor;
delete Companies[Locations.NewTokyoDefComm];
@ -695,7 +696,7 @@ initCompanies = function() {
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.CFO, CompanyPositions.CEO]);
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.CEO]);
if (companyExists(Locations.VolhavenHeliosLabs)) {
HeliosLabs.favor = Companies[Locations.VolhavenHeliosLabs].favor;
delete Companies[Locations.VolhavenHeliosLabs];
@ -709,7 +710,8 @@ initCompanies = function() {
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.BusinessManager,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO,
CompanyPositions.BusinessIntern, CompanyPositions.BusinessAnalyst, CompanyPositions.BusinessManager,
CompanyPositions.OperationsManager, CompanyPositions.CFO, CompanyPositions.CEO]);
if (companyExists(Locations.NewTokyoVitaLife)) {
VitaLife.favor = Companies[Locations.NewTokyoVitaLife].favor;
@ -724,7 +726,8 @@ initCompanies = function() {
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.BusinessManager,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO,
CompanyPositions.BusinessIntern, CompanyPositions.BusinessAnalyst, CompanyPositions.BusinessManager,
CompanyPositions.OperationsManager, CompanyPositions.CFO, CompanyPositions.CEO]);
if (companyExists(Locations.Sector12IcarusMicrosystems)) {
IcarusMicrosystems.favor = Companies[Locations.Sector12IcarusMicrosystems].favor;
@ -739,7 +742,8 @@ initCompanies = function() {
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.BusinessManager,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO,
CompanyPositions.BusinessIntern, CompanyPositions.BusinessAnalyst, CompanyPositions.BusinessManager,
CompanyPositions.OperationsManager, CompanyPositions.CFO, CompanyPositions.CEO]);
if (companyExists(Locations.Sector12UniversalEnergy)) {
UniversalEnergy.favor = Companies[Locations.Sector12UniversalEnergy].favor;
@ -754,7 +758,8 @@ initCompanies = function() {
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.BusinessManager,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO,
CompanyPositions.BusinessIntern, CompanyPositions.BusinessAnalyst, CompanyPositions.BusinessManager,
CompanyPositions.OperationsManager, CompanyPositions.CFO, CompanyPositions.CEO]);
if (companyExists(Locations.AevumGalacticCybersystems)) {
GalacticCybersystems.favor = Companies[Locations.AevumGalacticCybersystems].favor;
@ -770,7 +775,7 @@ initCompanies = function() {
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO,
CompanyPositions.OperationsManager, CompanyPositions.CFO, CompanyPositions.CEO,
CompanyPositions.OperationsManager, CompanyPositions.CEO,
CompanyPositions.SecurityGuard, CompanyPositions.SecurityOfficer, CompanyPositions.SecuritySupervisor,
CompanyPositions.HeadOfSecurity]);
if (companyExists(Locations.AevumAeroCorp)) {
@ -786,7 +791,7 @@ initCompanies = function() {
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO,
CompanyPositions.OperationsManager, CompanyPositions.CFO, CompanyPositions.CEO,
CompanyPositions.OperationsManager, CompanyPositions.CEO,
CompanyPositions.SecurityGuard, CompanyPositions.SecurityOfficer, CompanyPositions.SecuritySupervisor,
CompanyPositions.HeadOfSecurity]);
if (companyExists(Locations.VolhavenOmniaCybersystems)) {
@ -802,7 +807,7 @@ initCompanies = function() {
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO,
CompanyPositions.OperationsManager, CompanyPositions.CFO, CompanyPositions.CEO,
CompanyPositions.OperationsManager, CompanyPositions.CEO,
CompanyPositions.SecurityGuard, CompanyPositions.SecurityOfficer, CompanyPositions.SecuritySupervisor,
CompanyPositions.HeadOfSecurity]);
if (companyExists(Locations.ChongqingSolarisSpaceSystems)) {
@ -818,7 +823,7 @@ initCompanies = function() {
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO,
CompanyPositions.OperationsManager, CompanyPositions.CFO, CompanyPositions.CEO,
CompanyPositions.OperationsManager, CompanyPositions.CEO,
CompanyPositions.SecurityGuard, CompanyPositions.SecurityOfficer, CompanyPositions.SecuritySupervisor,
CompanyPositions.HeadOfSecurity]);
if (companyExists(Locations.Sector12DeltaOne)) {

@ -127,7 +127,7 @@ PlayerObject.prototype.applyForSecurityEngineerJob = function() {
if (this.isQualified(company, CompanyPositions.SecurityEngineer)) {
this.companyName = company.companyName;
this.companyPosition = CompanyPositions.SecurityEngineer;
dialogBoxCreate("Congratulations, you were offered a position at ", this.companyName, " as a Security Engineer!");
dialogBoxCreate("Congratulations, you were offered a position at " + this.companyName + " as a Security Engineer!");
Engine.loadLocationContent();
} else {
dialogBoxCreate("Unforunately, you do not qualify for this position");

@ -1,5 +1,5 @@
CONSTANTS = {
Version: "0.23.1",
Version: "0.24.0",
//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
@ -38,7 +38,7 @@ CONSTANTS = {
/* Script related things */
//Time (ms) it takes to run one operation in Netscript.
CodeInstructionRunTime: 200,
CodeInstructionRunTime: 100,
//RAM Costs for different commands
ScriptWhileRamCost: 0.2,
@ -82,8 +82,8 @@ CONSTANTS = {
//Augmentation Constants
AugmentationCostMultiplier: 5, //Used for balancing costs without having to readjust every Augmentation cost
AugmentationRepMultiplier: 1.75, //Used for balancing rep cost without having to readjust every value
MultipleAugMultiplier: 1.75,
AugmentationRepMultiplier: 2.5, //Used for balancing rep cost without having to readjust every value
MultipleAugMultiplier: 1.9,
//Maximum number of log entries for a script
MaxLogCapacity: 50,
@ -93,9 +93,15 @@ CONSTANTS = {
//Infiltration constants
InfiltrationBribeBaseAmount: 100000, //Amount per clearance level
InfiltrationMoneyValue: 2000, //Convert "secret" value to money
//Stock market constants
WSEAccountCost: 50000000,
TIXAPICost: 1000000000,
StockMarketCommission: 100000,
HospitalCostPerHp: 25000,
//Hospital/Health
HospitalCostPerHp: 75000,
MillisecondsPer20Hours: 72000000,
GameCyclesPer20Hours: 72000000 / 200,
@ -606,7 +612,7 @@ CONSTANTS = {
"From the travel agency you can travel to any other city. Doing so costs money. <br><br>" +
"Each city has its own set of companies and unique locations. Also, certain content is only available to you " +
"if you are in certain cities, so get exploring!",
TutorialJobsText: "Hacking is not the only way to gain money and experience! Located around the world are many " +
TutorialCompaniesText: "Hacking is not the only way to gain money and experience! Located around the world are many " +
"different companies which you can work for. By working for a company you can earn money, " +
"train your various labor skills, and unlock powerful passive perks. <br><br> " +
"To apply for a job, visit the company you want to work for through the 'World' menu. The company " +
@ -627,7 +633,26 @@ CONSTANTS = {
" be penalized if you cancel a work shift early. However, these positions pay less than full-time positions.<br><br>" +
"As you continue to work at a company, you will gain more and more reputation at that company. When your stats " +
"and reputation are high enough, you can get a promotion. You can apply for a promotion on the company page, just like " +
"you applied for the job originally. Higher positions at a company provide better salaries and stat gains.",
"you applied for the job originally. Higher positions at a company provide better salaries and stat gains.<br><br>" +
"<h1>Infiltrating Companies</h1><br>" +
"Many companies have facilities that you can attempt to infiltrate. By infiltrating, you can steal classified company secrets " +
"and then sell these for money or for faction reputation. To try and infiltrate a company, visit a company through the " +
"'World' menu. There will be an option that says 'Infiltrate Company'. <br><br>" +
"When infiltrating a company, you must progress through clearance levels in the facility. Every clearance level " +
"has some form of security that you must get past. There are several forms of security, ranging from high-tech security systems to " +
"armed guards. For each form of security, there are a variety of options that you can choose to try and bypass the security. Examples " +
"include hacking the security, engaging in combat, assassination, or sneaking past the security. The chance to succeed for each option " +
"is determined in part by your stats. So, for example, trying to hack the security system relies on your hacking skill, whereas trying to " +
"sneak past the security relies on your agility level.<br><br>" +
"The facility has a 'security level' that affects your chance of success when trying to get past a clearance level. " +
"Every time you advance to the next clearance level, the facility's security level will increase by a fixed amount. Furthermore " +
"the options you choose and whether you succeed or fail will affect the security level as well. For example, " +
"if you try to kill a security guard and fail, the security level will increase by a lot. If you choose to sneak past " +
"security and succeed, the security level will not increase at all. <br><br>" +
"Every 5 clearance levels, you will steal classified company secrets that can be sold for money or faction reputation. However, " +
"in order to sell these secrets you must successfully escape the facility using the 'Escape' option. Furthermore, companies have " +
"a max clearance level. If you reach the max clearance level you will automatically escape the facility with all of your " +
"stolen secrets.<br><br>",
TutorialFactionsText: "Throughout the game you may receive invitations from factions. There are many different factions, and each faction " +
"has different criteria for determining its potential members. Joining a faction and furthering its cause is crucial " +
"to progressing in the game and unlocking endgame content. <br><br> " +
@ -668,6 +693,22 @@ CONSTANTS = {
"RAM Upgrades on your home computer",
Changelog:
"v0.24.0<br>" +
"-Players now have HP, which is displayed in the top right. To regain HP, visit the hospital. Currently " +
"the only way to lose HP is through infiltration<br>" +
"-Infiltration - Attempt to infiltrate a company and steal their classified secrets. See 'Companies' documentation for more details<br>" +
"-Stock Market - Added the World Stock Exchange (WSE), a brokerage that lets you buy/sell stocks. To begin trading you must first purchase " +
"an account. A WSE account will persist even after resetting by installing Augmentations. How the stock market works should hopefully be " +
"self explanatory. There is no documentation about it currently, I will add some later. NOTE: Stock prices only change when the game is open. " +
"The Stock Market is reset when installing Augmentations, which means you will lose all your stocks<br>" +
"-Decreased money gained from hacking by ~12%<br>" +
"-Increased reputation required for all Augmentations by ~40%<br>" +
"-Cost increase when purchasing multiple augmentations increased from 75% to 90%<br>" +
"-Added basic variable runtime to Netscript operations. Basic commands run in 100ms. Any function incurs another 100ms in runtime (200ms total). " +
"Any function that starts with getServer incurs another 100ms runtime (300ms total). exec() and scp() require 400ms total. <br>" +
"-Slightly reduced the amount of experience gained from hacking<br><br>" +
"v0.23.1<br>" +
"-scan() Netscript function now takes a single argument representing the server from which to scan. <br><br>" +
"v0.23.0<br>" +
"-You can now purchase multiple Augmentations in a run. When you purchase an Augmentation you will lose money equal to the price " +
"and then the cost of purchasing another Augmentation during this run will be increased by 75%. You do not gain the benefits " +
@ -860,19 +901,18 @@ CONSTANTS = {
"-You can now see what an Augmentation does and its price even while its locked<br><br>",
LatestUpdate:
"v0.23.1<br>" +
"-scan() Netscript function now takes a single argument representing the server from which to scan. <br><br>" +
"v0.23.0<br>" +
"-You can now purchase multiple Augmentations in a run. When you purchase an Augmentation you will lose money equal to the price " +
"and then the cost of purchasing another Augmentation during this run will be increased by 75%. You do not gain the benefits " +
"of your purchased Augmentations until you install them. This installation can be done through the 'Augmentation' tab. When " +
"you install your Augmentations, your game will reset like before. <br>" +
"-Reputation needed to gain a favor from faction decreased from 7500 to 6500<br>" +
"-Reputation needed to gain a favor from company increased from 5000 to 6000<br>" +
"-Reputation cost of all Augmentations increased by 16%<br>" +
"-Higher positions at companies now grant slightly more reputation for working<br>" +
"-Added getServerMaxMoney() Netscript function<br>" +
"-Added scan() Netscript function<br>" +
"-Added getServerNumPortsRequired() Netscript function<br>" +
"-There is now no additional RAM cost incurred when multithreading a script<br><br>",
"v0.24.0<br>" +
"-Players now have HP, which is displayed in the top right. To regain HP, visit the hospital. Currently " +
"the only way to lose HP is through infiltration<br>" +
"-Infiltration - Attempt to infiltrate a company and steal their classified secrets. See 'Companies' documentation for more details<br>" +
"-Stock Market - Added the World Stock Exchange (WSE), a brokerage that lets you buy/sell stocks. To begin trading you must first purchase " +
"an account. A WSE account will persist even after resetting by installing Augmentations. How the stock market works should hopefully be " +
"self explanatory. There is no documentation about it currently, I will add some later. NOTE: Stock prices only change when the game is open. " +
"The Stock Market is reset when installing Augmentations, which means you will lose all your stocks<br>" +
"-Decreased money gained from hacking by ~12%<br>" +
"-Increased reputation required for all Augmentations by ~40%<br>" +
"-Cost increase when purchasing multiple augmentations increased from 75% to 90%<br>" +
"-Added basic variable runtime to Netscript operations. Basic commands run in 100ms. Any function incurs another 100ms in runtime (200ms total). " +
"Any function that starts with getServer incurs another 100ms runtime (300ms total). exec() and scp() require 400ms total. <br>" +
"-Slightly reduced the amount of experience gained from hacking<br>",
}

796
src/Infiltration.js Normal file

@ -0,0 +1,796 @@
/* Infiltration.js
*
* Kill
* Knockout (nonlethal)
* Stealth Knockout (nonlethal)
* Assassinate
*
* Hack Security
* Destroy Security
* Sneak past Security
*
* Pick the locked door
*
* Bribe security
*
* Escape
*/
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 " +
"room that can be used to bypass security.",
Bots: "You see a few security bots patrolling the area.",
}
function InfiltrationInstance(companyName, startLevel, val, maxClearance, diff) {
this.companyName = companyName;
this.clearanceLevel = 0;
this.maxClearanceLevel = maxClearance;
this.securityLevel = startLevel;
this.difficulty = diff; //Affects how much security level increases. Represents a percentage
this.baseValue = val; //Base value of company secrets
this.secretsStolen = []; //Numbers representing value of stolen secrets
this.hackingExpGained = 0;
this.strExpGained = 0;
this.defExpGained = 0;
this.dexExpGained = 0;
this.agiExpGained = 0;
this.chaExpGained = 0;
}
InfiltrationInstance.prototype.gainHackingExp = function(amt) {
if (isNaN(amt)) {return;}
this.hackingExpGained += amt;
}
InfiltrationInstance.prototype.gainStrengthExp = function(amt) {
if (isNaN(amt)) {return;}
this.strExpGained += amt;
}
InfiltrationInstance.prototype.gainDefenseExp = function(amt) {
if (isNaN(amt)) {return;}
this.defExpGained += amt;
}
InfiltrationInstance.prototype.gainDexterityExp = function(amt) {
if (isNaN(amt)) {return;}
this.dexExpGained += amt;
}
InfiltrationInstance.prototype.gainAgilityExp = function(amt) {
if (isNaN(amt)) {return;}
this.agiExpGained += amt;
}
InfiltrationInstance.prototype.gainCharismaExp = function(amt) {
if (isNaN(amt)) {return;}
this.chaExpGained += amt;
}
function beginInfiltration(companyName, startLevel, val, maxClearance, diff) {
var inst = new InfiltrationInstance(companyName, startLevel, val, maxClearance, diff);
clearInfiltrationStatusText();
nextInfiltrationLevel(inst);
}
function endInfiltration(inst, success) {
if (success) {
infiltrationBoxCreate(inst);
}
clearEventListeners("infiltration-kill");
clearEventListeners("infiltration-knockout");
clearEventListeners("infiltration-stealthknockout");
clearEventListeners("infiltration-assassinate");
clearEventListeners("infiltration-hacksecurity");
clearEventListeners("infiltration-destroysecurity");
clearEventListeners("infiltration-sneak");
clearEventListeners("infiltration-pickdoor");
clearEventListeners("infiltration-bribe");
clearEventListeners("infiltration-escape");
Engine.loadWorldContent();
}
function nextInfiltrationLevel(inst) {
++inst.clearanceLevel;
updateInfiltrationLevelText(inst);
//Buttons
var killButton = clearEventListeners("infiltration-kill");
var knockoutButton = clearEventListeners("infiltration-knockout");
var stealthKnockoutButton = clearEventListeners("infiltration-stealthknockout");
var assassinateButton = clearEventListeners("infiltration-assassinate");
var hackSecurityButton = clearEventListeners("infiltration-hacksecurity");
var destroySecurityButton = clearEventListeners("infiltration-destroysecurity");
var sneakButton = clearEventListeners("infiltration-sneak");
var pickdoorButton = clearEventListeners("infiltration-pickdoor");
var bribeButton = clearEventListeners("infiltration-bribe");
var escapeButton = clearEventListeners("infiltration-escape");
killButton.style.display = "none";
knockoutButton.style.display = "none";
stealthKnockoutButton.style.display = "none";
assassinateButton.style.display = "none";
hackSecurityButton.style.display = "none";
destroySecurityButton.style.display = "none";
sneakButton.style.display = "none";
pickdoorButton.style.display = "none";
bribeButton.style.display = "none";
escapeButton.style.display = "none";
var rand = getRandomInt(0, 5); //This needs to change if more scenarios are added
var scenario = null;
switch (rand) {
case 1:
scenario = InfiltrationScenarios.TechOnly;
hackSecurityButton.style.display = "block";
destroySecurityButton.style.display = "block";
sneakButton.style.display = "block";
escapeButton.style.display = "block";
break;
case 2:
scenario = InfiltrationScenarios.TechOrLockedDoor;
hackSecurityButton.style.display = "block";
destroySecurityButton.style.display = "block";
sneakButton.style.display = "block";
pickdoorButton.style.display = "block";
escapeButton.style.display = "block";
break;
case 3:
scenario = InfiltrationScenarios.Bots;
killButton.style.display = "block";
killButton.addEventListener("click", function() {
var res = attemptInfiltrationKill(inst);
if (res[0]) {
writeInfiltrationStatusText("You SUCCESSFULLY killed the security bots! Unfortunately you alerted the " +
"rest of the facility's security. The facility's security " +
"level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
Player.karma -= 1;
endInfiltrationLevel(inst);
return false;
} else {
var dmgTaken = Math.max(1, Math.round(1.5 * inst.securityLevel / Player.defense));
writeInfiltrationStatusText("You FAILED to kill the security bots. The bots fight back " +
"and raise the alarm! You take " + dmgTaken + " damage and " +
"the facility's security level increases by " +
formatNumber((res[1]*100)-100, 2).toString() + "%");
if (Player.takeDamage(dmgTaken)) {
endInfiltration(inst, false);
}
}
updateInfiltrationButtons(inst, scenario);
updateInfiltrationLevelText(inst);
});
assassinateButton.style.display = "block";
assassinateButton.addEventListener("click", function() {
var res = attemptInfiltrationAssassinate(inst);
if (res[0]) {
writeInfiltrationStatusText("You SUCCESSFULLY assassinated the security bots without being detected!");
Player.karma -= 1;
endInfiltrationLevel(inst);
return false;
} else {
writeInfiltrationStatusText("You FAILED to assassinate the security bots. The bots have not detected " +
"you but are now more alert for an intruder. The facility's security level " +
"has increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
}
updateInfiltrationButtons(inst, scenario);
updateInfiltrationLevelText(inst);
});
hackSecurityButton.style.display = "block";
sneakButton.style.display = "block";
escapeButton.style.display = "block";
break;
default: //0, 4-5
scenario = InfiltrationScenarios.Guards;
killButton.style.display = "block";
killButton.addEventListener("click", function() {
var res = attemptInfiltrationKill(inst);
if (res[0]) {
writeInfiltrationStatusText("You SUCCESSFULLY killed the security guard! Unfortunately you alerted the " +
"rest of the facility's security. The facility's security " +
"level has increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
Player.karma -= 3;
endInfiltrationLevel(inst);
return false;
} else {
var dmgTaken = Math.max(1, Math.round(inst.securityLevel / Player.defense));
writeInfiltrationStatusText("You FAILED to kill the security guard. The guard fights back " +
"and raises the alarm! You take " + dmgTaken + " damage and " +
"the facility's security level has increased by " +
formatNumber((res[1]*100)-100, 2).toString() + "%");
if (Player.takeDamage(dmgTaken)) {
endInfiltration(inst, false);
}
}
updateInfiltrationButtons(inst, scenario);
updateInfiltrationLevelText(inst);
});
knockoutButton.style.display = "block";
stealthKnockoutButton.style.display = "block";
assassinateButton.style.display = "block";
assassinateButton.addEventListener("click", function() {
var res = attemptInfiltrationAssassinate(inst);
if (res[0]) {
writeInfiltrationStatusText("You SUCCESSFULLY assassinated the security guard without being detected!");
Player.karma -= 3;
endInfiltrationLevel(inst);
return false;
} else {
writeInfiltrationStatusText("You FAILED to assassinate the security guard. The guard has not detected " +
"you but is now more alert for an intruder. The facility's security level " +
"has increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
}
updateInfiltrationButtons(inst, scenario);
updateInfiltrationLevelText(inst);
});
sneakButton.style.display = "block";
bribeButton.style.display = "block";
escapeButton.style.display = "block";
break;
}
knockoutButton.addEventListener("click", function() {
var res = attemptInfiltrationKnockout(inst);
if (res[0]) {
writeInfiltrationStatusText("You SUCCESSFULLY knocked out the security guard! " +
"Unfortunately you made a lot of noise and alerted other security.");
writeInfiltrationStatusText("The facility's security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
endInfiltrationLevel(inst);
return false;
} else {
var dmgTaken = Math.max(1, Math.round(inst.securityLevel / Player.defense));
writeInfiltrationStatusText("You FAILED to knockout the security guard. The guard " +
"raises the alarm and fights back! You take " + dmgTaken + " damage and " +
"the facility's security level increases by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
if (Player.takeDamage(dmgTaken)) {
endInfiltration(inst, false);
}
}
updateInfiltrationButtons(inst, scenario);
updateInfiltrationLevelText(inst);
return false;
});
stealthKnockoutButton.addEventListener("click", function() {
var res = attemptInfiltrationStealthKnockout(inst);
if (res[0]) {
writeInfiltrationStatusText("You SUCCESSFULLY knocked out the security guard without making " +
"any noise!");
endInfiltrationLevel(inst);
return false;
} else {
var dmgTaken = Math.max(1, Math.round(inst.securityLevel / Player.defense));
writeInfiltrationStatusText("You FAILED to stealthily knockout the security guard. The guard " +
"raises the alarm and fights back! You take " + dmgTaken + " damage and " +
"the facility's security level increases by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
if (Player.takeDamage(dmgTaken)) {
endInfiltration(inst, false);
}
}
updateInfiltrationButtons(inst, scenario);
updateInfiltrationLevelText(inst);
return false;
});
hackSecurityButton.addEventListener("click", function() {
var res = attemptInfiltrationHack(inst);
if (res[0]) {
writeInfiltrationStatusText("You SUCCESSFULLY hacked and disabled the security system!");
writeInfiltrationStatusText("The facility's security level increased by " + ((res[1]*100) - 100).toString() + "%");
endInfiltrationLevel(inst);
return false;
} else {
writeInfiltrationStatusText("You FAILED to hack the security system. The facility's " +
"security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
}
updateInfiltrationButtons(inst, scenario);
updateInfiltrationLevelText(inst);
return false;
});
destroySecurityButton.addEventListener("click", function() {
var res = attemptInfiltrationDestroySecurity(inst);
if (res[0]) {
writeInfiltrationStatusText("You SUCCESSFULLY and violently destroy the security system!");
writeInfiltrationStatusText("The facility's security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
endInfiltrationLevel(inst);
return false;
} else {
writeInfiltrationStatusText("You FAILED to destroy the security system. The facility's " +
"security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
}
updateInfiltrationButtons(inst, scenario);
updateInfiltrationLevelText(inst);
return false;
});
sneakButton.addEventListener("click", function() {
var res = attemptInfiltrationSneak(inst);
if (res[0]) {
writeInfiltrationStatusText("You SUCCESSFULLY sneak past the security undetected!");
endInfiltrationLevel(inst);
return false;
} else {
writeInfiltrationStatusText("You FAILED and were detected while trying to sneak past security! The facility's " +
"security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
}
updateInfiltrationButtons(inst, scenario);
updateInfiltrationLevelText(inst);
return false;
});
pickdoorButton.addEventListener("click", function() {
var res = attemptInfiltrationPickLockedDoor(inst);
if (res[0]) {
writeInfiltrationStatusText("You SUCCESSFULLY pick the locked door!");
writeInfiltrationStatusText("The facility's security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
endInfiltrationLevel(inst);
return false;
} else {
writeInfiltrationStatusText("You FAILED to pick the locked door. The facility's security level " +
"increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
}
updateInfiltrationButtons(inst, scenario);
updateInfiltrationLevelText(inst);
return false;
});
bribeButton.addEventListener("click", function() {
var bribeAmt = CONSTANTS.InfiltrationBribeBaseAmount * inst.clearanceLevel;
if (Player.money < bribeAmt) {
writeInfiltrationStatusText("You do not have enough money to bribe the guard. " +
"You need $" + bribeAmt);
return false;
}
var res = attemptInfiltrationBribe(inst);
if (res[0]) {
writeInfiltrationStatusText("You SUCCESSFULLY bribed a guard to let you through " +
"to the next clearance level for $" + bribeAmt);
Player.loseMoney(bribeAmt);
endInfiltrationLevel(inst);
return false;
} else {
writeInfiltrationStatusText("You FAILED to bribe a guard! The guard is alerting " +
"other security guards about your presence! The facility's " +
"security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
}
updateInfiltrationButtons(inst, scenario);
updateInfiltrationLevelText(inst);
return false;
});
escapeButton.addEventListener("click", function() {
var res = attemptInfiltrationEscape(inst);
if (res[0]) {
writeInfiltrationStatusText("You SUCCESSFULLY escape from the facility with the stolen classified " +
"documents and company secrets!");
endInfiltration(inst, true);
return false;
} else {
writeInfiltrationStatusText("You FAILED to escape from the facility. You took 1 damage. The facility's " +
"security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
if (Player.takeDamage(1)) {
endInfiltration(inst, false);
}
}
updateInfiltrationButtons(inst, scenario);
updateInfiltrationLevelText(inst);
return false;
});
updateInfiltrationButtons(inst, scenario);
writeInfiltrationStatusText("");
writeInfiltrationStatusText("You are now on clearance level " + inst.clearanceLevel + ".<br>" +
scenario);
}
function endInfiltrationLevel(inst) {
//Check if you gained any secrets
if (inst.clearanceLevel % 5 == 0) {
var baseSecretValue = inst.baseValue * inst.clearanceLevel / 2;
var secretValue = baseSecretValue * Player.faction_rep_mult;
var secretMoneyValue = baseSecretValue * CONSTANTS.InfiltrationMoneyValue;
inst.secretsStolen.push(secretValue);
dialogBoxCreate("You found and stole a set of classified documents from the company. " +
"These classified secrets could probably be sold for money ($" +
formatNumber(secretMoneyValue, 2) + "), or they " +
"could be given to factions for reputation (" + formatNumber(secretValue, 3) + " rep)");
}
//Increase security level based on difficulty
inst.securityLevel *= (1 + (inst.difficulty / 100));
writeInfiltrationStatusText("You move on to the facility's next clearance level. This " +
"clearance level has " + inst.difficulty + "% higher security");
//If this is max level, force endInfiltration
if (inst.clearanceLevel >= inst.maxClearanceLevel) {
endInfiltration(inst, true);
} else {
nextInfiltrationLevel(inst);
}
}
function writeInfiltrationStatusText(txt) {
var statusTxt = document.getElementById("infiltration-status-text");
statusTxt.innerHTML += (txt + "<br>");
statusTxt.parentElement.scrollTop = statusTxt.scrollHeight;
}
function clearInfiltrationStatusText() {
document.getElementById("infiltration-status-text").innerHTML = "";
}
function updateInfiltrationLevelText(inst) {
var totalValue = 0;
var totalMoneyValue = 0;
for (var i = 0; i < inst.secretsStolen.length; ++i) {
totalValue += inst.secretsStolen[i];
totalMoneyValue += inst.secretsStolen[i] * CONSTANTS.InfiltrationMoneyValue;
}
document.getElementById("infiltration-level-text").innerHTML =
"Facility name: " + inst.companyName + "<br>" +
"Clearance Level: " + inst.clearanceLevel + "<br>" +
"Security Level: " + formatNumber(inst.securityLevel, 3) + "<br><br>" +
"Total reputation value of secrets stolen: " + formatNumber(totalValue, 3) + "<br>" +
"Total monetary value of secrets stolen: $" + formatNumber(totalMoneyValue, 2) + "<br><br>" +
"Hack exp gained: " + formatNumber(inst.hackingExpGained, 3) + "<br>" +
"Str exp gained: " + formatNumber(inst.strExpGained, 3) + "<br>" +
"Def exp gained: " + formatNumber(inst.defExpGained, 3) + "<br>" +
"Dex exp gained: " + formatNumber(inst.dexExpGained, 3) + "<br>" +
"Agi exp gained: " + formatNumber(inst.agiExpGained, 3) + "<br>" +
"Cha exp gained: " + formatNumber(inst.chaExpGained, 3);
}
function updateInfiltrationButtons(inst, scenario) {
var killChance = getInfiltrationKillChance(inst);
var knockoutChance = getInfiltrationKnockoutChance(inst);
var stealthKnockoutChance = getInfiltrationStealthKnockoutChance(inst);
var assassinateChance = getInfiltrationAssassinateChance(inst);
var destroySecurityChance = getInfiltrationDestroySecurityChance(inst);
var hackChance = getInfiltrationHackChance(inst);
var sneakChance = getInfiltrationSneakChance(inst);
var lockpickChance = getInfiltrationPickLockedDoorChance(inst);
var bribeChance = getInfiltrationBribeChance(inst);
var escapeChance = getInfiltrationEscapeChance(inst);
document.getElementById("infiltration-escape").innerHTML = "Escape" +
"<span class='tooltiptext'>" +
"Attempt to escape the facility with the classified secrets and " +
"documents you have stolen. You have a " +
formatNumber(escapeChance*100, 2) + "% chance of success. If you fail, " +
"the security level will increase by 5%.</span>";
switch(scenario) {
case InfiltrationScenarios.TechOrLockedDoor:
document.getElementById("infiltration-pickdoor").innerHTML = "Lockpick" +
"<span class='tooltiptext'>" +
"Attempt to pick the locked door. You have a " +
formatNumber(lockpickChance*100, 2) + "% chance of success. " +
"If you succeed, the security level will increased by 1%. If you fail, the " +
"security level will increase by 3%.</span>";
case InfiltrationScenarios.TechOnly:
document.getElementById("infiltration-hacksecurity").innerHTML = "Hack" +
"<span class='tooltiptext'>" +
"Attempt to hack and disable the security system. You have a " +
formatNumber(hackChance*100, 2) + "% chance of success. " +
"If you succeed, the security level will increase by 3%. If you fail, " +
"the security level will increase by 5%.</span>";
document.getElementById("infiltration-destroysecurity").innerHTML = "Destroy security" +
"<span class='tooltiptext'>" +
"Attempt to violently destroy the security system. You have a " +
formatNumber(destroySecurityChance*100, 2) + "% chance of success. " +
"If you succeed, the security level will increase by 5%. If you fail, the " +
"security level will increase by 10%. </span>";
document.getElementById("infiltration-sneak").innerHTML = "Sneak" +
"<span class='tooltiptext'>" +
"Attempt to sneak past the security system. You have a " +
formatNumber(sneakChance*100, 2) + "% chance of success. " +
"If you fail, the security level will increase by 8%. </span>";
break;
case InfiltrationScenarios.Bots:
document.getElementById("infiltration-kill").innerHTML = "Destroy bots" +
"<span class='tooltiptext'>" +
"Attempt to destroy the security bots through combat. You have a " +
formatNumber(killChance*100, 2) + "% chance of success. " +
"If you succeed, the security level will increase by 5%. If you fail, " +
"the security level will increase by 10%. </span>";
document.getElementById("infiltration-assassinate").innerHTML = "Assassinate bots" +
"<span class='tooltiptext'>" +
"Attempt to stealthily destroy the security bots through assassination. You have a " +
formatNumber(assassinateChance*100, 2) + "% chance of success. " +
"If you fail, the security level will increase by 10%. </span>";
document.getElementById("infiltration-hacksecurity").innerHTML = "Hack bots" +
"<span class='tooltiptext'>" +
"Attempt to disable the security bots by hacking them. You have a " +
formatNumber(hackChance*100, 2) + "% chance of success. " +
"If you succeed, the security level will increase by 1%. If you fail, " +
"the security level will increase by 5%. </span>";
document.getElementById("infiltration-sneak").innerHTML = "Sneak" +
"<span class='tooltiptext'>" +
"Attempt to sneak past the security bots. You have a " +
formatNumber(sneakChance*100, 2) + "% chance of success. " +
"If you fail, the security level will increase by 8%. </span>";
break;
case InfiltrationScenarios.Guards:
default:
document.getElementById("infiltration-kill").innerHTML = "Kill" +
"<span class='tooltiptext'>" +
"Attempt to kill the security guard. You have a " +
formatNumber(killChance*100, 2) + "% chance of success. " +
"If you succeed, the security level will increase by 5%. If you fail, " +
"the security level will decrease by 10%. </span>";
document.getElementById("infiltration-knockout").innerHTML = "Knockout" +
"<span class='tooltiptext'>" +
"Attempt to knockout the security guard. You have a " +
formatNumber(knockoutChance*100, 2) + "% chance of success. " +
"If you succeed, the security level will increase by 3%. If you fail, the " +
"security level will increase by 10%. </span>";
document.getElementById("infiltration-stealthknockout").innerHTML = "Stealth Knockout" +
"<span class='tooltiptext'>" +
"Attempt to stealthily knockout the security guard. You have a " +
formatNumber(stealthKnockoutChance*100, 2) + "% chance of success. " +
"If you fail, the security level will increase by 10%. </span>";
document.getElementById("infiltration-assassinate").innerHTML = "Assassinate" +
"<span class='tooltiptext'>" +
"Attempt to assassinate the security guard. You have a " +
formatNumber(assassinateChance*100, 2) + "% chance of success. " +
"If you fail, the security level will increase by 5%. </span>";
document.getElementById("infiltration-sneak").innerHTML = "Sneak" +
"<span class='tooltiptext'>" +
"Attempt to sneak past the security guard. You have a " +
formatNumber(sneakChance*100, 2) + "% chance of success. " +
"If you fail, the security level will increase by 8%. </span>";
document.getElementById("infiltration-bribe").innerHTML = "Bribe" +
"<span class='tooltiptext'>" +
"Attempt to bribe the security guard. You have a " +
formatNumber(bribeChance*100, 2) + "% chance of success. " +
"If you fail, the security level will increase by 15%. </span>";
break;
}
}
//Kill
//Success: 5%, Failure 10%, -Karma
function attemptInfiltrationKill(inst) {
var chance = getInfiltrationKillChance(inst);
inst.gainStrengthExp(inst.securityLevel / 750) * Player.strength_exp_mult;
inst.gainDefenseExp(inst.securityLevel / 750) * Player.defense_exp_mult;
inst.gainDexterityExp(inst.securityLevel / 750) * Player.dexterity_exp_mult;
inst.gainAgilityExp(inst.securityLevel / 750) * Player.agility_exp_mult;
if (Math.random() <= chance) {
inst.securityLevel *= 1.05;
return [true, 1.05];
} else {
inst.securityLevel *= 1.1;
return [false, 1.1];
}
}
function getInfiltrationKillChance(inst) {
var lvl = inst.securityLevel;
return Math.min(0.95,
(Player.strength +
Player.dexterity +
Player.agility) / (1.5 * lvl));
}
//Knockout
//Success: 3%, Failure: 10%
function attemptInfiltrationKnockout(inst) {
var chance = getInfiltrationKnockoutChance(inst);
inst.gainStrengthExp(inst.securityLevel / 750) * Player.strength_exp_mult;
inst.gainDefenseExp(inst.securityLevel / 750) * Player.defense_exp_mult;
inst.gainDexterityExp(inst.securityLevel / 750) * Player.dexterity_exp_mult;
inst.gainAgilityExp(inst.securityLevel / 750) * Player.agility_exp_mult;
if (Math.random() <= chance) {
inst.securityLevel *= 1.03;
return [true, 1.03];
} else {
inst.securityLevel *= 1.1;
return [false, 1.1];
}
}
function getInfiltrationKnockoutChance(inst) {
var lvl = inst.securityLevel;
return Math.min(0.95,
(Player.strength +
Player.dexterity +
Player.agility) / (1.75 * lvl));
}
//Stealth knockout
//Success: 0%, Failure: 10%
function attemptInfiltrationStealthKnockout(inst) {
var chance = getInfiltrationStealthKnockoutChance(inst);
inst.gainStrengthExp(inst.securityLevel / 750) * Player.strength_exp_mult;
inst.gainDexterityExp(inst.securityLevel / 500) * Player.dexterity_exp_mult;
inst.gainAgilityExp(inst.securityLevel / 500) * Player.agility_exp_mult;
if (Math.random() <= chance) {
return [true, 1];
} else {
inst.securityLevel *= 1.1;
return [false, 1.1];
}
}
function getInfiltrationStealthKnockoutChance(inst) {
var lvl = inst.securityLevel;
return Math.min(0.95,
(0.5 * Player.strength +
2 * Player.dexterity +
2 * Player.agility) / (3 * lvl));
}
//Assassination
//Success: 0%, Failure: 5%, -Karma
function attemptInfiltrationAssassinate(inst) {
var chance = getInfiltrationAssassinateChance(inst);
inst.gainStrengthExp(inst.securityLevel / 750) * Player.strength_exp_mult;
inst.gainDexterityExp(inst.securityLevel / 500) * Player.dexterity_exp_mult;
inst.gainAgilityExp(inst.securityLevel / 500) * Player.agility_exp_mult;
if (Math.random() <= chance) {
return [true, 1];
} else {
inst.securityLevel *= 1.05;
return [false, 1.05];
}
}
function getInfiltrationAssassinateChance(inst) {
var lvl = inst.securityLevel;
return Math.min(0.95,
(Player.dexterity +
0.5 * Player.agility) / (2 * lvl));
}
//Destroy security
//Success: 5%, Failure: 10%
function attemptInfiltrationDestroySecurity(inst) {
var chance = getInfiltrationDestroySecurityChance(inst);
inst.gainStrengthExp(inst.securityLevel / 750) * Player.strength_exp_mult;
inst.gainDefenseExp(inst.securityLevel / 750) * Player.defense_exp_mult;
inst.gainDexterityExp(inst.securityLevel / 750) * Player.dexterity_exp_mult;
inst.gainAgilityExp(inst.securityLevel / 750) * Player.agility_exp_mult;
if (Math.random() <= chance) {
inst.securityLevel *= 1.05;
return [true, 1.05];
} else {
inst.securityLevel *= 1.1;
return [false, 1.1];
}
}
function getInfiltrationDestroySecurityChance(inst) {
var lvl = inst.securityLevel;
return Math.min(0.95,
(Player.strength +
Player.dexterity +
Player.agility) / (2 * lvl));
}
//Hack security
//Success: 1%, Failure: 5%
function attemptInfiltrationHack(inst) {
var chance = getInfiltrationHackChance(inst);
inst.gainHackingExp(inst.securityLevel / 250) * Player.hacking_exp_mult;
if (Math.random() <= chance) {
inst.securityLevel *= 1.03;
return [true, 1.03];
} else {
inst.securityLevel *= 1.05;
return [false, 1.05];
}
}
function getInfiltrationHackChance(inst) {
var lvl = inst.securityLevel;
return Math.min(0.95,
(Player.hacking_skill) / lvl);
}
//Sneak past security
//Success: 0%, Failure: 8%
function attemptInfiltrationSneak(inst) {
var chance = getInfiltrationSneakChance(inst);
inst.gainAgilityExp(inst.securityLevel / 250) * Player.agility_exp_mult;
if (Math.random() <= chance) {
return [true, 1];
} else {
inst.securityLevel *= 1.08;
return [false, 1.08];
}
}
function getInfiltrationSneakChance(inst) {
var lvl = inst.securityLevel;
return Math.min(0.95,
(Player.agility +
0.5 * Player.dexterity) / (2 * lvl));
}
//Pick locked door
//Success: 1%, Failure: 3%
function attemptInfiltrationPickLockedDoor(inst) {
var chance = getInfiltrationPickLockedDoorChance(inst);
inst.gainDexterityExp(inst.securityLevel / 250) * Player.dexterity_exp_mult;
if (Math.random() <= chance) {
inst.securityLevel *= 1.01;
return [true, 1.01];
} else {
inst.securityLevel *= 1.03;
return [false, 1.03];
}
}
function getInfiltrationPickLockedDoorChance(inst) {
var lvl = inst.securityLevel;
return Math.min(0.95,
(Player.dexterity) / lvl);
}
//Bribe
//Success: 0%, Failure: 15%,
function attemptInfiltrationBribe(inst) {
var chance = getInfiltrationBribeChance(inst);
inst.gainCharismaExp(inst.securityLevel / 250) * Player.charisma_exp_mult;
if (Math.random() <= chance) {
return [true, 1];
} else {
inst.securityLevel *= 1.15;
return [false, 1.15];
}
}
function getInfiltrationBribeChance(inst) {
var lvl = inst.securityLevel;
return Math.min(0.95,
(Player.charisma) / lvl);
}
//Escape
//Failure: 5%
function attemptInfiltrationEscape(inst) {
var chance = getInfiltrationEscapeChance(inst);
inst.gainAgilityExp(inst.securityLevel / 500) * Player.agility_exp_mult;
inst.gainDexterityExp(inst.securityLevel / 500) * Player.dexterity_exp_mult;
if (Math.random() <= chance) {
return [true, 1];
} else {
inst.securityLevel *= 1.05;
return [false, 1.05];
}
}
function getInfiltrationEscapeChance(inst) {
var lvl = inst.securityLevel;
return Math.min(0.95,
(2 * Player.agility +
Player.dexterity) / lvl);
}

@ -647,5 +647,5 @@ function iTutorialSetText(txt) {
var textBox = document.getElementById("interactive-tutorial-text");
if (textBox == null) {throw new Error("Could not find text box"); return;}
textBox.innerHTML = txt;
textBox.parentElement.scrollTop = 0; // this resets scroll position
}

@ -80,6 +80,10 @@ Locations = {
VolhavenCompuTek: "CompuTek",
VolhavenMilleniumFitnessGym: "Millenium Fitness Gym",
VolhavenSlums: "Volhaven Slums",
//Generic locations
Hospital: "Hospital",
WorldStockExchange: "World Stock Exchange",
}
displayLocationContent = function() {
@ -149,6 +153,10 @@ displayLocationContent = function() {
var travelToIshima = document.getElementById("location-travel-to-ishima");
var travelToVolhaven = document.getElementById("location-travel-to-volhaven");
var infiltrate = clearEventListeners("location-infiltrate");
var hospitalTreatment = document.getElementById("location-hospital-treatment");
var slumsDescText = document.getElementById("location-slums-description");
var slumsShoplift = document.getElementById("location-slums-shoplift");
var slumsMug = document.getElementById("location-slums-mug");
@ -246,6 +254,10 @@ displayLocationContent = function() {
travelToIshima.style.display = "none";
travelToVolhaven.style.display = "none";
infiltrate.style.display = "none";
hospitalTreatment.style.display = "none";
slumsDescText.style.display = "none";
slumsShoplift.style.display = "none";
slumsMug.style.display = "none";
@ -320,6 +332,10 @@ displayLocationContent = function() {
locationTxtDiv3.style.display = "none";
}
//Calculate hospital Cost
if (Player.hp < 0) {Player.hp = 0;}
var hospitalTreatmentCost = (Player.max_hp - Player.hp) * CONSTANTS.HospitalCostPerHp;
switch (loc) {
case Locations.AevumTravelAgency:
travelAgencyText.style.display = "block";
@ -352,6 +368,8 @@ displayLocationContent = function() {
purchase1tb.style.display = "block";
purchaseTor.style.display = "block";
purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumECorp,
6000, 100, 150, 14);
break;
case Locations.AevumBachmanAndAssociates:
@ -363,6 +381,8 @@ displayLocationContent = function() {
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumBachmanAndAssociates,
1500, 36, 60, 10);
break;
case Locations.AevumClarkeIncorporated:
@ -374,6 +394,8 @@ displayLocationContent = function() {
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumClarkeIncorporated,
2400, 28, 75, 9.5);
break;
case Locations.AevumFulcrumTechnologies:
@ -391,6 +413,8 @@ displayLocationContent = function() {
purchase1tb.style.display = "block";
purchaseTor.style.display = "block";
purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumFulcrumTechnologies,
6000, 84, 100, 16);
break;
case Locations.AevumAeroCorp:
@ -400,8 +424,9 @@ displayLocationContent = function() {
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumAeroCorp,
2000, 26, 50, 10.5);
break;
case Locations.AevumGalacticCybersystems:
@ -413,6 +438,8 @@ displayLocationContent = function() {
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumGalacticCybersystems,
1400, 24, 50, 10);
break;
case Locations.AevumWatchdogSecurity:
@ -425,6 +452,8 @@ displayLocationContent = function() {
networkEngineerJob.style.display = "block";
securityJob.style.display = "block";
agentJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumWatchdogSecurity,
850, 12, 30, 8);
break;
case Locations.AevumRhoConstruction:
@ -432,6 +461,8 @@ displayLocationContent = function() {
softwareJob.style.display = "block";
businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumRhoConstruction,
600, 8, 20, 4.5);
break;
case Locations.AevumPolice:
@ -439,6 +470,8 @@ displayLocationContent = function() {
softwareJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumPolice,
700, 10, 25, 6);
break;
case Locations.AevumNetLinkTechnologies:
@ -455,6 +488,8 @@ displayLocationContent = function() {
purchase8gb.style.display = "block";
purchaseTor.style.display = "block";
purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.AevumNetLinkTechnologies,
150, 5, 15, 3.5);
break;
case Locations.AevumCrushFitnessGym:
@ -487,6 +522,8 @@ displayLocationContent = function() {
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.ChongqingKuaiGongInternational,
5500, 42, 100, 15);
break;
case Locations.ChongqingSolarisSpaceSystems:
@ -496,8 +533,9 @@ displayLocationContent = function() {
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.ChongqingSolarisSpaceSystems,
3600, 24, 75, 14);
break;
@ -525,6 +563,8 @@ displayLocationContent = function() {
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12MegaCorp,
6000, 100, 125, 15.5);
break;
case Locations.Sector12BladeIndustries:
@ -536,6 +576,8 @@ displayLocationContent = function() {
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12BladeIndustries,
3000, 40, 100, 11);
break;
case Locations.Sector12FourSigma:
@ -547,6 +589,8 @@ displayLocationContent = function() {
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12FourSigma,
1500, 50, 100, 16);
break;
case Locations.Sector12IcarusMicrosystems:
@ -558,6 +602,8 @@ displayLocationContent = function() {
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12IcarusMicrosystems,
900, 28, 70, 12);
break;
case Locations.Sector12UniversalEnergy:
@ -569,6 +615,8 @@ displayLocationContent = function() {
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12UniversalEnergy,
775, 20, 50, 10);
break;
case Locations.Sector12DeltaOne:
@ -578,8 +626,9 @@ displayLocationContent = function() {
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12DeltaOne,
1200, 30, 75, 11);
break;
case Locations.Sector12CIA:
@ -591,6 +640,8 @@ displayLocationContent = function() {
networkEngineerJob.style.display = "block";
securityJob.style.display = "block";
agentJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12CIA,
1450, 38, 80, 12.5);
break;
case Locations.Sector12NSA:
@ -602,6 +653,8 @@ displayLocationContent = function() {
networkEngineerJob.style.display = "block";
securityJob.style.display = "block";
agentJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12NSA,
1400, 34, 80, 12);
break;
case Locations.Sector12AlphaEnterprises:
@ -614,6 +667,8 @@ displayLocationContent = function() {
purchase4gb.style.display = "block";
purchaseTor.style.display = "block";
purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12AlphaEnterprises,
250, 10, 40, 5);
break;
case Locations.Sector12CarmichaelSecurity:
@ -626,6 +681,8 @@ displayLocationContent = function() {
networkEngineerJob.style.display = "block";
securityJob.style.display = "block";
agentJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12CarmichaelSecurity,
500, 14, 60, 5);
break;
case Locations.Sector12FoodNStuff:
@ -640,6 +697,8 @@ displayLocationContent = function() {
employeeJob.style.display = "block";
employeePartTimeJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.Sector12JoesGuns,
100, 4, 20, 4);
break;
case Locations.Sector12IronGym:
@ -671,7 +730,8 @@ displayLocationContent = function() {
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.NewTokyoDefComm,
1300, 24, 70, 9.5);
break;
case Locations.NewTokyoVitaLife:
@ -683,6 +743,8 @@ displayLocationContent = function() {
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.NewTokyoVitaLife,
750, 18, 100, 9);
break;
case Locations.NewTokyoGlobalPharmaceuticals:
@ -695,6 +757,8 @@ displayLocationContent = function() {
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.NewTokyoGlobalPharmaceuticals,
900, 20, 80, 9);
break;
case Locations.NewTokyoNoodleBar:
@ -704,7 +768,6 @@ displayLocationContent = function() {
waitPartTimeJob.style.display = "block";
break;
case Locations.IshimaTravelAgency:
travelAgencyText.style.display = "block";
travelToAevum.style.display = "block";
@ -733,6 +796,8 @@ displayLocationContent = function() {
purchase128gb.style.display = "block";
purchase256gb.style.display = "block";
purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.IshimaStormTechnologies,
700, 20, 100, 10.5);
break;
case Locations.IshimaNovaMedical:
@ -744,6 +809,8 @@ displayLocationContent = function() {
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.IshimaNovaMedical,
600, 16, 50, 8);
break;
case Locations.IshimaOmegaSoftware:
@ -760,6 +827,8 @@ displayLocationContent = function() {
purchase32gb.style.display = "block";
purchaseTor.style.display = "block";
purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.IshimaOmegaSoftware,
200, 5, 40, 4.5);
break;
case Locations.VolhavenTravelAgency:
@ -791,6 +860,8 @@ displayLocationContent = function() {
purchase256gb.style.display = "block";
purchase512gb.style.display = "block";
purchase1tb.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenOmniTekIncorporated,
1500, 38, 100, 10);
break;
case Locations.VolhavenNWO:
@ -802,6 +873,8 @@ displayLocationContent = function() {
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenNWO,
1800, 48, 200, 12);
break;
case Locations.VolhavenHeliosLabs:
@ -812,7 +885,8 @@ displayLocationContent = function() {
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenHeliosLabs,
1200, 24, 75, 9.5);
break;
case Locations.VolhavenOmniaCybersystems:
@ -822,8 +896,9 @@ displayLocationContent = function() {
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenOmniaCybersystems,
900, 24, 90, 10);
break;
case Locations.VolhavenLexoCorp:
@ -836,6 +911,8 @@ displayLocationContent = function() {
networkEngineerJob.style.display = "block";
businessJob.style.display = "block";
securityJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenLexoCorp,
500, 10, 40, 6);
break;
case Locations.VolhavenSysCoreSecurities:
@ -845,6 +922,8 @@ displayLocationContent = function() {
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenSysCoreSecurities,
600, 12, 50, 7);
break;
case Locations.VolhavenCompuTek:
@ -864,6 +943,8 @@ displayLocationContent = function() {
purchase256gb.style.display = "block";
purchaseTor.style.display = "block";
purchaseHomeRam.style.display = "block";
setInfiltrateButton(infiltrate, Locations.VolhavenCompuTek,
300, 8, 35, 6);
break;
case Locations.VolhavenMilleniumFitnessGym:
@ -918,6 +999,13 @@ displayLocationContent = function() {
slumsHeist.innerHTML = "Heist (" + (heistChance*100).toFixed(3) + "% chance of success)";
slumsHeist.innerHTML += '<span class="tooltiptext"> Attempt to pull off the ultimate heist </span>';
break;
//Hospital
case Locations.Hospital:
hospitalTreatment.innerText = "Get treatment for wounds - $" + formatNumber(hospitalTreatmentCost, 2).toString();
hospitalTreatment.style.display = "block";
break;
default:
console.log("ERROR: INVALID LOCATION");
@ -949,6 +1037,13 @@ initLocationButtons = function() {
return false;
});
aevumHospital = document.getElementById("aevum-hospital");
aevumHospital.addEventListener("click", function() {
Player.location = Locations.Hospital;
Engine.loadLocationContent();
return false;
});
aevumSummitUniversity = document.getElementById("aevum-summituniversity");
aevumSummitUniversity.addEventListener("click", function() {
Player.location = Locations.AevumSummitUniversity;
@ -1054,6 +1149,13 @@ initLocationButtons = function() {
return false;
});
chongqingHospital = document.getElementById("chongqing-hospital");
chongqingHospital.addEventListener("click", function() {
Player.location = Locations.Hospital;
Engine.loadLocationContent();
return false;
});
chongqingKuaiGongInternational = document.getElementById("chongqing-kuaigonginternational");
chongqingKuaiGongInternational.addEventListener("click", function() {
Player.location = Locations.ChongqingKuaiGongInternational;
@ -1083,6 +1185,13 @@ initLocationButtons = function() {
return false;
});
sector12Hospital = document.getElementById("sector12-hospital");
sector12Hospital.addEventListener("click", function() {
Player.location = Locations.Hospital;
Engine.loadLocationContent();
return false;
});
sector12RothmanUniversity = document.getElementById("sector12-rothmanuniversity");
sector12RothmanUniversity.addEventListener("click", function() {
Player.location = Locations.Sector12RothmanUniversity;
@ -1202,6 +1311,13 @@ initLocationButtons = function() {
return false;
});
newTokyoHospital = document.getElementById("newtokyo-hospital");
newTokyoHospital.addEventListener("click", function() {
Player.location = Locations.Hospital;
Engine.loadLocationContent();
return false;
});
newTokyoDefComm = document.getElementById("newtokyo-defcomm");
newTokyoDefComm.addEventListener("click", function() {
Player.location = Locations.NewTokyoDefComm;
@ -1244,6 +1360,13 @@ initLocationButtons = function() {
return false;
});
ishimaHospital = document.getElementById("ishima-hospital");
ishimaHospital.addEventListener("click", function() {
Player.location = Locations.Hospital;
Engine.loadLocationContent();
return false;
});
ishimaStormTechnologies = document.getElementById("ishima-stormtechnologies");
ishimaStormTechnologies.addEventListener("click", function() {
Player.location = Locations.IshimaStormTechnologies;
@ -1279,6 +1402,13 @@ initLocationButtons = function() {
return false;
});
volhavenHospital = document.getElementById("volhaven-hospital");
volhavenHospital.addEventListener("click", function() {
Player.location = Locations.Hospital;
Engine.loadLocationContent();
return false;
});
volhavenZBInstituteOfTechnology = document.getElementById("volhaven-zbinstituteoftechnology");
volhavenZBInstituteOfTechnology.addEventListener("click", function() {
Player.location = Locations.VolhavenZBInstituteOfTechnology;
@ -1349,6 +1479,13 @@ initLocationButtons = function() {
return false;
});
worldStockExchange = document.getElementById("generic-location-wse");
worldStockExchange.addEventListener("click", function() {
Player.location = Locations.WorldStockExchange;
Engine.loadStockMarketContent();
return false;
});
//Buttons to interact at a location (apply for job/promotion, train, purchase, etc.)
var softwareJob = document.getElementById("location-software-job");
@ -1397,6 +1534,8 @@ initLocationButtons = function() {
var slumsAssassinate = document.getElementById("location-slums-assassinate");
var slumsHeist = document.getElementById("location-slums-heist");
var hospitalTreatment = document.getElementById("location-hospital-treatment");
softwareJob.addEventListener("click", function() {
Player.applyForSoftwareJob();
return false;
@ -1596,6 +1735,17 @@ initLocationButtons = function() {
commitHeistCrime();
return false;
});
hospitalTreatment.addEventListener("click", function() {
if (Player.hp < 0) {Player.hp = 0;}
var price = (Player.max_hp - Player.hp) * CONSTANTS.HospitalCostPerHp;
Player.loseMoney(price);
dialogBoxCreate("You were healed to full health! The hospital billed " +
"you for $" + formatNumber(price, 2).toString());
Player.hp = Player.max_hp;
displayLocationContent();
return false;
});
}
travelToCity = function(destCityName, cost) {
@ -1741,3 +1891,12 @@ setGymLocationButtons = function(costMult, expMult) {
return false;
});
}
setInfiltrateButton = function(btn, companyName, startLevel, val, maxClearance, difficulty) {
btn.style.display = "block";
btn.addEventListener("click", function() {
Engine.loadInfiltrationContent();
beginInfiltration(companyName, startLevel, val, maxClearance, difficulty)
return false;
});
}

@ -154,6 +154,7 @@ function evaluate(exp, workerScript) {
});
break;
case "call":
setTimeout(function() {
if (exp.func.value == "hack") {
var p = netscriptHack(exp, workerScript);
p.then(function(res) {
@ -321,6 +322,7 @@ function evaluate(exp, workerScript) {
reject(e);
});
} else if (exp.func.value == "exec") {
setTimeout(function() {
if (exp.args.length < 2) {
return reject(makeRuntimeRejectMsg(workerScript, "exec() call has incorrect number of arguments. Usage: exec(scriptname, server, [numThreads], [arg1], [arg2]...)"));
}
@ -353,6 +355,7 @@ function evaluate(exp, workerScript) {
}).catch(function(e) {
reject(e);
});
}, 2 * CONSTANTS.CodeInstructionRunTime);
} else if (exp.func.value == "kill") {
if (exp.args.length < 2) {
return reject(makeRuntimeRejectMsg(workerScript, "kill() call has incorrect number of arguments. Usage: kill(scriptname, server, [arg1], [arg2]...)"));
@ -412,6 +415,7 @@ function evaluate(exp, workerScript) {
reject(e);
});
} else if (exp.func.value == "scp") {
setTimeout(function() {
if (exp.args.length != 2) {
return reject(makeRuntimeRejectMsg(workerScript, "scp() call has incorrect number of arguments. Takes 2 arguments"));
}
@ -473,6 +477,7 @@ function evaluate(exp, workerScript) {
}).catch(function(e) {
reject(e);
});
}, 2 * CONSTANTS.CodeInstructionRunTime);
} else if (exp.func.value == "getHostname") {
if (exp.args.length != 0) {
return reject(makeRuntimeRejectMsg(workerScript, "getHostname() call has incorrect number of arguments. Takes 0 arguments"));
@ -490,6 +495,7 @@ function evaluate(exp, workerScript) {
workerScript.scriptRef.log("getHackingLevel() returned " + Player.hacking_skill);
resolve(Player.hacking_skill);
} else if (exp.func.value == "getServerMoneyAvailable") {
setTimeout(function() {
if (exp.args.length != 1) {
return reject(makeRuntimeRejectMsg(workerScript, "getServerMoneyAvailable() call has incorrect number of arguments. Takes 1 arguments"));
}
@ -505,7 +511,9 @@ function evaluate(exp, workerScript) {
}, function(e) {
reject(e);
});
}, CONSTANTS.CodeInstructionRunTime);
} else if (exp.func.value == "getServerSecurityLevel") {
setTimeout(function() {
if (exp.args.length != 1) {
return reject(makeRuntimeRejectMsg(workerScript, "getServerSecurityLevel() call has incorrect number of arguments. Takes 1 arguments"));
}
@ -521,7 +529,9 @@ function evaluate(exp, workerScript) {
}, function(e) {
reject(e);
});
}, CONSTANTS.CodeInstructionRunTime);
} else if (exp.func.value == "getServerBaseSecurityLevel") {
setTimeout(function() {
if (exp.args.length != 1) {
return reject(makeRuntimeRejectMsg(workerScript, "getServerBaseSecurityLevel() call has incorrect number of arguments. Takes 1 arguments"));
}
@ -537,7 +547,9 @@ function evaluate(exp, workerScript) {
}, function(e) {
reject(e);
});
}, CONSTANTS.CodeInstructionRunTime);
} else if (exp.func.value == "getServerRequiredHackingLevel") {
setTimeout(function() {
if (exp.args.length != 1) {
return reject(makeRuntimeRejectMsg(workerScript, "getServerRequiredHackingLevel() call has incorrect number of arguments. Takes 1 argument"));
}
@ -553,7 +565,9 @@ function evaluate(exp, workerScript) {
}, function(e) {
reject(e);
});
}, CONSTANTS.CodeInstructionRunTime);
} else if (exp.func.value == "getServerMaxMoney") {
setTimeout(function() {
if (exp.args.length != 1) {
return reject(makeRuntimeRejectMsg(workerScript, "getServerMaxMoney() call has incorrect number of arguments. Takes 1 argument"));
}
@ -569,7 +583,9 @@ function evaluate(exp, workerScript) {
}, function(e) {
reject(e);
});
}, CONSTANTS.CodeInstructionRunTime);
} else if (exp.func.value == "getServerNumPortsRequired") {
setTimeout(function() {
if (exp.args.length != 1) {
return reject(makeRuntimeRejectMsg(workerScript, "getServerNumPortsRequired() call has incorrect number of arguments. Takes 1 argument"));
}
@ -585,6 +601,7 @@ function evaluate(exp, workerScript) {
}, function(e) {
reject(e);
});
}, CONSTANTS.CodeInstructionRunTime);
} else if (exp.func.value == "fileExists") {
if (exp.args.length != 1 && exp.args.length != 2) {
return reject(makeRuntimeRejectMsg(workerScript, "fileExists() call has incorrect number of arguments. Takes 1 or 2 arguments"));
@ -688,6 +705,7 @@ function evaluate(exp, workerScript) {
} else {
reject(makeRuntimeRejectMsg(workerScript, "Invalid function: " + exp.func.value));
}
}, CONSTANTS.CodeInstructionRunTime); //End additional setTimeout delay for function "calls", the Netscript operation run time
break;
default:
reject(makeRuntimeRejectMsg(workerScript, "Unrecognized token: " + exp.type + ". This is a bug please report to game developer"));
@ -1113,14 +1131,14 @@ function scriptCalculateExpGain(server) {
if (server.baseDifficulty == null) {
server.baseDifficulty = server.hackDifficulty;
}
return (server.baseDifficulty * Player.hacking_exp_mult * 0.5 + 2);
return (server.baseDifficulty * Player.hacking_exp_mult * 0.4 + 2);
}
//The same as Player's calculatePercentMoneyHacked() function but takes in the server as an argument
function scriptCalculatePercentMoneyHacked(server) {
var difficultyMult = (100 - server.hackDifficulty) / 100;
var skillMult = (Player.hacking_skill - (server.requiredHackingSkill - 1)) / Player.hacking_skill;
var percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / 200;
var percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / 225;
if (percentMoneyHacked < 0) {return 0;}
if (percentMoneyHacked > 1) {return 1;}
return percentMoneyHacked;

@ -170,6 +170,10 @@ function PlayerObject() {
this.hacknet_node_core_cost_mult = 1;
this.hacknet_node_level_cost_mult = 1;
//Stock Market
this.hasWseAccount = false;
this.hasTixApiAccess = false;
//Used to store the last update time.
this.lastUpdate = 0;
this.totalPlaytime = 0;
@ -203,13 +207,16 @@ PlayerObject.prototype.calculateSkill = function(exp) {
}
PlayerObject.prototype.updateSkillLevels = function() {
//TODO Account for total and lifetime stats for achievements and stuff
this.hacking_skill = Math.floor(this.calculateSkill(this.hacking_exp) * this.hacking_mult);
this.strength = Math.floor(this.calculateSkill(this.strength_exp) * this.strength_mult);
this.defense = Math.floor(this.calculateSkill(this.defense_exp) * this.defense_mult);
this.dexterity = Math.floor(this.calculateSkill(this.dexterity_exp) * this.dexterity_mult);
this.agility = Math.floor(this.calculateSkill(this.agility_exp) * this.agility_mult);
this.charisma = Math.floor(this.calculateSkill(this.charisma_exp) * this.charisma_mult);
var ratio = this.hp / this.max_hp;
this.max_hp = Math.floor(10 + this.defense / 10);
Player.hp = Math.round(this.max_hp * ratio);
}
//Calculates the chance of hacking a server
@ -246,7 +253,7 @@ PlayerObject.prototype.calculateHackingTime = function() {
PlayerObject.prototype.calculatePercentMoneyHacked = function() {
var difficultyMult = (100 - this.getCurrentServer().hackDifficulty) / 100;
var skillMult = (this.hacking_skill - (this.getCurrentServer().requiredHackingSkill - 1)) / this.hacking_skill;
var percentMoneyHacked = difficultyMult * skillMult * this.hacking_money_mult / 200;
var percentMoneyHacked = difficultyMult * skillMult * this.hacking_money_mult / 225;
console.log("Percent money hacked calculated to be: " + percentMoneyHacked);
if (percentMoneyHacked < 0) {return 0;}
if (percentMoneyHacked > 1) {return 1;}
@ -261,7 +268,7 @@ PlayerObject.prototype.calculateExpGain = function() {
if (s.baseDifficulty == null) {
s.baseDifficulty = s.hackDifficulty;
}
return (s.baseDifficulty * this.hacking_exp_mult * 0.5 + 2);
return (s.baseDifficulty * this.hacking_exp_mult * 0.4 + 2);
}
//Hack/Analyze a server. Return the amount of time the hack will take. This lets the Terminal object know how long to disable itself for
@ -1204,12 +1211,24 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
Engine.loadLocationContent();
}
PlayerObject.prototype.takeDamage = function() {
//Returns true if hospitalized, false otherwise
PlayerObject.prototype.takeDamage = function(amt) {
this.hp -= amt;
if (this.hp <= 0) {
this.hospitalize();
return true;
} else {
return false;
}
}
PlayerObject.prototype.hospitalize = function() {
dialogBoxCreate("You were in critical condition! You were taken to the hospital where " +
"luckily they were able to save your life. You were charged $" +
formatNumber(this.max_hp * CONSTANTS.HospitalCostPerHp, 2));
Player.loseMoney(this.max_hp * CONSTANTS.HospitalCostPerHp);
this.hp = this.max_hp;
}
/* Functions for saving and loading the Player data */

@ -200,6 +200,12 @@ function prestigeAugmentation() {
//Messages
initMessages();
//Stock market
if (Player.hasWseAccount) {
initStockMarket();
initSymbolToStockMap();
}
Player.playtimeSinceLastAug = 0;
Engine.loadTerminalContent();

@ -11,6 +11,7 @@ function BitburnerSaveObject() {
this.SpecialServerIpsSave = "";
this.AliasesSave = "";
this.MessagesSave = "";
this.StockMarketSave = "";
this.VersionSave = "";
}
@ -36,6 +37,7 @@ BitburnerSaveObject.prototype.saveGame = function() {
this.SpecialServerIpsSave = JSON.stringify(SpecialServerIps);
this.AliasesSave = JSON.stringify(Aliases);
this.MessagesSave = JSON.stringify(Messages);
this.StockMarketSave = JSON.stringify(StockMarket);
this.VersionSave = JSON.stringify(CONSTANTS.Version);
var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this))));
window.localStorage.setItem("bitburnerSave", saveString);
@ -76,6 +78,15 @@ loadGame = function(saveObj) {
} else {
initMessages();
}
if (saveObj.hasOwnProperty("StockMarketSave")) {
try {
StockMarket = JSON.parse(saveObj.StockMarketSave, Reviver);
} catch(e) {
StockMarket = {};
}
} else {
StockMarket = {};
}
if (saveObj.hasOwnProperty("VersionSave")) {
try {
var ver = JSON.parse(saveObj.VersionSave, Reviver);
@ -119,6 +130,7 @@ loadImportedGame = function(saveObj, saveString) {
var tempAugmentations = null;
var tempAliases = null;
var tempMessages = null;
var tempStockMarket = null;
try {
saveString = decodeURIComponent(escape(atob(saveString)));
tempSaveObj = new BitburnerSaveObject();
@ -148,6 +160,15 @@ loadImportedGame = function(saveObj, saveString) {
} else {
initMessages();
}
if (saveObj.hasOwnProperty("StockMarketSave")) {
try {
tempStockMarket = JSON.parse(saveObj.StockMarketSave, Reviver);
} catch(e) {
tempStockMarket = {};
}
} else {
tempStockMarket = {};
}
if (tempSaveObj.hasOwnProperty("VersionSave")) {
try {
var ver = JSON.parse(tempSaveObj.VersionSave, Reviver);
@ -198,6 +219,10 @@ loadImportedGame = function(saveObj, saveString) {
Messages = tempMessages;
}
if (tempStockMarket) {
StockMarket = tempStockMarket;
}
dialogBoxCreate("Imported game");
gameOptionsBoxClose();

@ -529,7 +529,7 @@ initForeignServers = function() {
var TheBlackHandServer = new Server();
TheBlackHandServer.init(createRandomIp(), "I.I.I.I", "I.I.I.I", true, false, false, false, 0);
TheBlackHandServer.setHackingParameters(getRandomInt(303, 325), 0, 0, 0);
TheBlackHandServer.setHackingParameters(getRandomInt(340, 365), 0, 0, 0);
TheBlackHandServer.setPortProperties(3);
AddToAllServers(TheBlackHandServer);
SpecialServerIps.addIp(SpecialServerNames.TheBlackHandServer, TheBlackHandServer.ip);
@ -689,7 +689,7 @@ 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);
//console.log("Adjusted growth rate: " + adjGrowthRate);
//Calculate adjusted server growth rate based on parameters
var serverGrowthPercentage = server.serverGrowth / 100;

546
src/StockMarket.js Normal file

@ -0,0 +1,546 @@
/* StockMarket.js */
function Stock(name, symbol, mv, b, otlkMag, initPrice=10000) {
this.symbol = symbol;
this.name = name;
this.price = initPrice;
this.playerShares = 0;
this.playerAvgPx = 0;
this.mv = mv;
this.b = b;
this.otlkMag = otlkMag;
}
StockMarket = {} //Full name to stock object
StockSymbols = {} //Full name to symbol
SymbolToStockMap = {}; //Symbol to Stock object
function initStockSymbols() {
//Stocks for companies at which you can work
StockSymbols[Locations.AevumECorp] = "ECP";
StockSymbols[Locations.Sector12MegaCorp] = "MGCP";
StockSymbols[Locations.Sector12BladeIndustries] = "BLD";
StockSymbols[Locations.AevumClarkeIncorporated] = "CLRK";
StockSymbols[Locations.VolhavenOmniTekIncorporated] = "OMTK";
StockSymbols[Locations.Sector12FourSigma] = "FSIG";
StockSymbols[Locations.ChongqingKuaiGongInternational] = "KGI";
StockSymbols[Locations.AevumFulcrumTechnologies] = "FLCM";
StockSymbols[Locations.IshimaStormTechnologies] = "STM";
StockSymbols[Locations.NewTokyoDefComm] = "DCOMM";
StockSymbols[Locations.VolhavenHeliosLabs] = "HLS";
StockSymbols[Locations.NewTokyoVitaLife] = "VITA";
StockSymbols[Locations.Sector12IcarusMicrosystems] = "ICRS";
StockSymbols[Locations.Sector12UniversalEnergy] = "UNV";
StockSymbols[Locations.AevumGalacticCybersystems] = "GLC"
StockSymbols[Locations.AevumAeroCorp] = "AERO";
StockSymbols[Locations.VolhavenOmniaCybersystems] = "OMN";
StockSymbols[Locations.ChongqingSolarisSpaceSystems] = "SLRS";
StockSymbols[Locations.NewTokyoGlobalPharmaceuticals] = "GPH";
StockSymbols[Locations.IshimaNovaMedical] = "NVMD";
StockSymbols[Locations.AevumWatchdogSecurity] = "WDS";
StockSymbols[Locations.VolhavenLexoCorp] = "LXO";
StockSymbols[Locations.AevumRhoConstruction] = "RHOC";
StockSymbols[Locations.Sector12AlphaEnterprises] = "APHE";
StockSymbols[Locations.VolhavenSysCoreSecurities] = "SYSC";
StockSymbols[Locations.VolhavenCompuTek] = "CTK";
StockSymbols[Locations.AevumNetLinkTechnologies] = "NTLK";
StockSymbols[Locations.IshimaOmegaSoftware] = "OMGA";
StockSymbols[Locations.Sector12FoodNStuff] = "FNS";
//Stocks for other companies
StockSymbols["Sigma Cosmetics"] = "SGC";
StockSymbols["Joes Guns"] = "JGN";
StockSymbols["Catalyst Ventures"] = "CTYS";
StockSymbols["UnitaLife Group"] = "UNT";
StockSymbols["Zeus Medical"] = "ZEUS";
StockSymbols["Taiyang Digital"] = "TAI";
StockSymbols["Microdyne Technologies"] = "MDYN";
StockSymbols["Titan Laboratories"] = "TITN";
}
function initStockMarket() {
StockMarket = {};
var ecorp = Locations.AevumECorp;
var ecorpStk = new Stock(ecorp, StockSymbols[ecorp], 0.5, true, 20, getRandomInt(20000, 25000));
StockMarket[ecorp] = ecorpStk;
var megacorp = Locations.Sector12MegaCorp;
var megacorpStk = new Stock(megacorp, StockSymbols[megacorp], 0.5, true, 20, getRandomInt(25000, 33000));
StockMarket[megacorp] = megacorpStk;
var blade = Locations.Sector12BladeIndustries;
var bladeStk = new Stock(blade, StockSymbols[blade], 0.75, true, 16, getRandomInt(15000, 22000));
StockMarket[blade] = bladeStk;
var clarke = Locations.AevumClarkeIncorporated;
var clarkeStk = new Stock(clarke, StockSymbols[clarke], 0.7, true, 15, getRandomInt(15000, 20000));
StockMarket[clarke] = clarkeStk;
var omnitek = Locations.VolhavenOmniTekIncorporated;
var omnitekStk = new Stock(omnitek, StockSymbols[omnitek], 0.65, true, 15, getRandomInt(35000, 40000));
StockMarket[omnitek] = omnitekStk;
var foursigma = Locations.Sector12FourSigma;
var foursigmaStk = new Stock(foursigma, StockSymbols[foursigma], 1.25, true, 20, getRandomInt(75000, 80000));
StockMarket[foursigma] = foursigmaStk;
var kuaigong = Locations.ChongqingKuaiGongInternational;
var kuaigongStk = new Stock(kuaigong, StockSymbols[kuaigong], 0.8, true, 12, getRandomInt(20000, 24000));
StockMarket[kuaigong] = kuaigongStk;
var fulcrum = Locations.AevumFulcrumTechnologies;
var fulcrumStk = new Stock(fulcrum, StockSymbols[fulcrum], 1.25, true, 21, getRandomInt(30000, 35000));
StockMarket[fulcrum] = fulcrumStk;
var storm = Locations.IshimaStormTechnologies;
var stormStk = new Stock(storm, StockSymbols[storm], 0.85, true, 9, getRandomInt(21000, 24000));
StockMarket[storm] = stormStk;
var defcomm = Locations.NewTokyoDefComm;
var defcommStk = new Stock(defcomm, StockSymbols[defcomm], 0.65, true, 12, getRandomInt(10000, 15000));
StockMarket[defcomm] = defcommStk;
var helios = Locations.VolhavenHeliosLabs;
var heliosStk = new Stock(helios, StockSymbols[helios], 0.6, true, 11, getRandomInt(12000, 16000));
StockMarket[helios] = heliosStk;
var vitalife = Locations.NewTokyoVitaLife;
var vitalifeStk = new Stock(vitalife, StockSymbols[vitalife], 0.75, true, 7.5, getRandomInt(10000, 12000));
StockMarket[vitalife] = vitalifeStk;
var icarus = Locations.Sector12IcarusMicrosystems;
var icarusStk = new Stock(icarus, StockSymbols[icarus], 0.65, true, 9, getRandomInt(16000, 20000));
StockMarket[icarus] = icarusStk;
var universalenergy = Locations.Sector12UniversalEnergy;
var universalenergyStk = new Stock(universalenergy, StockSymbols[universalenergy], 0.55, true, 12, getRandomInt(20000, 25000));
StockMarket[universalenergy] = universalenergyStk;
var galactic = Locations.AevumGalacticCybersystems;
var galacticStk = new Stock(galactic, StockSymbols[galactic], 0.6, true, 6, getRandomInt(8000, 10000));
StockMarket[galactic] = galacticStk;
var aerocorp = Locations.AevumAeroCorp;
var aerocorpStk = new Stock(aerocorp, StockSymbols[aerocorp], 0.6, true, 7, getRandomInt(10000, 15000));
StockMarket[aerocorp] = aerocorpStk;
var omnia = Locations.VolhavenOmniaCybersystems;
var omniaStk = new Stock(omnia, StockSymbols[omnia], 0.7, true, 4.5, getRandomInt(9000, 12000));
StockMarket[omnia] = omniaStk;
var solaris = Locations.ChongqingSolarisSpaceSystems;
var solarisStk = new Stock(solaris, StockSymbols[solaris], 0.75, true, 10, getRandomInt(18000, 24000));
StockMarket[solaris] = solarisStk;
var globalpharm = Locations.NewTokyoGlobalPharmaceuticals;
var globalpharmStk = new Stock(globalpharm, StockSymbols[globalpharm], 0.6, true, 12, getRandomInt(18000, 24000));
StockMarket[globalpharm] = globalpharmStk;
var nova = Locations.IshimaNovaMedical;
var novaStk = new Stock(nova, StockSymbols[nova], 0.75, true, 6, getRandomInt(18000, 24000));
StockMarket[nova] = novaStk;
var watchdog = Locations.AevumWatchdogSecurity;
var watchdogStk = new Stock(watchdog, StockSymbols[watchdog], 1, true, 2, getRandomInt(5000, 7500));
StockMarket[watchdog] = watchdogStk;
var lexocorp = Locations.VolhavenLexoCorp;
var lexocorpStk = new Stock(lexocorp, StockSymbols[lexocorp], 1.25, true, 3, getRandomInt(5000, 7500));
StockMarket[lexocorp] = lexocorpStk;
var rho = Locations.AevumRhoConstruction;
var rhoStk = new Stock(rho, StockSymbols[rho], 0.6, true, 1, getRandomInt(3000, 6000));
StockMarket[rho] = rhoStk;
var alpha = Locations.Sector12AlphaEnterprises;
var alphaStk = new Stock(alpha, StockSymbols[alpha], 1.05, true, 2, getRandomInt(5000, 7500));
StockMarket[alpha] = alphaStk;
var syscore = Locations.VolhavenSysCoreSecurities;
var syscoreStk = new Stock(syscore, StockSymbols[syscore], 1.25, true, 0, getRandomInt(4000, 7000))
StockMarket[syscore] = syscoreStk;
var computek = Locations.VolhavenCompuTek;
var computekStk = new Stock(computek, StockSymbols[computek], 0.9, true, 0, getRandomInt(2000, 5000));
StockMarket[computek] = computekStk;
var netlink = Locations.AevumNetLinkTechnologies;
var netlinkStk = new Stock(netlink, StockSymbols[netlink], 1, true, 1, getRandomInt(2000, 4000));
StockMarket[netlink] = netlinkStk;
var omega = Locations.IshimaOmegaSoftware;
var omegaStk = new Stock(omega, StockSymbols[omega], 1, true, 0.5, getRandomInt(3000, 6000));
StockMarket[omega] = omegaStk;
var fns = Locations.Sector12FoodNStuff;
var fnsStk = new Stock(fns, StockSymbols[fns], 0.75, false, 1, getRandomInt(1000, 4000));
StockMarket[fns] = fnsStk;
var sigmacosm = "Sigma Cosmetics";
var sigmacosmStk = new Stock(sigmacosm, StockSymbols[sigmacosm], 0.9, true, 0, getRandomInt(2000, 3000));
StockMarket[sigmacosm] = sigmacosmStk;
var joesguns = "Joes Guns";
var joesgunsStk = new Stock(joesguns, StockSymbols[joesguns], 1, true, 1, getRandomInt(500, 1000));
StockMarket[joesguns] = joesgunsStk;
var catalyst = "Catalyst Ventures";
var catalystStk = new Stock(catalyst, StockSymbols[catalyst], 1.25, true, 0, getRandomInt(1000, 1500));
StockMarket[catalyst] = catalystStk;
var unitalife = "UnitaLife Group";
var unitalifeStk = new Stock(unitalife, StockSymbols[unitalife], 0.75, true, 8, getRandomInt(10000, 15000));
StockMarket[unitalife] = unitalifeStk;
var zeus = "Zeus Medical";
var zeusStk = new Stock(zeus, StockSymbols[zeus], 0.6, true, 9, getRandomInt(20000, 25000));
StockMarket[zeus] = zeusStk;
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;
var titanlabs = "Titan Laboratories";
var titanlabsStk = new Stock(titanlabs, StockSymbols[titanlabs], 0.6, true, 11, getRandomInt(15000, 20000));
StockMarket[titanlabs] = titanlabsStk;
}
function initSymbolToStockMap() {
for (var name in StockSymbols) {
if (StockSymbols.hasOwnProperty(name)) {
var stock = StockMarket[name];
if (stock == null) {
console.log("ERROR finding stock");
continue;
}
var symbol = StockSymbols[name];
SymbolToStockMap[symbol] = stock;
}
}
}
//Returns true if successful, false otherwise
function buyStock(stock, shares) {
if (stock == null || shares < 0) {
dialogBoxCreate("Failed to buy stock. This may be a bug, contact developer");
return false;
}
shares = Math.round(shares);
var totalPrice = stock.price * shares;
if (Player.money < totalPrice + CONSTANTS.StockMarketCommission) {
dialogBoxCreate("You do not have enough money to purchase this. You need $" +
formatNumber(totalPrice + CONSTANTS.StockMarketCommission, 2).toString() + ".");
return false;
}
var origTotal = stock.playerShares * stock.playerAvgPx;
Player.loseMoney(totalPrice + CONSTANTS.StockMarketCommission);
var newTotal = origTotal + totalPrice;
stock.playerShares += shares;
stock.playerAvgPx = newTotal / stock.playerShares;
updateStockPlayerPosition(stock);
dialogBoxCreate("Bought " + formatNumber(shares, 0) + " shares of " + stock.symbol + " at $" +
formatNumber(stock.price, 2) + " per share. You also paid $" +
formatNumber(CONSTANTS.StockMarketCommission, 2) + " in commission fees.");
return true;
}
//Returns true if successful and false otherwise
function sellStock(stock, shares) {
if (stock == null || shares < 0) {
dialogBoxCreate("Failed to sell stock. This may be a bug, contact developer");
return false;
}
if (shares > stock.playerShares) {shares = stock.playerShares;}
var gains = stock.price * shares - CONSTANTS.StockMarketCommission;
Player.gainMoney(gains);
stock.playerShares -= shares;
if (stock.playerShares == 0) {
stock.playerAvgPx = 0;
}
updateStockPlayerPosition(stock);
dialogBoxCreate("Sold " + formatNumber(shares, 0) + " shares of " + stock.symbol + " at $" +
formatNumber(stock.price, 2) + " per share. After commissions, you gained " +
"a total of $" + formatNumber(gains, 2));
return true;
}
function updateStockPrices() {
var v = Math.random();
for (var name in StockMarket) {
if (StockMarket.hasOwnProperty(name)) {
var stock = StockMarket[name];
var av = (v * stock.mv) / 100;
if (isNaN(av)) {av = .02;}
var chc = 50;
if (stock.b) {
chc = (chc + stock.otlkMag)/100;
if (isNaN(chc)) {chc = 0.5;}
} else {
chc = (chc - stock.otlkMag)/100;
if (isNaN(chc)) {chc = 0.5;}
}
var c = Math.random();
if (c < chc) {
stock.price *= (1 + av);
if (Engine.currentPage == Engine.Page.StockMarket) {
updateStockTicker(stock, true);
}
} else {
stock.price /= (1 + av);
if (Engine.currentPage == Engine.Page.StockMarket) {
updateStockTicker(stock, false);
}
}
var otlkMagChange = stock.otlkMag * av;
if (stock.otlkMag <= 0.1) {
otlkMagChange = 1;
}
if (c < 0.5) {
stock.otlkMag += otlkMagChange;
} else {
stock.otlkMag -= otlkMagChange;
}
if (stock.otlkMag < 0) {
stock.otlkMag *= -1;
stock.b = !stock.b;
}
}
}
}
var stockMarketContentCreated = false;
function displayStockMarketContent() {
if (Player.hasWseAccount == null) {Player.hasWseAccount = false;}
if (Player.hasTixApiAccess == null) {Player.hasTixApiAccess = false;}
var wseAccountButton = clearEventListeners("stock-market-buy-account");
wseAccountButton.innerText = "Buy WSE Account - $" + formatNumber(CONSTANTS.WSEAccountCost, 2).toString()
if (!Player.hasWseAccount && Player.money >= CONSTANTS.WSEAccountCost) {
wseAccountButton.setAttribute("class", "a-link-button");
} else {
wseAccountButton.setAttribute("class", "a-link-button-inactive");
}
wseAccountButton.addEventListener("click", function() {
Player.hasWseAccount = true;
initStockMarket();
Player.loseMoney(CONSTANTS.WSEAccountCost);
displayStockMarketContent();
return false;
});
var stockList = document.getElementById("stock-market-list");
if (stockList == null) {return;}
if (!Player.hasWseAccount) {
stockMarketContentCreated = false;
while (stockList.firstChild) {
stockList.removeChild(stockList.firstChild);
}
return;
}
if (!stockMarketContentCreated && Player.hasWseAccount) {
console.log("Creating Stock Market UI");
document.getElementById("stock-market-commission").innerText =
"Commission Fees: Every transaction you make has a $" +
formatNumber(CONSTANTS.StockMarketCommission, 2) + " commission fee.<br><br>" +
"WARNING: When you reset after installing Augmentations, the Stock Market is reset. " +
"This means all your positions are lost, so make sure to sell your stocks before installing " +
"Augmentations!";
var hdrLi = document.createElement("li");
var hdrName = document.createElement("p");
var hdrSym = document.createElement("p");
var hdrPrice = document.createElement("p");
var hdrQty = document.createElement("p");
var hdrBuySell = document.createElement("p")
var hdrAvgPrice = document.createElement("p");
var hdrShares = document.createElement("p");
var hdrReturn = document.createElement("p");
hdrName.style.display = "inline-block";
hdrName.innerText = "Stock Name";
hdrName.style.width = "8%";
hdrSym.style.display = "inline-block";
hdrSym.innerText = "Symbol";
hdrSym.style.width = "4%";
hdrPrice.style.display = "inline-block";
hdrPrice.innerText = "Price";
hdrPrice.style.width = "8%";
hdrQty.style.display = "inline-block";
hdrQty.innerText = "Quantity";
hdrQty.style.width = "3%";
hdrBuySell.style.display = "inline-block";
hdrBuySell.innerText = "Buy/Sell";
hdrBuySell.style.width = "5%";
hdrAvgPrice.style.display = "inline-block";
hdrAvgPrice.innerText = "Avg price of owned shares";
hdrAvgPrice.style.width = "7.5%";
hdrShares.style.display = "inline-block";
hdrShares.innerText = "Shares owned";
hdrShares.style.width = "4%";
hdrReturn.style.display = "inline-block";
hdrReturn.innerText = "Total Return";
hdrReturn.style.width = "6%";
hdrLi.appendChild(hdrName);
hdrLi.appendChild(hdrSym);
hdrLi.appendChild(hdrPrice);
hdrLi.appendChild(hdrQty);
hdrLi.appendChild(hdrBuySell);
hdrLi.appendChild(hdrAvgPrice);
hdrLi.appendChild(hdrShares);
hdrLi.appendChild(hdrReturn);
stockList.appendChild(hdrLi);
for (var name in StockMarket) {
if (StockMarket.hasOwnProperty(name)) {
(function() {
var stock = StockMarket[name];
var li = document.createElement("li");
var stkName = document.createElement("p");
var stkSym = document.createElement("p");
var stkPrice = document.createElement("p");
var qtyInput = document.createElement("input");
var buyButton = document.createElement("span");
var sellButton = document.createElement("span");
var avgPriceTxt = document.createElement("p");
var sharesTxt = document.createElement("p");
var returnTxt = document.createElement("p");
var tickerId = "stock-market-ticker-" + stock.symbol;
stkName.setAttribute("id", tickerId + "-name");
stkSym.setAttribute("id", tickerId + "-sym");
stkPrice.setAttribute("id", tickerId + "-price");
stkName.style.display = "inline-block";
stkName.style.width = "8%";
stkSym.style.display = "inline-block";
stkSym.style.width = "4%";
stkPrice.style.display = "inline-block";
stkPrice.style.width = "9%";
li.setAttribute("display", "inline-block");
qtyInput.setAttribute("type", "text");
qtyInput.setAttribute("id", tickerId + "-qty-input");
qtyInput.setAttribute("class", "stock-market-qty-input");
qtyInput.setAttribute("onkeypress", 'return event.charCode >= 48 && event.charCode <= 57');
qtyInput.style.width = "3%";
qtyInput.style.display = "inline-block";
buyButton.innerHTML = "Buy";
buyButton.setAttribute("class", "stock-market-buy-sell-button");
buyButton.style.width = "3%";
buyButton.style.display = "inline-block";
buyButton.addEventListener("click", function() {
var shares = document.getElementById(tickerId + "-qty-input").value;
shares = Number(shares);
if (isNaN(shares)) {return false;}
buyStock(stock, shares);
});
sellButton.innerHTML = "Sell";
sellButton.setAttribute("class", "stock-market-buy-sell-button");
sellButton.style.width = "3%";
sellButton.style.display = "inline-block";
sellButton.addEventListener("click", function() {
var shares = document.getElementById(tickerId + "-qty-input").value;
shares = Number(shares);
if (isNaN(shares)) {return false;}
sellStock(stock, shares);
});
avgPriceTxt.setAttribute("id", tickerId + "-avgprice");
avgPriceTxt.style.display = "inline-block";
avgPriceTxt.style.width = "8%";
avgPriceTxt.style.color = "white";
sharesTxt.setAttribute("id", tickerId + "-shares");
sharesTxt.style.display = "inline-block";
sharesTxt.style.width = "4%";
sharesTxt.style.color = "white";
returnTxt.setAttribute("id", tickerId + "-return");
returnTxt.style.display = "inline-block";
returnTxt.style.width = "6%";
returnTxt.style.color = "white";
li.appendChild(stkName);
li.appendChild(stkSym);
li.appendChild(stkPrice);
li.appendChild(qtyInput);
li.appendChild(buyButton);
li.appendChild(sellButton);
li.appendChild(avgPriceTxt);
li.appendChild(sharesTxt);
li.appendChild(returnTxt);
stockList.appendChild(li);
updateStockTicker(stock, true);
updateStockPlayerPosition(stock);
}()); //Immediate invocation
}//End if
}
stockMarketContentCreated = true;
}
}
//'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");
if (stkName == null || stkSym == null || stkPrice == null) {
console.log("ERROR, couldn't find elements with tickerId " + tickerId);
return;
}
stkName.innerText = stock.name;
stkSym.innerText = stock.symbol;
stkPrice.innerText = "$" + formatNumber(stock.price, 2).toString();
var returnTxt = document.getElementById(tickerId + "-return");
var totalCost = stock.playerShares * stock.playerAvgPx;
var gains = (stock.price - stock.playerAvgPx) * stock.playerShares;
var percentageGains = gains / totalCost;
if (totalCost > 0) {
returnTxt.innerText = "$" + formatNumber(gains, 2) + " (" +
formatNumber(percentageGains * 100, 2) + "%)";
} else {
returnTxt.innerText = "N/A";
}
if (increase) {
stkName.style.color = "#66ff33";
stkSym.style.color = "#66ff33";
stkPrice.style.color = "#66ff33";
} else {
stkName.style.color = "red";
stkSym.style.color = "red";
stkPrice.style.color = "red";
}
}
function updateStockPlayerPosition(stock) {
var tickerId = "stock-market-ticker-" + stock.symbol;
var avgPriceTxt = document.getElementById(tickerId + "-avgprice");
var sharesTxt = document.getElementById(tickerId + "-shares");
if (avgPriceTxt == null || sharesTxt == null) {
dialogBoxCreate("Could not find element for player positions for stock " +
stock.symbol + ". This is a bug please contact developer");
return;
}
avgPriceTxt.innerText = "$" + formatNumber(stock.playerAvgPx, 2);
sharesTxt.innerText = stock.playerShares.toString();
}

@ -25,7 +25,7 @@ var Engine = {
tutorialScriptsButton: null,
tutorialNetscriptButton: null,
tutorialTravelingButton: null,
tutorialJobsButton: null,
tutorialCompaniesButton: null,
tutorialFactionsButton: null,
tutorialAugmentationsButton: null,
tutorialBackButton: null,
@ -55,6 +55,7 @@ var Engine = {
augmentationsContent: null,
tutorialContent: null,
infiltrationContent: null,
stockMarketContent: null,
locationContent: null,
workInProgressContent: null,
@ -80,6 +81,8 @@ var Engine = {
Tutorial: "Tutorial",
Location: "Location",
workInProgress: "WorkInProgress",
Infiltration: "Infiltration",
StockMarket: "StockMarket",
},
currentPage: null,
@ -111,7 +114,6 @@ var Engine = {
document.getElementById("script-editor-text").value = code;
}
document.getElementById("script-editor-text").focus();
Engine.currentPage = Engine.Page.ScriptEditor;
},
@ -119,7 +121,6 @@ var Engine = {
Engine.hideAllContent();
Engine.Display.activeScriptsContent.style.visibility = "visible";
setActiveScriptsClickHandlers();
Engine.currentPage = Engine.Page.ActiveScripts;
},
@ -127,7 +128,6 @@ var Engine = {
Engine.hideAllContent();
Engine.Display.hacknetNodesContent.style.visibility = "visible";
displayHacknetNodesContent();
Engine.currentPage = Engine.Page.HacknetNodes;
},
@ -135,7 +135,6 @@ var Engine = {
Engine.hideAllContent();
Engine.Display.worldContent.style.visibility = "visible";
Engine.displayWorldInfo();
Engine.currentPage = Engine.Page.World;
},
@ -143,7 +142,6 @@ var Engine = {
Engine.hideAllContent();
Engine.Display.createProgramContent.style.visibility = "visible";
displayCreateProgramContent();
Engine.currentPage = Engine.Page.CreateProgram;
},
@ -151,14 +149,12 @@ var Engine = {
Engine.hideAllContent();
Engine.Display.factionsContent.style.visibility = "visible";
Engine.displayFactionsInfo();
Engine.currentPage = Engine.Page.Factions;
},
loadFactionContent: function() {
Engine.hideAllContent();
Engine.Display.factionContent.style.visibility = "visible";
Engine.currentPage = Engine.Page.Faction;
},
@ -166,7 +162,6 @@ var Engine = {
Engine.hideAllContent();
Engine.Display.augmentationsContent.style.visibility = "visible";
Engine.displayAugmentationsContent();
Engine.currentPage = Engine.Page.Augmentations;
},
@ -174,7 +169,6 @@ var Engine = {
Engine.hideAllContent();
Engine.Display.tutorialContent.style.visibility = "visible";
Engine.displayTutorialContent();
Engine.currentPage = Engine.Page.Tutorial;
},
@ -182,21 +176,30 @@ var Engine = {
Engine.hideAllContent();
Engine.Display.locationContent.style.visibility = "visible";
displayLocationContent();
Engine.currentPage = Engine.Page.Location;
},
loadWorkInProgressContent: function() {
Engine.hideAllContent();
var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "hidden";
Engine.Display.workInProgressContent.style.visibility = "visible";
Engine.currentPage = Engine.Page.WorkInProgress;
},
loadInfiltrationContent: function() {
Engine.hideAllContent();
Engine.Display.infiltrationContent.style.visibility = "visible";
Engine.currentPage = Engine.Page.Infiltration;
},
loadStockMarketContent: function() {
Engine.hideAllContent();
Engine.Display.stockMarketContent.style.visibility = "visible";
displayStockMarketContent();
Engine.currentPage = Engine.Page.StockMarket;
},
//Helper function that hides all content
hideAllContent: function() {
Engine.Display.terminalContent.style.visibility = "hidden";
@ -213,6 +216,8 @@ var Engine = {
Engine.Display.tutorialContent.style.visibility = "hidden";
Engine.Display.locationContent.style.visibility = "hidden";
Engine.Display.workInProgressContent.style.visibility = "hidden";
Engine.Display.infiltrationContent.style.visibility = "hidden";
Engine.Display.stockMarketContent.style.visibility = "hidden";
//Location lists
Engine.aevumLocationsList.style.display = "none";
@ -224,8 +229,10 @@ var Engine = {
},
displayCharacterOverviewInfo: function() {
if (Player.hp == null) {Player.hp = Player.max_hp;}
document.getElementById("character-overview-text").innerHTML =
("Money: $" + formatNumber(Player.money, 2) + "<br>" +
("Hp: " + Player.hp + " / " + Player.max_hp + "<br>" +
"Money: $" + formatNumber(Player.money, 2) + "<br>" +
"Hack: " + (Player.hacking_skill).toLocaleString() + "<br>" +
"Str: " + (Player.strength).toLocaleString() + "<br>" +
"Def: " + (Player.defense).toLocaleString() + "<br>" +
@ -336,6 +343,8 @@ var Engine = {
console.log("Invalid city value in Player object!");
break;
}
document.getElementById("generic-locations-list").style.display = "inline";
},
displayFactionsInfo: function() {
@ -441,7 +450,7 @@ var Engine = {
Engine.Clickables.tutorialScriptsButton.style.display = "block";
Engine.Clickables.tutorialNetscriptButton.style.display = "block";
Engine.Clickables.tutorialTravelingButton.style.display = "block";
Engine.Clickables.tutorialJobsButton.style.display = "block";
Engine.Clickables.tutorialCompaniesButton.style.display = "block";
Engine.Clickables.tutorialFactionsButton.style.display = "block";
Engine.Clickables.tutorialAugmentationsButton.style.display = "block";
@ -457,7 +466,7 @@ var Engine = {
Engine.Clickables.tutorialScriptsButton.style.display = "none";
Engine.Clickables.tutorialNetscriptButton.style.display = "none";
Engine.Clickables.tutorialTravelingButton.style.display = "none";
Engine.Clickables.tutorialJobsButton.style.display = "none";
Engine.Clickables.tutorialCompaniesButton.style.display = "none";
Engine.Clickables.tutorialFactionsButton.style.display = "none";
Engine.Clickables.tutorialAugmentationsButton.style.display = "none";
@ -548,6 +557,7 @@ var Engine = {
checkFactionInvitations: 100, //Check whether you qualify for any faction invitations every 5 minutes
passiveFactionGrowth: 600,
messages: 300,
stockTick: 50, //Update stock prices
},
decrementAllCounters: function(numCycles = 1) {
@ -622,6 +632,13 @@ var Engine = {
checkForMessagesToSend();
Engine.Counters.messages = 300;
}
if (Engine.Counters.stockTick <= 0) {
if (Player.hasWseAccount) {
updateStockPrices();
}
Engine.Counters.stockTick = 50;
}
},
/* Calculates the hack progress for a manual (non-scripted) hack and updates the progress bar/time accordingly */
@ -684,6 +701,10 @@ var Engine = {
Engine.init(); //Initialize buttons, work, etc.
CompanyPositions.init();
initAugmentations(); //Also calls Player.reapplyAllAugmentations()
initStockSymbols();
if (Player.hasWseAccount) {
initSymbolToStockMap();
}
//Calculate the number of cycles have elapsed while offline
Engine._lastUpdate = new Date().getTime();
@ -740,6 +761,7 @@ var Engine = {
CompanyPositions.init();
initAugmentations();
initMessages();
initStockSymbols();
//Start interactive tutorial
iTutorialStart();
@ -788,6 +810,10 @@ var Engine = {
Engine.Display.infiltrationContent = document.getElementById("infiltration-container");
Engine.Display.infiltrationContent.style.visibility = "hidden";
Engine.Display.stockMarketContent = document.getElementById("stock-market-container");
Engine.Display.stockMarketContent.style.visibility = "hidden";
//Character info
Engine.Display.characterInfo = document.getElementById("character-info");
@ -844,9 +870,9 @@ var Engine = {
Engine.displayTutorialPage(CONSTANTS.TutorialTravelingText);
});
Engine.Clickables.tutorialJobsButton = document.getElementById("tutorial-jobs-link");
Engine.Clickables.tutorialJobsButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialJobsText);
Engine.Clickables.tutorialCompaniesButton = document.getElementById("tutorial-jobs-link");
Engine.Clickables.tutorialCompaniesButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialCompaniesText);
});
Engine.Clickables.tutorialFactionsButton = document.getElementById("tutorial-factions-link");

90
utils/InfiltrationBox.js Normal file

@ -0,0 +1,90 @@
/* InfiltrationBox.js */
infiltrationBoxClose = function() {
var box = document.getElementById("infiltration-box-container");
box.style.display = "none";
}
infiltrationBoxOpen = function() {
var box = document.getElementById("infiltration-box-container");
box.style.display = "block";
}
infiltrationSetText = function(txt) {
var textBox = document.getElementById("infiltration-box-text");
textBox.innerHTML = txt;
}
//ram argument is in GB
infiltrationBoxCreate = function(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>" +
formatNumber(inst.chaExpGained, 3) + " cha exp<br>");
return;
}
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(totalValue, 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] +
"'>" + 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>" +
formatNumber(inst.chaExpGained, 3) + " cha exp<br>");
infiltrationBoxClose();
return false;
});
}, 750);
var factionButton = clearEventListeners("infiltration-box-faction");
setTimeout(function() {
factionButton.addEventListener("click", function() {
var facName = selector.options[selector.selectedIndex].value;
var faction = Factions[facName];
if (faction == null) {
dialogBoxCreate("Error finding faction. This is a bug please report to developer");
return false;
}
faction.playerReputation += totalValue;
dialogBoxCreate("You gave the classified information you stole from " + inst.companyName +
" to " + facName + " and gained " + formatNumber(totalValue, 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();
}