mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2025-03-08 03:24:48 +01:00
13
.editorconfig
Normal file
13
.editorconfig
Normal file
@ -0,0 +1,13 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[package.json]
|
||||
indent_size = 2
|
||||
|
||||
[md]
|
||||
trim_trailing_whitespace = false
|
@ -1,2 +1,12 @@
|
||||
$fontFamily: 'Lucida Console', 'Lucida Sans Unicode', 'Fira Mono', 'Consolas', 'Courier New', Courier, monospace, 'Times New Roman';
|
||||
$defaultFontSize: 16px;
|
||||
|
||||
/* COLORS */
|
||||
$hacky-green: #adff2f;
|
||||
|
||||
/* Attributes */
|
||||
$my-stat-hp-color: #dd3434;
|
||||
$my-stat-money-color: #ffd700;
|
||||
$my-stat-hack-color: $hacky-green;
|
||||
$my-stat-cha-color: #a671d1;
|
||||
$my-stat-int-color: #6495ed;
|
||||
|
@ -27,14 +27,14 @@
|
||||
}
|
||||
|
||||
/* Action & Skills panel navigation button */
|
||||
%bladburner-nav-button {
|
||||
%bladeburner-nav-button {
|
||||
border: 1px solid #fff;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.bladeburner-nav-button {
|
||||
@extend %bladburner-nav-button;
|
||||
@extend %bladeburner-nav-button;
|
||||
|
||||
color: #fff;
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
}
|
||||
|
||||
.bladeburner-nav-button-inactive {
|
||||
@extend %bladburner-nav-button;
|
||||
@extend %bladeburner-nav-button;
|
||||
|
||||
text-decoration: none;
|
||||
background-color: #555;
|
||||
|
@ -11,11 +11,11 @@
|
||||
position: absolute; /* Stay in place */
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 400px; /* Full height */
|
||||
height: 450px;
|
||||
padding: 10px;
|
||||
border: 5px solid #fff;
|
||||
width: 20%;
|
||||
overflow: auto; /* Enable scroll if needed */
|
||||
width: 23%;
|
||||
overflow: hidden;
|
||||
background-color: #444; /* Fallback color */
|
||||
color: #fff;
|
||||
|
||||
@ -29,6 +29,9 @@
|
||||
margin: 4px;
|
||||
color: #fff;
|
||||
background-color: #444;
|
||||
font-size: $defaultFontSize * 0.875;
|
||||
max-height: 350px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#interactive-tutorial-exit,
|
||||
@ -38,7 +41,7 @@
|
||||
@include boxShadow(1px 1px 3px #000);
|
||||
|
||||
color: #aaa;
|
||||
font-size: $defaultFontSize * 1.25;
|
||||
font-size: $defaultFontSize * 1.125;
|
||||
font-weight: bold;
|
||||
background-color: #000;
|
||||
|
||||
@ -50,6 +53,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#interactive-tutorial-exit {
|
||||
float: left;
|
||||
}
|
||||
@ -58,6 +62,16 @@
|
||||
margin-right: 20%;
|
||||
float: right;
|
||||
}
|
||||
*/
|
||||
#interactive-tutorial-exit {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#interactive-tutorial-back {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#interactive-tutorial-next {
|
||||
float: right;
|
||||
|
@ -22,17 +22,15 @@
|
||||
#script-editor-container {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#javascript-editor {
|
||||
margin: 10px;
|
||||
|
||||
height: 80%;
|
||||
width: 100%;
|
||||
margin-left: 6px;
|
||||
|
||||
padding-left: 6px;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
|
||||
border: 2px solid var(--my-highlight-color);
|
||||
z-index: 1;
|
||||
font-family: $fontFamily;
|
||||
@ -101,9 +99,7 @@
|
||||
resize: none;
|
||||
color: #fff;
|
||||
margin: 4px;
|
||||
|
||||
padding: 2px;
|
||||
|
||||
border: 2px solid var(--my-highlight-color);
|
||||
}
|
||||
|
||||
@ -225,15 +221,15 @@
|
||||
.active-scripts-script-header:after {
|
||||
content: '\02795'; /* "plus" sign (+) */
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
color: var(--my-font-color);
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 var(--my-font-color);
|
||||
}
|
||||
|
||||
.active-scripts-script-header.active:after {
|
||||
content: "\2796"; /* "minus" sign (-) */
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
color: var(--my-font-color);
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
}
|
||||
@ -244,16 +240,13 @@
|
||||
width: auto;
|
||||
display: none;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.active-scripts-script-panel p,
|
||||
.active-scripts-script-panel h2,
|
||||
.active-scripts-script-panel ul,
|
||||
.active-scripts-script-panel li {
|
||||
background-color: #555;
|
||||
width: auto;
|
||||
color: #fff;
|
||||
margin-left: 5%;
|
||||
p, h2, ul, li {
|
||||
background-color: #555;
|
||||
width: auto;
|
||||
color: #fff;
|
||||
margin-left: 5%;
|
||||
}
|
||||
}
|
||||
|
||||
.active-scripts-button {
|
||||
@ -266,13 +259,13 @@
|
||||
margin: 4px;
|
||||
padding: 4px;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.active-scripts-button:hover,
|
||||
.active-scripts-button:focus {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hacknet Nodes */
|
||||
@ -291,6 +284,16 @@
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
&.hacknet-node {
|
||||
$boxShadowArgs: inset 0 0 8px rgba(0, 0, 0, 0.1), 0 0 16px rgba(0, 0, 0, 0.1);
|
||||
@include boxShadow($boxShadowArgs);
|
||||
|
||||
margin: 6px;
|
||||
padding: 7px;
|
||||
width: 35vw;
|
||||
border: 2px solid var(--my-highlight-color);
|
||||
}
|
||||
}
|
||||
|
||||
#hacknet-nodes-list {
|
||||
@ -316,34 +319,24 @@
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.hacknet-node {
|
||||
$boxShadowArgs: inset 0 0 8px rgba(0, 0, 0, 0.1), 0 0 16px rgba(0, 0, 0, 0.1);
|
||||
@include boxShadow($boxShadowArgs);
|
||||
|
||||
margin: 6px;
|
||||
padding: 6px;
|
||||
width: 34vw;
|
||||
border: 2px solid var(--my-highlight-color);
|
||||
}
|
||||
|
||||
.hacknet-node-container {
|
||||
display: inline-table;
|
||||
}
|
||||
|
||||
.hacknet-node-container .row {
|
||||
display: table-row;
|
||||
height: 30px;
|
||||
}
|
||||
.row {
|
||||
display: table-row;
|
||||
height: 30px;
|
||||
|
||||
.hacknet-node-container .row p {
|
||||
display: table-cell;
|
||||
}
|
||||
p {
|
||||
display: table-cell;
|
||||
}
|
||||
}
|
||||
|
||||
.hacknet-node-container .upgradable-info {
|
||||
display: inline-block;
|
||||
margin: 0 4px; /* Don't want the vertical margin/padding, just left & right */
|
||||
padding: 0 4px;
|
||||
width: $defaultFontSize * 4;
|
||||
.upgradable-info {
|
||||
display: inline-block;
|
||||
margin: 0 4px; /* Don't want the vertical margin/padding, just left & right */
|
||||
padding: 0 4px;
|
||||
width: $defaultFontSize * 4;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-page-text {
|
||||
@ -426,17 +419,14 @@
|
||||
}
|
||||
|
||||
/* Faction Augmentations */
|
||||
#faction-augmentations-container{
|
||||
#faction-augmentations-container {
|
||||
position: fixed;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#faction-augmentations-container p,
|
||||
#faction-augmentations-container a,
|
||||
#faction-augmentations-container ul,
|
||||
#faction-augmentations-container h1{
|
||||
margin: 8px;
|
||||
padding: 4px;
|
||||
p, a, ul, h1 {
|
||||
margin: 8px;
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
/* World */
|
||||
@ -451,11 +441,20 @@
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.augmentations-list button,
|
||||
.augmentations-list div {
|
||||
color: var(--my-font-color);
|
||||
padding: 8px;
|
||||
text-decoration: none;
|
||||
.augmentations-list {
|
||||
button,
|
||||
div {
|
||||
color: var(--my-font-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
div {
|
||||
padding: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tutorial */
|
||||
@ -510,11 +509,12 @@
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
#location-container * {
|
||||
#location-container > * {
|
||||
margin: 10px 5px 10px 5px;
|
||||
}
|
||||
|
||||
#location-job-reputation, #location-company-favor {
|
||||
#location-job-reputation,
|
||||
#location-company-favor {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
@ -523,6 +523,7 @@
|
||||
position: fixed;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
#infiltration-left-panel,
|
||||
#infiltration-right-panel {
|
||||
display: inline-block;
|
||||
@ -552,6 +553,25 @@
|
||||
#stock-market-container {
|
||||
position: fixed;
|
||||
padding: 6px;
|
||||
|
||||
p {
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
}
|
||||
a {
|
||||
font-size: $defaultFontSize * 0.875;
|
||||
}
|
||||
h2 {
|
||||
margin-top: 10px;
|
||||
margin-left: 10px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Change font size of Stock TIcker headers */
|
||||
#stock-market-list li {
|
||||
button {
|
||||
font-size: $defaultFontSize;
|
||||
}
|
||||
}
|
||||
|
||||
#stock-market-container p {
|
||||
@ -564,6 +584,11 @@
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#stock-market-watchlist-filter {
|
||||
width: 50%;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.stock-market-input {
|
||||
display: inline-block;
|
||||
padding: 4px;
|
||||
|
@ -8,6 +8,8 @@
|
||||
z-index: 10; /* Sit on top */
|
||||
left: 0;
|
||||
top: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
@ -16,10 +18,21 @@
|
||||
|
||||
.popup-box-content {
|
||||
background-color: var(--my-background-color);
|
||||
margin: 15% auto;
|
||||
padding: 12px;
|
||||
border: 5px solid var(--my-highlight-color);
|
||||
width: 70%;
|
||||
max-height: 80%;
|
||||
/*
|
||||
margin: auto;
|
||||
height:auto;
|
||||
max-height:80%;
|
||||
position:absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
bottom:0;
|
||||
right:0;
|
||||
*/
|
||||
overflow-y: auto;
|
||||
color: var(--my-font-color);
|
||||
}
|
||||
|
||||
@ -141,11 +154,12 @@
|
||||
|
||||
#game-options-content {
|
||||
background-color: var(--my-background-color);
|
||||
margin: 15% auto;
|
||||
padding: 10px;
|
||||
border: 5px solid var(--my-highlight-color);
|
||||
width: 60%;
|
||||
color: var(--my-font-color);
|
||||
width: 80%;
|
||||
max-height: 80%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#game-options-left-panel,
|
||||
|
207
css/styles.scss
207
css/styles.scss
@ -3,10 +3,11 @@
|
||||
|
||||
@import "reset";
|
||||
|
||||
:root{
|
||||
:root {
|
||||
--my-font-color: #6f3;
|
||||
--my-background-color: #000;
|
||||
--my-highlight-color: #fff;
|
||||
--my-prompt-color: #f92672;
|
||||
}
|
||||
|
||||
body {
|
||||
@ -83,7 +84,7 @@ tr:focus {
|
||||
display: block;
|
||||
color: #e6e6e6;
|
||||
background-color: #555;
|
||||
padding: 16px;
|
||||
padding: 12px 8px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@ -105,21 +106,36 @@ tr:focus {
|
||||
background-color: #aaa;
|
||||
}
|
||||
|
||||
#hacking-menu-header-li,
|
||||
#character-menu-header-li,
|
||||
#world-menu-header-li,
|
||||
#help-menu-header-li {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Accordion Outline */
|
||||
.mainmenu-accordion-header {
|
||||
outline: 2px solid #fff;
|
||||
}
|
||||
|
||||
/* Plus and minus signs */
|
||||
.mainmenu-accordion-header:after {
|
||||
content: '\02795';
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
color: #fff;
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.mainmenu-accordion-header.opened:after {
|
||||
content: "\2796";
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
position: absolute;
|
||||
bottom: 25%;
|
||||
right: 3px;
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 #fff;
|
||||
}
|
||||
|
||||
.mainmenu-accordion-header.opened {
|
||||
background-color: #222;
|
||||
|
||||
&:after {
|
||||
content: "\2796";
|
||||
}
|
||||
}
|
||||
|
||||
/* Slide down transition */
|
||||
@ -129,11 +145,6 @@ tr:focus {
|
||||
transition: max-height 0.2s ease-out;
|
||||
}
|
||||
|
||||
/* Borders */
|
||||
.mainmenu-accordion-header {
|
||||
border: 2px solid #fff;
|
||||
}
|
||||
|
||||
/* Make html links ("a" elements) nice looking buttons with this class */
|
||||
a:link,
|
||||
a:visited {
|
||||
@ -144,7 +155,7 @@ a:visited {
|
||||
text-decoration: none;
|
||||
background-color: #555;
|
||||
color: #fff;
|
||||
padding: 5px;
|
||||
padding: 3px 5px;
|
||||
margin: 5px;
|
||||
border: 1px solid #333;
|
||||
|
||||
@ -167,7 +178,7 @@ a:visited {
|
||||
text-decoration: none;
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
padding: 5px;
|
||||
padding: 3px 5px;
|
||||
margin: 5px;
|
||||
border: 1px solid #333;
|
||||
cursor: default;
|
||||
@ -188,7 +199,7 @@ a:visited {
|
||||
text-decoration: none;
|
||||
background-color: #0a0;
|
||||
color: #fff;
|
||||
padding: 5px;
|
||||
padding: 3px 5px;
|
||||
margin: 5px;
|
||||
border: 1px solid #0a0;
|
||||
cursor: default;
|
||||
@ -218,9 +229,9 @@ a:visited {
|
||||
#create-program-tab {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#create-program-notification {
|
||||
font-size: $defaultFontSize * 0.625;
|
||||
|
||||
position: absolute; /* Position the badge within the relatively positioned button */
|
||||
top: 0;
|
||||
right: 0;
|
||||
@ -310,11 +321,23 @@ a:visited {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.help-tip:hover {
|
||||
.help-tip-big {
|
||||
content: '?';
|
||||
padding: 3px;
|
||||
margin-left: 3px;
|
||||
color: #fff;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 8px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.help-tip:hover,
|
||||
.help-tip-big:hover {
|
||||
background-color: #888;
|
||||
}
|
||||
|
||||
.help-tip:active {
|
||||
.help-tip:active,
|
||||
.help-tip-big:active {
|
||||
@include boxShadow(inset 0 1px 4px rgba(0, 0, 0, 0.6));
|
||||
}
|
||||
|
||||
@ -352,7 +375,7 @@ a:visited {
|
||||
|
||||
/* Blinking Cursor */
|
||||
/* ----- blinking cursor animation ----- */
|
||||
.typed-cursor{
|
||||
.typed-cursor {
|
||||
opacity: 1;
|
||||
-webkit-animation: blink 0.95s infinite;
|
||||
-moz-animation: blink 0.95s infinite;
|
||||
@ -388,24 +411,21 @@ a:visited {
|
||||
}
|
||||
|
||||
/* Status text */
|
||||
@-webkit-keyframes status-text{
|
||||
from{
|
||||
@-webkit-keyframes status-text {
|
||||
from {
|
||||
opacity: 1;
|
||||
top: 0;
|
||||
}
|
||||
to{
|
||||
to {
|
||||
opacity: 0;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.status-text{
|
||||
display: inline;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
-webkit-animation: status-text 3s 1;
|
||||
background-color: transparent;
|
||||
.status-text {
|
||||
display: inline-block;
|
||||
height: 15%;
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
-webkit-animation: status-text 3s 1;
|
||||
}
|
||||
|
||||
#status-text-container {
|
||||
@ -413,14 +433,14 @@ a:visited {
|
||||
}
|
||||
|
||||
#status-text {
|
||||
font-size: $defaultFontSize * 1.25;
|
||||
color: #fff;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 4px;
|
||||
margin-right: 14px;
|
||||
background-color: transparent;
|
||||
z-index: 2;
|
||||
font-size: $defaultFontSize * 1.25;
|
||||
bottom: 0;
|
||||
color: #fff;
|
||||
margin-right: 14px;
|
||||
padding: 4px;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
@ -428,47 +448,78 @@ a:visited {
|
||||
#character-overview-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#character-overview-container {
|
||||
display: none;
|
||||
position: absolute; /* Stay in place */
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: auto; /* Full height */
|
||||
padding: 8px;
|
||||
padding: 10px 2px;
|
||||
border: 2px solid var(--my-highlight-color);
|
||||
width: 19%;
|
||||
width: auto;
|
||||
max-width: 280px;
|
||||
overflow: auto; /* Enable scroll if needed */
|
||||
background-color: #444; /* Fallback color */
|
||||
background-color: #393636; /* Fallback color */
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#character-overview-text {
|
||||
color: #fff;
|
||||
background-color: #444;
|
||||
color: #faffdf;
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 2px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.character-stat-text {
|
||||
color: #fff;
|
||||
background-color: #444;
|
||||
}
|
||||
.character-stat-cell {
|
||||
|
||||
.character-stat-cell {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#character-hack-wrapper td,
|
||||
#character-agi-wrapper td {
|
||||
border-bottom: 1px #aaa solid;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
#character-str-wrapper td,
|
||||
#character-cha-wrapper td {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#character-hp-wrapper { color: $my-stat-hp-color; }
|
||||
#character-money-wrapper { color: $my-stat-money-color; }
|
||||
#character-hack-wrapper { color: $my-stat-hack-color; }
|
||||
#character-cha-wrapper { color: $my-stat-cha-color; }
|
||||
#character-int-wrapper { color: $my-stat-int-color; }
|
||||
|
||||
#character-overview-save-button,
|
||||
#character-overview-options-button {
|
||||
@include borderRadius(12px);
|
||||
@include boxShadow(1px 1px 3px #000);
|
||||
|
||||
color: #aaa;
|
||||
color: #cecece;
|
||||
display: inline-block;
|
||||
font-size: $defaultFontSize * 0.875;
|
||||
font-weight: bold;
|
||||
height: 22px;
|
||||
height: 25px;
|
||||
background-color: #000;
|
||||
padding: 5px 8px;
|
||||
}
|
||||
|
||||
.character-quick-options {
|
||||
padding-top: 5px;
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#character-overview-save-button:hover,
|
||||
@ -480,16 +531,13 @@ a:visited {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#character-overview-options-button {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/* Scan analyze links from AutoLink */
|
||||
.scan-analyze-link {
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.scan-analyze-link:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
@ -500,37 +548,37 @@ a:visited {
|
||||
font-size: $defaultFontSize * 1.25;
|
||||
color: #fff;
|
||||
margin: 6px 6px 0 6px;
|
||||
padding: 6px;
|
||||
padding: 4px 6px;
|
||||
cursor: pointer;
|
||||
width: 80%;
|
||||
text-align: left;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
position: relative;
|
||||
|
||||
.accordion-header.active,
|
||||
.accordion-header:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
&.active,
|
||||
&:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
.accordion-header.active:hover {
|
||||
background-color: #666;
|
||||
}
|
||||
&.active:hover {
|
||||
background-color: #666;
|
||||
}
|
||||
|
||||
.accordion-header:after {
|
||||
content: '\02795'; /* "plus" sign (+) */
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
color: #fff;
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
}
|
||||
&:after {
|
||||
content: '\02795'; /* "plus" sign (+) */
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
float: right;
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 #fff;
|
||||
position: absolute;
|
||||
bottom: 3px;
|
||||
right: 6px;
|
||||
}
|
||||
|
||||
.accordion-header.active:after {
|
||||
content: "\2796"; /* "minus" sign (-) */
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
color: #fff;
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
&.active:after {
|
||||
content: "\2796"; /* "minus" sign (-) */
|
||||
}
|
||||
}
|
||||
|
||||
.accordion-panel {
|
||||
@ -542,13 +590,10 @@ a:visited {
|
||||
background-color: #555;
|
||||
overflow-y: auto;
|
||||
overflow-x: none;
|
||||
}
|
||||
|
||||
.accordion-panel div,
|
||||
.accordion-panel ul,
|
||||
.accordion-panel p,
|
||||
.accordion-panel ul > li {
|
||||
background-color: #555;
|
||||
div, ul, p, ul > li {
|
||||
background-color: #555;
|
||||
}
|
||||
}
|
||||
|
||||
/* override the global <span> styling */
|
||||
|
@ -51,6 +51,7 @@
|
||||
}
|
||||
|
||||
#terminal-input-header {
|
||||
color: var(--my-prompt-color);
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,14 @@
|
||||
color: var(--my-font-color);
|
||||
width: 99%;
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.generic-fullscreen-container-scroll {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
#work-in-progress-container {
|
||||
|
2
dist/engine.bundle.js
vendored
2
dist/engine.bundle.js
vendored
File diff suppressed because one or more lines are too long
91
dist/engine.css
vendored
91
dist/engine.css
vendored
@ -276,10 +276,21 @@ a:visited {
|
||||
border-radius: 5px;
|
||||
display: inline-block; }
|
||||
|
||||
.help-tip:hover {
|
||||
.help-tip-big {
|
||||
content: '?';
|
||||
padding: 3px;
|
||||
margin-left: 3px;
|
||||
color: #fff;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 8px;
|
||||
display: inline-block; }
|
||||
|
||||
.help-tip:hover,
|
||||
.help-tip-big:hover {
|
||||
background-color: #888; }
|
||||
|
||||
.help-tip:active {
|
||||
.help-tip:active,
|
||||
.help-tip-big:active {
|
||||
-webkit-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.6);
|
||||
-moz-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.6);
|
||||
box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.6); }
|
||||
@ -388,32 +399,29 @@ a:visited {
|
||||
/* Status text */
|
||||
@-webkit-keyframes status-text {
|
||||
from {
|
||||
opacity: 1;
|
||||
top: 0; }
|
||||
opacity: 1; }
|
||||
to {
|
||||
opacity: 0;
|
||||
top: 0; } }
|
||||
opacity: 0; } }
|
||||
|
||||
.status-text {
|
||||
display: inline;
|
||||
display: inline-block;
|
||||
height: 15%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
-webkit-animation: status-text 3s 1;
|
||||
background-color: transparent;
|
||||
height: 15%; }
|
||||
z-index: 2;
|
||||
-webkit-animation: status-text 3s 1; }
|
||||
|
||||
#status-text-container {
|
||||
background-color: transparent; }
|
||||
|
||||
#status-text {
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 4px;
|
||||
margin-right: 14px;
|
||||
background-color: transparent;
|
||||
z-index: 2;
|
||||
font-size: 20px;
|
||||
bottom: 0;
|
||||
color: #fff;
|
||||
margin-right: 14px;
|
||||
padding: 4px;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: auto; }
|
||||
|
||||
/* Character Overview */
|
||||
@ -1071,6 +1079,18 @@ a:visited {
|
||||
#stock-market-container {
|
||||
position: fixed;
|
||||
padding: 6px; }
|
||||
#stock-market-container p {
|
||||
font-size: 13px; }
|
||||
#stock-market-container a {
|
||||
font-size: 14px; }
|
||||
#stock-market-container h2 {
|
||||
margin-top: 10px;
|
||||
margin-left: 10px;
|
||||
display: block; }
|
||||
|
||||
/* Change font size of Stock TIcker headers */
|
||||
#stock-market-list li button {
|
||||
font-size: 16px; }
|
||||
|
||||
#stock-market-container p {
|
||||
padding: 10px;
|
||||
@ -1080,6 +1100,10 @@ a:visited {
|
||||
#stock-market-container a {
|
||||
margin: 10px; }
|
||||
|
||||
#stock-market-watchlist-filter {
|
||||
width: 50%;
|
||||
margin-left: 10px; }
|
||||
|
||||
.stock-market-input {
|
||||
display: inline-block;
|
||||
padding: 4px;
|
||||
@ -1119,7 +1143,14 @@ a:visited {
|
||||
.generic-fullscreen-container {
|
||||
color: var(--my-font-color);
|
||||
width: 99%;
|
||||
height: 100%; }
|
||||
height: 100%;
|
||||
overflow-y: hidden; }
|
||||
|
||||
.generic-fullscreen-container-scroll {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
padding-right: 20px; }
|
||||
|
||||
#work-in-progress-container {
|
||||
position: fixed; }
|
||||
@ -1174,6 +1205,8 @@ a:visited {
|
||||
/* Sit on top */
|
||||
left: 0;
|
||||
top: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
@ -1181,10 +1214,21 @@ a:visited {
|
||||
|
||||
.popup-box-content {
|
||||
background-color: var(--my-background-color);
|
||||
margin: 15% auto;
|
||||
padding: 12px;
|
||||
border: 5px solid var(--my-highlight-color);
|
||||
width: 70%;
|
||||
max-height: 80%;
|
||||
/*
|
||||
margin: auto;
|
||||
height:auto;
|
||||
max-height:80%;
|
||||
position:absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
bottom:0;
|
||||
right:0;
|
||||
*/
|
||||
overflow-y: auto;
|
||||
color: var(--my-font-color); }
|
||||
|
||||
.popup-box-button,
|
||||
@ -1292,11 +1336,12 @@ a:visited {
|
||||
|
||||
#game-options-content {
|
||||
background-color: var(--my-background-color);
|
||||
margin: 15% auto;
|
||||
padding: 10px;
|
||||
border: 5px solid var(--my-highlight-color);
|
||||
width: 60%;
|
||||
color: var(--my-font-color); }
|
||||
color: var(--my-font-color);
|
||||
width: 80%;
|
||||
max-height: 80%;
|
||||
overflow-y: auto; }
|
||||
|
||||
#game-options-left-panel,
|
||||
#game-options-right-panel {
|
||||
|
112
dist/vendor.bundle.js
vendored
112
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@ -3,6 +3,48 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
v0.40.2 - 8/27/2018
|
||||
-------------------
|
||||
* Bladeburner Changes:
|
||||
* Added getBonusTime(), getSkillUpgradeCost(), and getCity() Netscript functions to the API
|
||||
* Buffed the effects of many Bladeburner Augmentations
|
||||
* The Blade's Simulacrum Augmentation requires significantly less reputation but slightly more money
|
||||
* Slightly increased the amount of successes needed for a Contract/Operation in order to increase its max level
|
||||
* Increased the amount of money gained from Contracts by ~25%
|
||||
* Increased the base amount of rank gained from Operations by 10%
|
||||
* Significantly increased the 'randomness' in determining a Contract/Operation's initial count and rate of count increase
|
||||
* The number (count) of Operations should now increase significantly faster
|
||||
* There are now, on average, more Synthoid communities in a city
|
||||
* If automation is enabled (the feature in Bladeburner console), then switching to another action such as working for a company will now disable the automation
|
||||
* Stock Market Changes:
|
||||
*Added a watchlist filter feature to the UI that allows you to specify which stocks to show
|
||||
*Added the Four Sigma (4S) Market Data feed, which provides volatility and price forecast information about stocks
|
||||
*Added the 4S Market Data TIX API, which lets you access the aforementioned data through Netscript
|
||||
* There is now a setting for enabling/disabling the popup that appears when you are hospitalized
|
||||
* Bug Fix: Stock market should now be correctly initialized in BitNode-8 (by Kline-)
|
||||
* Bug Fix: bladeburner.getCurrentAction() should now properly an 'Idle' object rather than null (by Kline-)
|
||||
* Bug Fix: Bladeburner skill cost multiplier should now properly increase in BitNode-12 (by hydroflame)
|
||||
* Bug Fix: 'document', 'hacknet', and 'window' keywords should no longer be counted multiple times in RAM calculations
|
||||
* Bug Fix: Joining factions through Singularity functions should now prevent you from joining opposing factions
|
||||
* Bug Fix: Four Sigma should no longer have two 'Speech Enhancement' Augmentations (by Kline-)
|
||||
|
||||
v0.40.1 - 8/5/2018 - Community Update
|
||||
-------------------------------------
|
||||
* Added getPurchasedServerCost() Netscript function (by kopelli)
|
||||
* Added getFavorToDonate() Netscript function (by hydroflame)
|
||||
* Added getFactionFavorGain() and getCompanyFavorGain() Singularity functions (by hydroflame)
|
||||
* Accumulated 'bonus' time in Bladeburner is now displayed in the UI (by hydroflame)
|
||||
* The Red Pill can now be purchased with negative money (since its supposed to be free) (by hydroflame)
|
||||
* Cranial Signal Processor Augmentations now have the previous generation as a prerequisite. i.e. Cranial Signal Processor - Gen II requires Gen I (by Kline-)
|
||||
* Terminal now supports semicolon usage (end of command). This allows chaining multiple Terminal commands (by hydroflame)
|
||||
* Bladeburner Raid operations can no longer be performed if your estimate of Synthoid communities is zero (by hydroflame)
|
||||
* The difficulty of BN-12 now scales faster (by hydroflame)
|
||||
* Active Scripts UI now shows a RAM Usage bar for each server (by kopelli)
|
||||
* Bug Fix: Corrected terminal timestamp format (by kopelli)
|
||||
* Bug Fix: NetscriptJS scripts should now die properly if they don't have a 'main' function (by hydroflame)
|
||||
* Bug Fix: write(), read(), and tryWrite() Netscript functions should now work properly for writing Arrays/objects to Netscript Ports
|
||||
* Various minor UI/QOL fixes by hydroflame, kopelli, and Kline-
|
||||
|
||||
v0.40.0 - 7/28/2018
|
||||
-------------------
|
||||
* **WARNING: This update makes some significant changes to Netscript and therefore you may need to make some changes to your scripts. See** `this post <https://www.reddit.com/r/Bitburner/comments/9252j4/psa_netscript_10_changes_in_next_version_v0400/>`_ **this post for details**
|
||||
|
@ -143,7 +143,9 @@ getActionEstimatedSuccessChance
|
||||
:param string type: Type of action. See :ref:`bladeburner_action_types`
|
||||
:param string name: Name of action. Must be an exact match
|
||||
|
||||
Returns the estimated success chance for the specified action
|
||||
Returns the estimated success chance for the specified action. This chance
|
||||
is returned as a decimal value, NOT a percentage (e.g. if you have an estimated
|
||||
success chance of 80%, then this function will return 0.80, NOT 80).
|
||||
|
||||
getActionCountRemaining
|
||||
-----------------------
|
||||
@ -235,18 +237,30 @@ getSkillLevel
|
||||
|
||||
.. js:function:: getSkillLevel(skillName="")
|
||||
|
||||
:param string skillName: Name of skill
|
||||
:param string skillName: Name of skill. Case-sensitive and must be an exact match
|
||||
|
||||
This function returns your level in the specified skill.
|
||||
|
||||
The function returns -1 if an invalid skill name is passed in
|
||||
|
||||
getSkillUpgradeCost
|
||||
-------------------
|
||||
|
||||
.. js:function:: getSkillUpgradeCost(skillName="")
|
||||
|
||||
:param string skillName: Name of skill. Case-sensitive and must be an exact match
|
||||
|
||||
This function returns the number of skill points needed to upgrade the
|
||||
specified skill.
|
||||
|
||||
The function returns -1 if an invalid skill name is passed in.
|
||||
|
||||
upgradeSkill
|
||||
------------
|
||||
|
||||
.. js:function:: upgradeSkill(skillName)
|
||||
|
||||
:param string skillName: Name of Skill to be upgraded. Must be an exact match
|
||||
:param string skillName: Name of Skill to be upgraded. Case-sensitive and must be an exact match
|
||||
|
||||
Attempts to upgrade the specified Bladeburner skill. Returns true if the
|
||||
skill is successfully upgraded, and false otherwise
|
||||
@ -358,6 +372,21 @@ joinBladeburnerDivision
|
||||
|
||||
Returns false otherwise
|
||||
|
||||
getBonusTime
|
||||
------------
|
||||
|
||||
.. js:function:: getBonusTime()
|
||||
|
||||
Returns the amount of accumulated "bonus time" (seconds) for the Bladeburner mechanic.
|
||||
|
||||
"Bonus time" is accumulated when the game is offline or if the game is
|
||||
inactive in the browser.
|
||||
|
||||
"Bonus time" makes the game progress faster, up to 5x the normal speed.
|
||||
For example, if an action takes 30 seconds to complete but you've accumulated
|
||||
over 30 seconds in bonus time, then the action will only take 6 seconds
|
||||
in real life to complete.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
|
@ -659,16 +659,14 @@ getNextHacknetNodeCost
|
||||
|
||||
.. js:function:: getNextHacknetNodeCost()
|
||||
|
||||
Returns the cost of purchasing a new Hacknet Node
|
||||
Deprecated (no longer usable). See :doc:`netscripthacknetnodeapi`
|
||||
|
||||
purchaseHacknetNode
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. js:function:: purchaseHacknetNode()
|
||||
|
||||
Purchases a new Hacknet Node. Returns a number with the index of the Hacknet Node. This index is equivalent to the number at the
|
||||
end of the Hacknet Node's name (e.g The Hacknet Node named 'hacknet-node-4' will have an index of 4). If the player cannot afford
|
||||
to purchase a new Hacknet Node then the function will return false.
|
||||
Deprecated (no longer usable). See :doc:`netscripthacknetnodeapi`
|
||||
|
||||
getPurchasedServerCost
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -1,3 +1,5 @@
|
||||
.. _netscripthacknetnodeapi:
|
||||
|
||||
Netscript Hacknet Node API
|
||||
==========================
|
||||
|
||||
|
@ -159,7 +159,7 @@ cancelOrder
|
||||
:param number price: Execution price for the order
|
||||
:param string type: Type of order. It must specify "limit" or "stop", and must also specify "buy" or "sell". This is NOT
|
||||
case-sensitive. Here are four examples that will work:
|
||||
|
||||
|
||||
* limitbuy
|
||||
* limitsell
|
||||
* stopbuy
|
||||
@ -172,3 +172,38 @@ cancelOrder
|
||||
Cancels an oustanding Limit or Stop order on the stock market.
|
||||
|
||||
The ability to use limit and stop orders is **not** immediately available to the player and must be unlocked later on in the game.
|
||||
|
||||
getStockVolatility
|
||||
------------------
|
||||
|
||||
.. js:function:: getStockVolatility(sym)
|
||||
|
||||
:param string sym: Symbol of stock
|
||||
|
||||
Returns the volatility of the specified stock.
|
||||
|
||||
Volatility represents the maximum percentage by which a stock's price can
|
||||
change every tick. The volatility is returned as a decimal value, NOT
|
||||
a percentage (e.g. if a stock has a volatility of 3%, then this function will
|
||||
return 0.03, NOT 3).
|
||||
|
||||
In order to use this function, you must first purchase access to the Four Sigma (4S)
|
||||
Market Data TIX API.
|
||||
|
||||
getStockForecast
|
||||
----------------
|
||||
|
||||
.. js:function:: getStockForecast(sym)
|
||||
|
||||
:param string sym: Symbol of stock
|
||||
|
||||
Returns the probability that the specified stock's price will increase
|
||||
(as opposed to decrease) during the next tick.
|
||||
|
||||
The probability is returned as a decimal value, NOT a percentage (e.g. if a
|
||||
stock has a 60% chance of increasing, then this function will return 0.6,
|
||||
NOT 60).
|
||||
|
||||
In other words, if this function returned 0.30 for a stock, then this means
|
||||
that the stock's price has a 30% chance of increasing and a 70% chance of
|
||||
decreasing during the next tick.
|
||||
|
@ -311,6 +311,18 @@ getCompanyFavor
|
||||
|
||||
This function will return the amount of favor you have at the specified company.
|
||||
If the company passed in as an argument is invalid, -1 will be returned.
|
||||
|
||||
getCompanyFavorGain
|
||||
-------------------
|
||||
|
||||
.. js:function:: getCompanyFavorGain(companyName)
|
||||
|
||||
:param string companyName: Name of the company. CASE-SENSITIVE
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.
|
||||
|
||||
This function will return the amount of favor you will gain for the specified company
|
||||
when you reset by installing Augmentations.
|
||||
|
||||
checkFactionInvitations
|
||||
-----------------------
|
||||
@ -386,6 +398,17 @@ getFactionFavor
|
||||
If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.
|
||||
|
||||
This function returns the amount of favor you have for the specified faction.
|
||||
|
||||
getFactionFavorGain
|
||||
-------------------
|
||||
|
||||
.. js:function:: getFactionFavorGain(factionName)
|
||||
|
||||
:param string factionName: Name of faction. CASE-SENSITIVE
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.
|
||||
|
||||
This function returns the amount of favor you will gain for the specified faction when you reset by installing Augmentations.
|
||||
|
||||
createProgram
|
||||
-------------
|
||||
|
88
index.html
88
index.html
@ -110,7 +110,7 @@
|
||||
|
||||
<div id="script-editor-filename-wrapper">
|
||||
<p id="script-editor-filename-tag"> <strong style="background-color:#555;">Script name: </strong></p>
|
||||
<input id="script-editor-filename" type="text" maxlength="30" tabindex="1"/>
|
||||
<input id="script-editor-filename" type="text" maxlength="30" tabindex="1" />
|
||||
</div>
|
||||
|
||||
<div id="javascript-editor"></div>
|
||||
@ -160,7 +160,7 @@
|
||||
|
||||
<fieldset>
|
||||
<label for="script-editor-option-maxerr" class="tooltip">Max Error Count</label>
|
||||
<input type="range" max="1000" min="50" value="200" step="1" name="script-editor-option-maxerr" id="script-editor-option-maxerr"/>
|
||||
<input type="range" max="1000" min="50" value="200" step="1" name="script-editor-option-maxerr" id="script-editor-option-maxerr" />
|
||||
<em id="script-editor-option-maxerror-value-label" style="font-style: normal;"></em>
|
||||
</fieldset>
|
||||
</div> <!-- End script editor options panel -->
|
||||
@ -169,11 +169,11 @@
|
||||
<!-- Terminal page -->
|
||||
<div id="terminal-container">
|
||||
<table id="terminal">
|
||||
<tr id="terminal-input">
|
||||
<tr id="terminal-input">
|
||||
<td id="terminal-input-td" tabindex="2">$
|
||||
<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" onfocus="this.value = this.value;"/>
|
||||
<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" onfocus="this.value = this.value;" />
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@ -215,7 +215,7 @@
|
||||
<div id="hacknet-nodes-money-multipliers-div">
|
||||
<p id="hacknet-nodes-money">
|
||||
<span>Money:</span><span id="hacknet-nodes-player-money"></span><br/>
|
||||
<span>Total Hacknet Node Prodution:</span><span id="hacknet-nodes-total-production"></span>
|
||||
<span>Total Hacknet Node Production:</span><span id="hacknet-nodes-total-production"></span>
|
||||
</p>
|
||||
<span id="hacknet-nodes-multipliers">
|
||||
<a id="hacknet-nodes-1x-multiplier" class="a-link-button-inactive"> x1 </a>
|
||||
@ -452,7 +452,7 @@
|
||||
<div id="create-program-container" class="generic-menupage-container">
|
||||
<p id="create-program-page-text">
|
||||
This page displays any programs that you are able to create. Writing the code for a program takes time, which
|
||||
can vary based on how complex the program is. If you are working on creating on a program you can cancel
|
||||
can vary based on how complex the program is. If you are working on creating a program you can cancel
|
||||
at any time. Your progress will be saved and you can continue later.
|
||||
</p>
|
||||
|
||||
@ -625,9 +625,9 @@
|
||||
<!-- Slums -->
|
||||
<p id="location-slums-description">
|
||||
You have entered the Slums, a poverty-ridden district filled with gangs, criminals, and
|
||||
other shadowy entities. The city's government and police have neglected this area for years... <br><br><br>
|
||||
|
||||
In the Slums you can commit crimes to earn money and experience. Crime attempts are not always
|
||||
other shadowy entities. The city's government and police have neglected this area for years...
|
||||
<br><br><br>
|
||||
In the Slums, you can commit crimes to earn money and experience. Crime attempts are not always
|
||||
successful. Your chance at successfully committing a crime is determined by your stats.
|
||||
</p>
|
||||
<a class="a-link-button tooltip" id="location-slums-shoplift"> Shoplift </a>
|
||||
@ -679,22 +679,44 @@
|
||||
after you 'reset' by installing Augmentations.
|
||||
</p>
|
||||
<a id="stock-market-buy-account" class="a-link-button-inactive"> Buy WSE Account </a>
|
||||
<a id="stock-market-investopedia" class="a-link-button">Investopedia</a>
|
||||
|
||||
<h2> Trade Information eXchange (TIX) API </h2>
|
||||
<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!
|
||||
TIX, short for Trade Information eXchange, is the communications protocol supported by the WSE.
|
||||
Purchasing access to the TIX API lets you write code to create your own algorithmic/automated
|
||||
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 (TIX) API Access</a>
|
||||
<a id="stock-market-investopedia" class="a-link-button">Investopedia</a>
|
||||
|
||||
<h2> Four Sigma (4S) Market Data Feed </h2>
|
||||
<p>
|
||||
Four Sigma's (4S) Market Data Feed provides information about stocks
|
||||
that will help your trading strategies.
|
||||
<br><br>
|
||||
If you purchase access to 4S Market Data and/or the 4S TIX API, you will
|
||||
retain that access even after you 'reset' by installing Augmentations.
|
||||
</p>
|
||||
|
||||
<a id="stock-market-buy-4s-data" class="a-link-button-inactive tooltip">
|
||||
Buy 4S Market Data Feed
|
||||
</a>
|
||||
<div class="help-tip-big" id="stock-market-4s-data-help-tip">?</div>
|
||||
|
||||
<a id="stock-market-buy-4s-tix-api" class="a-link-button-inactive tooltip">
|
||||
Buy 4S Market Data TIX API Access
|
||||
</a>
|
||||
|
||||
<p id="stock-market-commission"> </p>
|
||||
<a id="stock-market-mode" class="a-link-button tooltip"></a>
|
||||
<a id="stock-market-expand-tickers" class="a-link-button tooltip">Expand tickers</a>
|
||||
<a id="stock-market-collapse-tickers" class="a-link-button tooltip">Collapse tickers</a>
|
||||
<br><br>
|
||||
<input id="stock-market-watchlist-filter" type="text" placeholder="Filter Stocks by symbol (comma-separated list)"> </input>
|
||||
<a id="stock-market-watchlist-filter-update" class="a-link-button"> Update Watchlist </a>
|
||||
<ul id="stock-market-list" style="list-style:none;">
|
||||
</ul>
|
||||
</div>
|
||||
@ -722,7 +744,7 @@
|
||||
<div id="yes-no-text-input-box-container" class="popup-box-container">
|
||||
<div id="yes-no-text-input-box-content" class="popup-box-content">
|
||||
<p id="yes-no-text-input-box-text"> </p>
|
||||
<input type="text" id="yes-no-text-input-box-input" pattern="[a-zA-Z0-9-_]" maxlength="30"/>
|
||||
<input type="text" id="yes-no-text-input-box-input" pattern="[a-zA-Z0-9-_]" maxlength="30" />
|
||||
<span id="yes-no-text-input-box-yes" class="popup-box-button"> Yes </span>
|
||||
<span id="yes-no-text-input-box-no" class="popup-box-button"> No </span>
|
||||
</div>
|
||||
@ -766,7 +788,9 @@
|
||||
</div>
|
||||
|
||||
<!-- Red Pill Container -->
|
||||
<div id="red-pill-container" class="generic-fullscreen-container"></div>
|
||||
<div id="red-pill-container" class="generic-fullscreen-container">
|
||||
<div id="red-pill-content" class="generic-fullscreen-container-scroll"></div>
|
||||
</div>
|
||||
|
||||
<!-- Cinematic Text Container -->
|
||||
<div id="cinematic-text-container" class="generic-fullscreen-container"></div>
|
||||
@ -813,11 +837,11 @@
|
||||
<tr id="character-int-wrapper">
|
||||
<td>Int: </td><td id="character-int-text" class="character-stat-cell"></td>
|
||||
</tr>
|
||||
<table>
|
||||
</table>
|
||||
</div>
|
||||
<div class="character-quick-options">
|
||||
<span id="character-overview-save-button"> Save Game </span>
|
||||
<span id="character-overview-options-button"> Options </span>
|
||||
<span id="character-overview-save-button">Save Game</span>
|
||||
<span id="character-overview-options-button">Options</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -844,7 +868,7 @@
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<input type ="range" max="100" min="10" step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="25"/>
|
||||
<input type ="range" max="100" min="10" step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="25" />
|
||||
<em id="settingsNSExecTimeRangeValLabel" style="font-style: normal;"></em>
|
||||
</fieldset>
|
||||
|
||||
@ -858,7 +882,7 @@
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<input type="range" max="100" min="20" step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50"/>
|
||||
<input type="range" max="100" min="20" step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50" />
|
||||
<em id="settingsNSLogRangeValLabel" style="font-style: normal;"></em>
|
||||
</fieldset>
|
||||
|
||||
@ -872,7 +896,7 @@
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<input type="range" max="100" min="20" step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50"/>
|
||||
<input type="range" max="100" min="20" step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50" />
|
||||
<em id="settingsNSPortRangeValLabel" style="font-style: normal;"></em>
|
||||
</fieldset>
|
||||
|
||||
@ -884,7 +908,7 @@
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<input type="range" max="600" min="0" step="1" name="settingsAutosaveIntervalVal" id="settingsAutosaveIntervalVal" value="60"/>
|
||||
<input type="range" max="600" min="0" step="1" name="settingsAutosaveIntervalVal" id="settingsAutosaveIntervalVal" value="60" />
|
||||
<em id="settingsAutosaveIntervalValLabel" style="font-style: normal;"></em>
|
||||
</fieldset>
|
||||
|
||||
@ -932,6 +956,16 @@
|
||||
<input type="checkbox" name="settingsSuppressBuyAugmentationConfirmation" id="settingsSuppressBuyAugmentationConfirmation">
|
||||
</fieldset>
|
||||
|
||||
<!-- Hospitalization Popup -->
|
||||
<fieldset>
|
||||
<label for="settingsSuppressHospitalizationPopup" class="tooltip">Suppress Hospitalization popup:
|
||||
<span class="tooltiptext">
|
||||
If this is set, a popup message will no longer be shown when you are hospitalized after taking too much damage.
|
||||
</span>
|
||||
</label>
|
||||
<input type="checkbox" name="settingsSuppressHospitalizationPopup" id="settingsSuppressHospitalizationPopup">
|
||||
</fieldset>
|
||||
|
||||
<!-- Disable Terminal and Navigation Shortcuts -->
|
||||
<fieldset>
|
||||
<label for="settingsDisableHotkeys" class="tooltip">Disable Hotkeys:
|
||||
@ -960,7 +994,7 @@
|
||||
<a id="save-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Save Game </a>
|
||||
<a id="delete-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Delete Game </a>
|
||||
<a id="export-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Export Game </a>
|
||||
<input type="file" id="import-game-file-selector" name="file"/>
|
||||
<input type="file" id="import-game-file-selector" name="file" />
|
||||
<a id="import-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Import Game </a>
|
||||
<a id="debug-delete-scripts-link" class="a-link-button tooltip" style="display:block;width:46%;">
|
||||
(DEBUG) Delete Active Scripts
|
||||
@ -972,7 +1006,7 @@
|
||||
<a id="debug-soft-reset" class="a-link-button tooltip" style="display:block;width:46%;">
|
||||
(DEBUG) Soft Reset
|
||||
<span class="tooltiptext">
|
||||
Perform a soft reset. Resets everything as if you had just purchased an Augmentation
|
||||
Perform a soft reset. Resets everything as if you had just purchased an Augmentation.
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -81,6 +81,7 @@ let NetscriptFunctions =
|
||||
"gymWorkout|travelToCity|purchaseTor|purchaseProgram|upgradeHomeRam|" +
|
||||
"getUpgradeHomeRamCost|workForCompany|applyToCompany|getCompanyRep|" +
|
||||
"getCompanyFavor|stopAction|getFactionFavor|" +
|
||||
"getFavorToDonate|getFactionFavorGain|getCompanyFavorGain|" +
|
||||
"checkFactionInvitations|joinFaction|workForFaction|getFactionRep|" +
|
||||
"createProgram|commitCrime|getCrimeChance|getOwnedAugmentations|" +
|
||||
"getOwnedSourceFiles|getAugmentationsFromFaction|" +
|
||||
@ -99,9 +100,10 @@ let NetscriptFunctions =
|
||||
"getActionTime|getActionEstimatedSuccessChance|getActionCountRemaining|" +
|
||||
"getActionMaxLevel|getActionCurrentLevel|getActionAutolevel|" +
|
||||
"setActionAutolevel|setActionLevel|" +
|
||||
"getRank|getSkillPoints|getSkillLevel|upgradeSkill|getTeamSize|" +
|
||||
"getRank|getSkillPoints|getSkillLevel|getSkillUpgradeCost|" +
|
||||
"upgradeSkill|getTeamSize|" +
|
||||
"setTeamSize|getCityEstimatedPopulation|getCityEstimatedCommunities|" +
|
||||
"getCityChaos|switchCity|getStamina|joinBladeburnerFaction";
|
||||
"getCityChaos|switchCity|getStamina|joinBladeburnerFaction|getBonusTime";
|
||||
|
||||
var NetscriptHighlightRules = function(options) {
|
||||
var keywordMapper = this.createKeywordMapper({
|
||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bitburner",
|
||||
"version": "0.35.1",
|
||||
"version": "0.40.2",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -101,5 +101,5 @@
|
||||
"watch": "webpack --watch --mode production",
|
||||
"watch:dev": "webpack --watch --mode development"
|
||||
},
|
||||
"version": "0.35.1"
|
||||
"version": "0.40.2"
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import {Engine} from "./engine";
|
||||
import {workerScripts,
|
||||
killWorkerScript} from "./NetscriptWorker";
|
||||
import {Player} from "./Player";
|
||||
@ -16,6 +15,7 @@ import {formatNumber} from "../utils/StringHelperFunctions";
|
||||
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
import {removeElement} from "../utils/uiHelpers/removeElement";
|
||||
import {roundToTwo} from "../utils/helpers/roundToTwo";
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
|
||||
/* {
|
||||
* serverName: {
|
||||
@ -232,7 +232,7 @@ function updateActiveScriptsItems(maxTasks=150) {
|
||||
}
|
||||
}
|
||||
|
||||
if (Engine.currentPage !== Engine.Page.ActiveScripts) {return;}
|
||||
if (!routing.isOn(Page.ActiveScripts)) {return;}
|
||||
var total = 0;
|
||||
for (var i = 0; i < workerScripts.length; ++i) {
|
||||
try {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {post} from "./Terminal";
|
||||
import {post} from "./ui/postToTerminal";
|
||||
|
||||
let Aliases = {};
|
||||
let GlobalAliases = {};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {BitNodeMultipliers} from "./BitNode";
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Engine} from "./engine";
|
||||
import {Factions, getNextNeurofluxLevel,
|
||||
@ -746,7 +746,7 @@ function initAugmentations() {
|
||||
"Increases the player's hacking skill by 7%.",
|
||||
prereqs:[AugmentationNames.CranialSignalProcessorsG1]
|
||||
});
|
||||
CranialSignalProcessorsG2.addToFactions(["NiteSec"]);
|
||||
CranialSignalProcessorsG2.addToFactions(["CyberSec", "NiteSec"]);
|
||||
if (augmentationExists(AugmentationNames.CranialSignalProcessorsG2)) {
|
||||
delete Augmentations[AugmentationNames.CranialSignalProcessorsG2];
|
||||
}
|
||||
@ -764,7 +764,7 @@ function initAugmentations() {
|
||||
"Increases the player's hacking skill by 9%.",
|
||||
prereqs:[AugmentationNames.CranialSignalProcessorsG2]
|
||||
});
|
||||
CranialSignalProcessorsG3.addToFactions(["NiteSec", "The Black Hand"]);
|
||||
CranialSignalProcessorsG3.addToFactions(["NiteSec", "The Black Hand", "BitRunners"]);
|
||||
if (augmentationExists(AugmentationNames.CranialSignalProcessorsG3)) {
|
||||
delete Augmentations[AugmentationNames.CranialSignalProcessorsG3];
|
||||
}
|
||||
@ -782,7 +782,7 @@ function initAugmentations() {
|
||||
"Increases the amount of money the player can inject into servers using grow() by 25%.",
|
||||
prereqs:[AugmentationNames.CranialSignalProcessorsG3]
|
||||
});
|
||||
CranialSignalProcessorsG4.addToFactions(["The Black Hand"]);
|
||||
CranialSignalProcessorsG4.addToFactions(["The Black Hand", "BitRunners"]);
|
||||
if (augmentationExists(AugmentationNames.CranialSignalProcessorsG4)) {
|
||||
delete Augmentations[AugmentationNames.CranialSignalProcessorsG4];
|
||||
}
|
||||
@ -848,7 +848,7 @@ function initAugmentations() {
|
||||
"Increases the amount of reputation the player gains when working for a company by 10%."
|
||||
});
|
||||
SpeechEnhancement.addToFactions(["Tian Di Hui", "Speakers for the Dead", "Four Sigma", "KuaiGong International",
|
||||
"Clarke Incorporated", "Four Sigma", "Bachman & Associates"]);
|
||||
"Clarke Incorporated", "Bachman & Associates"]);
|
||||
if (augmentationExists(AugmentationNames.SpeechEnhancement)) {
|
||||
delete Augmentations[AugmentationNames.SpeechEnhancement];
|
||||
}
|
||||
@ -1575,7 +1575,7 @@ function initAugmentations() {
|
||||
"AR HUD and assist the user in field missions.<br><br>" +
|
||||
"This augmentation:<br>" +
|
||||
"Increases the player's success chance in Bladeburner contracts/operations by 3%.<br>" +
|
||||
"Increases the player's dexterity by 3%."
|
||||
"Increases the player's dexterity by 5%."
|
||||
});
|
||||
EsperEyewear.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(EsperEyewear);
|
||||
@ -1589,7 +1589,7 @@ function initAugmentations() {
|
||||
"This augmentation:<br>" +
|
||||
"Increases the player's sucess chance in Bladeburner contracts/operations by 3%.<br>" +
|
||||
"Increases the player's effectiveness in Bladeburner Field Analysis by 5%.<br>" +
|
||||
"Increases the player's Bladeburner stamina gain rate by 1%."
|
||||
"Increases the player's Bladeburner stamina gain rate by 2%."
|
||||
});
|
||||
EMS4Recombination.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(EMS4Recombination);
|
||||
@ -1602,7 +1602,7 @@ function initAugmentations() {
|
||||
"crystallized graphene plating.<br><br>" +
|
||||
"This augmentation:<br>" +
|
||||
"Increases the player's defense by 5%.<br>" +
|
||||
"Increases the player's strength and dexterity by 3%.<br>" +
|
||||
"Increases the player's strength and dexterity by 5%.<br>" +
|
||||
"Increases the player's success chance in Bladeburner contracts/operations by 4%."
|
||||
});
|
||||
OrionShoulder.addToFactions([BladeburnersFactionName]);
|
||||
@ -1617,7 +1617,7 @@ function initAugmentations() {
|
||||
"it can also be effective against non-augmented enemies due to its high temperature " +
|
||||
"and concussive force.<br><br>" +
|
||||
"This augmentation:<br>" +
|
||||
"Increases the player's success chance in Bladeburner contracts/operations by 5%."
|
||||
"Increases the player's success chance in Bladeburner contracts/operations by 6%."
|
||||
});
|
||||
HyperionV1.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(HyperionV1);
|
||||
@ -1629,7 +1629,7 @@ function initAugmentations() {
|
||||
"more power-efficiency, more accurate, and can fire plasma bolts at a much " +
|
||||
"higher velocity than the V1 model.<br><br>" +
|
||||
"This augmentation:<br>" +
|
||||
"Increases the player's success chance in Bladeburner contracts/operations by 7%.",
|
||||
"Increases the player's success chance in Bladeburner contracts/operations by 8%.",
|
||||
prereqs:[AugmentationNames.HyperionV1]
|
||||
});
|
||||
HyperionV2.addToFactions([BladeburnersFactionName]);
|
||||
@ -1642,7 +1642,7 @@ function initAugmentations() {
|
||||
"serum was originally developed by the Chinese military in an attempt to " +
|
||||
"create super soldiers.<br><br>" +
|
||||
"This augmentation:<br>" +
|
||||
"Increases all of the player's combat stats by 5%.<br>" +
|
||||
"Increases all of the player's combat stats by 7%.<br>" +
|
||||
"Increases the player's Bladeburner stamina gain rate by 5%.<br>"
|
||||
});
|
||||
GolemSerum.addToFactions([BladeburnersFactionName]);
|
||||
@ -1655,7 +1655,7 @@ function initAugmentations() {
|
||||
"This augmentation:<br>" +
|
||||
"Increases the player's effectiveness in Bladeburner Field Analysis by 10%.<br>" +
|
||||
"Increases the player's success chance in Bladeburner contracts/operations by 4%.<br>" +
|
||||
"Increases the player's dexterity experience gain rate by 5%."
|
||||
"Increases the player's dexterity experience gain rate by 10%."
|
||||
});
|
||||
VangelisVirus.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(VangelisVirus);
|
||||
@ -1668,7 +1668,7 @@ function initAugmentations() {
|
||||
"agility/reflexes.<br><br>" +
|
||||
"This augmentation:<br>" +
|
||||
"Increases the player's effectiveness in Bladeburner Field Analysis by 15%.<br>" +
|
||||
"Increases the player's defense and dexterity experience gain rate by 5%.<br>" +
|
||||
"Increases the player's defense and dexterity experience gain rate by 10%.<br>" +
|
||||
"Increases the player's success chance in Bladeburner contracts/operations by 5%.",
|
||||
prereqs:[AugmentationNames.VangelisVirus]
|
||||
});
|
||||
@ -1682,7 +1682,7 @@ function initAugmentations() {
|
||||
"structurally support the body and grants heightened strength and " +
|
||||
"durability.<br><br>" +
|
||||
"This augmentation:<br>" +
|
||||
"Increases the player's experience gain rate for all combat stats by 4%.<br>" +
|
||||
"Increases the player's experience gain rate for all combat stats by 5%.<br>" +
|
||||
"Increases the player's Bladeburner max stamina by 10%."
|
||||
});
|
||||
INTERLINKED.addToFactions([BladeburnersFactionName]);
|
||||
@ -1709,7 +1709,7 @@ function initAugmentations() {
|
||||
"concussive, thermal, chemical, and electric trauma. It also enhances the user's " +
|
||||
"strength and agility.<br><br>" +
|
||||
"This augmentation:<br>" +
|
||||
"Increases all of the player's combat stats by 2%.<br>" +
|
||||
"Increases all of the player's combat stats by 4%.<br>" +
|
||||
"Increases the player's Bladeburner stamina gain rate by 2%.<br>" +
|
||||
"Increases the player's success chance in Bladeburner contracts/operations by 3%.",
|
||||
});
|
||||
@ -1780,7 +1780,7 @@ function initAugmentations() {
|
||||
resetAugmentation(BladeArmorIPU);
|
||||
|
||||
var BladesSimulacrum = new Augmentation({
|
||||
name:AugmentationNames.BladesSimulacrum, repCost:6e3, moneyCost:75e9,
|
||||
name:AugmentationNames.BladesSimulacrum, repCost:3e3, moneyCost:80e9,
|
||||
info:"A highly-advanced matter phase-shifter module that is embedded " +
|
||||
"in the brainstem and cerebellum. This augmentation allows " +
|
||||
"the user to project and control a holographic simulacrum within an " +
|
||||
@ -2297,48 +2297,48 @@ function applyAugmentation(aug, reapply=false) {
|
||||
//Bladeburner augmentations
|
||||
case AugmentationNames.EsperEyewear:
|
||||
Player.bladeburner_success_chance_mult *= 1.03;
|
||||
Player.dexterity_mult *= 1.03;
|
||||
Player.dexterity_mult *= 1.05;
|
||||
break;
|
||||
case AugmentationNames.EMS4Recombination:
|
||||
Player.bladeburner_success_chance_mult *= 1.03;
|
||||
Player.bladeburner_analysis_mult *= 1.05;
|
||||
Player.bladeburner_stamina_gain_mult *= 1.01;
|
||||
Player.bladeburner_stamina_gain_mult *= 1.02;
|
||||
break;
|
||||
case AugmentationNames.OrionShoulder:
|
||||
Player.defense_mult *= 1.05;
|
||||
Player.strength_mult *= 1.03;
|
||||
Player.dexterity_mult *= 1.03;
|
||||
Player.strength_mult *= 1.05;
|
||||
Player.dexterity_mult *= 1.05;
|
||||
Player.bladeburner_success_chance_mult *= 1.04;
|
||||
break;
|
||||
case AugmentationNames.HyperionV1:
|
||||
Player.bladeburner_success_chance_mult *= 1.05;
|
||||
Player.bladeburner_success_chance_mult *= 1.06;
|
||||
break;
|
||||
case AugmentationNames.HyperionV2:
|
||||
Player.bladeburner_success_chance_mult *= 1.07;
|
||||
Player.bladeburner_success_chance_mult *= 1.08;
|
||||
break;
|
||||
case AugmentationNames.GolemSerum:
|
||||
Player.strength_mult *= 1.05;
|
||||
Player.defense_mult *= 1.05;
|
||||
Player.dexterity_mult *= 1.05;
|
||||
Player.agility_mult *= 1.05;
|
||||
Player.strength_mult *= 1.07;
|
||||
Player.defense_mult *= 1.07;
|
||||
Player.dexterity_mult *= 1.07;
|
||||
Player.agility_mult *= 1.07;
|
||||
Player.bladeburner_stamina_gain_mult *= 1.05;
|
||||
break;
|
||||
case AugmentationNames.VangelisVirus:
|
||||
Player.dexterity_exp_mult *= 1.05;
|
||||
Player.dexterity_exp_mult *= 1.1;
|
||||
Player.bladeburner_analysis_mult *= 1.1;
|
||||
Player.bladeburner_success_chance_mult *= 1.04;
|
||||
break;
|
||||
case AugmentationNames.VangelisVirus3:
|
||||
Player.defense_exp_mult *= 1.05;
|
||||
Player.dexterity_exp_mult *= 1.05;
|
||||
Player.defense_exp_mult *= 1.1;
|
||||
Player.dexterity_exp_mult *= 1.1;
|
||||
Player.bladeburner_analysis_mult *= 1.15;
|
||||
Player.bladeburner_success_chance_mult *= 1.05;
|
||||
break;
|
||||
case AugmentationNames.INTERLINKED:
|
||||
Player.strength_exp_mult *= 1.04;
|
||||
Player.defense_exp_mult *= 1.04;
|
||||
Player.dexterity_exp_mult *= 1.04;
|
||||
Player.agility_exp_mult *= 1.04;
|
||||
Player.strength_exp_mult *= 1.05;
|
||||
Player.defense_exp_mult *= 1.05;
|
||||
Player.dexterity_exp_mult *= 1.05;
|
||||
Player.agility_exp_mult *= 1.05;
|
||||
Player.bladeburner_max_stamina_mult *= 1.1;
|
||||
break;
|
||||
case AugmentationNames.BladeRunner:
|
||||
@ -2347,10 +2347,10 @@ function applyAugmentation(aug, reapply=false) {
|
||||
Player.bladeburner_stamina_gain_mult *= 1.05;
|
||||
break;
|
||||
case AugmentationNames.BladeArmor:
|
||||
Player.strength_mult *= 1.02;
|
||||
Player.defense_mult *= 1.02;
|
||||
Player.dexterity_mult *= 1.02;
|
||||
Player.agility_mult *= 1.02;
|
||||
Player.strength_mult *= 1.04;
|
||||
Player.defense_mult *= 1.04;
|
||||
Player.dexterity_mult *= 1.04;
|
||||
Player.agility_mult *= 1.04;
|
||||
Player.bladeburner_stamina_gain_mult *= 1.02;
|
||||
Player.bladeburner_success_chance_mult *= 1.03;
|
||||
break;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import {Player} from "./Player";
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {Player} from "./Player";
|
||||
|
||||
function BitNode(n, name, desc="", info="") {
|
||||
this.number = n;
|
||||
@ -141,7 +142,7 @@ function initBitNodes() {
|
||||
BitNodes["BitNode8"] = new BitNode(8, "Ghost of Wall Street", "Money never sleeps",
|
||||
"You are trying to make a name for yourself as an up-and-coming hedge fund manager on Wall Street.<br><br>" +
|
||||
"In this BitNode:<br><br>" +
|
||||
"You start with $100 million<br>" +
|
||||
"You start with $250 million<br>" +
|
||||
"The only way to earn money is by trading on the stock market<br>" +
|
||||
"You start with a WSE membership and access to the TIX API<br>" +
|
||||
"You are able to short stocks and place different types of orders (limit/stop)<br>" +
|
||||
@ -199,43 +200,6 @@ function initBitNodes() {
|
||||
BitNodes["BitNode24"] = new BitNode(24, "", "COMING SOON");
|
||||
}
|
||||
|
||||
let BitNodeMultipliers = {
|
||||
HackingLevelMultiplier: 1,
|
||||
|
||||
ServerMaxMoney: 1,
|
||||
ServerStartingMoney: 1,
|
||||
ServerGrowthRate: 1,
|
||||
ServerWeakenRate: 1,
|
||||
ServerStartingSecurity: 1,
|
||||
|
||||
ManualHackMoney: 1,
|
||||
ScriptHackMoney: 1,
|
||||
CompanyWorkMoney: 1,
|
||||
CrimeMoney: 1,
|
||||
HacknetNodeMoney: 1,
|
||||
|
||||
CompanyWorkExpGain: 1,
|
||||
ClassGymExpGain: 1,
|
||||
FactionWorkExpGain: 1,
|
||||
HackExpGain: 1,
|
||||
CrimeExpGain: 1,
|
||||
|
||||
FactionWorkRepGain: 1,
|
||||
FactionPassiveRepGain: 1,
|
||||
RepToDonateToFaction: 1,
|
||||
|
||||
AugmentationRepCost: 1,
|
||||
AugmentationMoneyCost: 1,
|
||||
|
||||
InfiltrationMoney: 1,
|
||||
InfiltrationRep: 1,
|
||||
|
||||
CorporationValuation: 1,
|
||||
|
||||
BladeburnerRank: 1,
|
||||
BladeburnerSkillCost: 1,
|
||||
}
|
||||
|
||||
function initBitNodeMultipliers() {
|
||||
if (Player.bitNodeN == null) {
|
||||
Player.bitNodeN = 1;
|
||||
@ -394,7 +358,7 @@ function initBitNodeMultipliers() {
|
||||
BitNodeMultipliers.CorporationValuation = dec;
|
||||
|
||||
BitNodeMultipliers.BladeburnerRank = dec;
|
||||
BitNodeMultipliers.BladeburnerSkillCost = dec;
|
||||
BitNodeMultipliers.BladeburnerSkillCost = inc;
|
||||
break;
|
||||
default:
|
||||
console.log("WARNING: Player.bitNodeN invalid");
|
||||
@ -403,7 +367,5 @@ function initBitNodeMultipliers() {
|
||||
}
|
||||
|
||||
export {initBitNodes,
|
||||
BitNode,
|
||||
BitNodes,
|
||||
BitNodeMultipliers,
|
||||
initBitNodeMultipliers};
|
||||
|
178
src/BitNodeMultipliers.ts
Normal file
178
src/BitNodeMultipliers.ts
Normal file
@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Bitnode multipliers influence the difficulty of different aspects of the game.
|
||||
* Each Bitnode has a different theme/strategy to achieving the end goal, so these multipliers will can help drive the
|
||||
* player toward the intended strategy. Unless they really want to play the long, slow game of waiting...
|
||||
*/
|
||||
interface IBitNodeMultipliers {
|
||||
/**
|
||||
* Influences the base cost to purchase an augmentation.
|
||||
*/
|
||||
AugmentationMoneyCost: number;
|
||||
|
||||
/**
|
||||
* Influences the base rep the player must have with a faction to purchase an augmentation.
|
||||
*/
|
||||
AugmentationRepCost: number;
|
||||
|
||||
/**
|
||||
* Influences how quickly the player can gain rank within Bladeburner.
|
||||
*/
|
||||
BladeburnerRank: number;
|
||||
|
||||
/**
|
||||
* Influences the cost of skill levels from Bladeburner.
|
||||
*/
|
||||
BladeburnerSkillCost: number;
|
||||
|
||||
/**
|
||||
* Influences the experience gained for each ability when a player completes a class.
|
||||
*/
|
||||
ClassGymExpGain: number;
|
||||
|
||||
/**
|
||||
* Influences the experience gained for each ability when the player completes working their job.
|
||||
*/
|
||||
CompanyWorkExpGain: number;
|
||||
|
||||
/**
|
||||
* Influences how much money the player earns when completing working their job.
|
||||
*/
|
||||
CompanyWorkMoney: number;
|
||||
|
||||
/**
|
||||
* Influences the valuation of corporations created by the player.
|
||||
*/
|
||||
CorporationValuation: number;
|
||||
|
||||
/**
|
||||
* Influences the base experience gained for each ability when the player commits a crime.
|
||||
*/
|
||||
CrimeExpGain: number;
|
||||
|
||||
/**
|
||||
* Influences the base money gained when the player commits a crime.
|
||||
*/
|
||||
CrimeMoney: number;
|
||||
|
||||
/**
|
||||
* Influences how much rep the player gains in each faction simply by being a member.
|
||||
*/
|
||||
FactionPassiveRepGain: number;
|
||||
|
||||
/**
|
||||
* Influences the experience gained for each ability when the player completes work for a Faction.
|
||||
*/
|
||||
FactionWorkExpGain: number;
|
||||
|
||||
/**
|
||||
* Influences how much rep the player gains when performing work for a faction.
|
||||
*/
|
||||
FactionWorkRepGain: number;
|
||||
|
||||
/**
|
||||
* Influences the experienced gained when hacking a server.
|
||||
*/
|
||||
HackExpGain: number;
|
||||
|
||||
/**
|
||||
* Influences how quickly the player's hacking level (not experience) scales
|
||||
*/
|
||||
HackingLevelMultiplier: number;
|
||||
|
||||
/**
|
||||
* Influences how much money each Hacknet node can generate.
|
||||
*/
|
||||
HacknetNodeMoney: number;
|
||||
|
||||
/**
|
||||
* Influences how much money is gained when the player infiltrates a company.
|
||||
*/
|
||||
InfiltrationMoney: number;
|
||||
|
||||
/**
|
||||
* Influences how much rep the player can gain from factions when selling stolen documents and secrets
|
||||
*/
|
||||
InfiltrationRep: number;
|
||||
|
||||
/**
|
||||
* Influences how much money can be stolen from a server when the player performs a hack against it through
|
||||
* the Terminal.
|
||||
*/
|
||||
ManualHackMoney: number;
|
||||
|
||||
/**
|
||||
* Influences the minimum favor the player must have with a faction before they can donate to gain rep.
|
||||
*/
|
||||
RepToDonateToFaction: number;
|
||||
|
||||
/**
|
||||
* Influences how much money can be stolen from a server when a script performs a hack against it.
|
||||
*/
|
||||
ScriptHackMoney: number;
|
||||
|
||||
/**
|
||||
* Influences the growth percentage per cycle against a server.
|
||||
*/
|
||||
ServerGrowthRate: number;
|
||||
|
||||
/**
|
||||
* Influences the maxmimum money that a server can grow to.
|
||||
*/
|
||||
ServerMaxMoney: number;
|
||||
|
||||
/**
|
||||
* Influences the initial money that a server starts with.
|
||||
*/
|
||||
ServerStartingMoney: number;
|
||||
|
||||
/**
|
||||
* Influences the initial security level (hackDifficulty) of a server.
|
||||
*/
|
||||
ServerStartingSecurity: number;
|
||||
|
||||
/**
|
||||
* Influences the weaken amount per invocation against a server.
|
||||
*/
|
||||
ServerWeakenRate: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* The multipliers that are influenced by current Bitnode progression.
|
||||
*/
|
||||
// tslint:disable-next-line:variable-name
|
||||
export const BitNodeMultipliers: IBitNodeMultipliers = {
|
||||
HackingLevelMultiplier: 1,
|
||||
|
||||
ServerGrowthRate: 1,
|
||||
ServerMaxMoney: 1,
|
||||
ServerStartingMoney: 1,
|
||||
ServerStartingSecurity: 1,
|
||||
ServerWeakenRate: 1,
|
||||
|
||||
CompanyWorkMoney: 1,
|
||||
CrimeMoney: 1,
|
||||
HacknetNodeMoney: 1,
|
||||
ManualHackMoney: 1,
|
||||
ScriptHackMoney: 1,
|
||||
|
||||
ClassGymExpGain: 1,
|
||||
CompanyWorkExpGain: 1,
|
||||
CrimeExpGain: 1,
|
||||
FactionWorkExpGain: 1,
|
||||
HackExpGain: 1,
|
||||
|
||||
FactionPassiveRepGain: 1,
|
||||
FactionWorkRepGain: 1,
|
||||
RepToDonateToFaction: 1,
|
||||
|
||||
AugmentationMoneyCost: 1,
|
||||
AugmentationRepCost: 1,
|
||||
|
||||
InfiltrationMoney: 1,
|
||||
InfiltrationRep: 1,
|
||||
|
||||
CorporationValuation: 1,
|
||||
|
||||
BladeburnerRank: 1,
|
||||
BladeburnerSkillCost: 1,
|
||||
};
|
@ -1,13 +1,13 @@
|
||||
import {Augmentations, AugmentationNames} from "./Augmentations";
|
||||
import {BitNodeMultipliers} from "./BitNode";
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Engine} from "./engine";
|
||||
import {Faction, Factions, factionExists,
|
||||
joinFaction, displayFactionContent} from "./Faction";
|
||||
import {Locations} from "./Location";
|
||||
import {Locations} from "./Locations";
|
||||
import {Player} from "./Player";
|
||||
import {hackWorldDaemon, redPillFlag} from "./RedPill";
|
||||
import {KEY} from "./Terminal";
|
||||
import {KEY} from "../utils/helpers/keyCodes";
|
||||
|
||||
import {createProgressBarText} from "../utils/helpers/createProgressBarText";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
@ -20,6 +20,7 @@ import {appendLineBreaks} from "../utils/uiHelpers/app
|
||||
import {clearObject} from "../utils/helpers/clearObject";
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {createPopup} from "../utils/uiHelpers/createPopup";
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
|
||||
import {formatNumber} from "../utils/StringHelperFunctions";
|
||||
import {getRandomInt} from "../utils/helpers/getRandomInt";
|
||||
@ -61,12 +62,12 @@ var ActionCountGrowthPeriod = 300; //Time (s) it takes for action count to g
|
||||
var RankToFactionRepFactor = 2; //Delta Faction Rep = this * Delta Rank
|
||||
var RankNeededForFaction = 25;
|
||||
|
||||
var ContractSuccessesPerLevel = 3; //How many successes you need to level up a contract
|
||||
var OperationSuccessesPerLevel = 2.5; //How many successes you need to level up an op
|
||||
var ContractSuccessesPerLevel = 3.5; //How many successes you need to level up a contract
|
||||
var OperationSuccessesPerLevel = 3; //How many successes you need to level up an op
|
||||
|
||||
var RanksPerSkillPoint = 4; //How many ranks needed to get 1 Skill Point
|
||||
|
||||
var ContractBaseMoneyGain = 40e3; //Base Money Gained per contract
|
||||
var ContractBaseMoneyGain = 50e3; //Base Money Gained per contract
|
||||
|
||||
//DOM related variables
|
||||
var ActiveActionCssClass = "bladeburner-active-action";
|
||||
@ -145,7 +146,7 @@ var consoleHelpText = {
|
||||
|
||||
//Keypresses for Console
|
||||
$(document).keydown(function(event) {
|
||||
if (Engine.currentPage === Engine.Page.Bladeburner) {
|
||||
if (routing.isOn(Page.Bladeburner)) {
|
||||
//if (DomElems.consoleInput && !event.ctrlKey && !event.shiftKey && !event.altKey) {
|
||||
// DomElems.consoleInput.focus();
|
||||
//}
|
||||
@ -213,8 +214,8 @@ function City(params={}) {
|
||||
this.popEst = this.pop * (Math.random() + 0.5);
|
||||
|
||||
//Number of Synthoid communities population and estimate
|
||||
this.comms = params.comms ? params.comms : getRandomInt(1, 40);
|
||||
this.commsEst = this.comms + getRandomInt(-2, 2);
|
||||
this.comms = params.comms ? params.comms : getRandomInt(5, 100);
|
||||
this.commsEst = this.comms + getRandomInt(-5, 5);
|
||||
if (this.commsEst < 0) {this.commsEst = 0;}
|
||||
this.chaos = 0;
|
||||
}
|
||||
@ -733,7 +734,7 @@ Bladeburner.prototype.create = function() {
|
||||
"whatever city you are currently in.",
|
||||
baseDifficulty:125,difficultyFac:1.02,rewardFac:1.041,
|
||||
rankGain:0.3, hpLoss:0.5,
|
||||
count:getRandomInt(300, 800), countGrowth:getRandomInt(1, 5),
|
||||
count:getRandomInt(100, 500), countGrowth:getRandomInt(5, 75)/10,
|
||||
weights:{hack:0,str:0.05,def:0.05,dex:0.35,agi:0.35,cha:0.1, int:0.05},
|
||||
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.9, int:1},
|
||||
isStealth:true
|
||||
@ -745,7 +746,7 @@ Bladeburner.prototype.create = function() {
|
||||
"current city, and will also increase its chaos level.",
|
||||
baseDifficulty:250, difficultyFac:1.04,rewardFac:1.085,
|
||||
rankGain:0.9, hpLoss:1,
|
||||
count:getRandomInt(200, 750), countGrowth:getRandomInt(1, 3),
|
||||
count:getRandomInt(25, 750), countGrowth:getRandomInt(5, 75)/10,
|
||||
weights:{hack:0,str:0.15,def:0.15,dex:0.25,agi:0.25,cha:0.1, int:0.1},
|
||||
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
|
||||
isKill:true
|
||||
@ -757,7 +758,7 @@ Bladeburner.prototype.create = function() {
|
||||
"city, and will also increase its chaos level.",
|
||||
baseDifficulty:200, difficultyFac:1.03, rewardFac:1.065,
|
||||
rankGain:0.6, hpLoss:1,
|
||||
count:getRandomInt(300, 900), countGrowth:getRandomInt(1,4),
|
||||
count:getRandomInt(50, 1000), countGrowth:getRandomInt(5,75)/10,
|
||||
weights:{hack:0,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0.1, int:0.1},
|
||||
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
|
||||
isKill:true
|
||||
@ -771,8 +772,8 @@ Bladeburner.prototype.create = function() {
|
||||
"synthoid data.<br><br>" +
|
||||
"You will NOT lose HP from failed Investigation ops.",
|
||||
baseDifficulty:400, difficultyFac:1.03,rewardFac:1.07,reqdRank:25,
|
||||
rankGain:2, rankLoss:0.2,
|
||||
count:getRandomInt(50, 400), countGrowth:1,
|
||||
rankGain:2.2, rankLoss:0.2,
|
||||
count:getRandomInt(50, 200), countGrowth:getRandomInt(10, 40)/10,
|
||||
weights:{hack:0.25,str:0.05,def:0.05,dex:0.2,agi:0.1,cha:0.25, int:0.1},
|
||||
decays:{hack:0.85,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
|
||||
isStealth:true
|
||||
@ -784,8 +785,8 @@ Bladeburner.prototype.create = function() {
|
||||
"Successful Undercover ops will increase the accuracy of your synthoid " +
|
||||
"data.",
|
||||
baseDifficulty:500, difficultyFac:1.04, rewardFac:1.09, reqdRank:100,
|
||||
rankGain:4, rankLoss:0.4, hpLoss:2,
|
||||
count:getRandomInt(50, 300), countGrowth:1,
|
||||
rankGain:4.4, rankLoss:0.4, hpLoss:2,
|
||||
count:getRandomInt(25, 300), countGrowth:getRandomInt(10, 40)/10,
|
||||
weights:{hack:0.2,str:0.05,def:0.05,dex:0.2,agi:0.2,cha:0.2, int:0.1},
|
||||
decays:{hack:0.8,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
|
||||
isStealth:true
|
||||
@ -795,8 +796,8 @@ Bladeburner.prototype.create = function() {
|
||||
desc:"Conduct a sting operation to bait and capture particularly " +
|
||||
"notorious Synthoid criminals.",
|
||||
baseDifficulty:650, difficultyFac:1.04, rewardFac:1.095, reqdRank:500,
|
||||
rankGain:5, rankLoss:0.5, hpLoss:2.5,
|
||||
count:getRandomInt(25,400), countGrowth:0.75,
|
||||
rankGain:5.5, rankLoss:0.5, hpLoss:2.5,
|
||||
count:getRandomInt(25,400), countGrowth:getRandomInt(3, 40)/10,
|
||||
weights:{hack:0.25,str:0.05,def:0.05,dex:0.25,agi:0.1,cha:0.2, int:0.1},
|
||||
decays:{hack:0.8,str:0.85,def:0.85,dex:0.85,agi:0.85,cha:0.7, int:0.9},
|
||||
isStealth:true
|
||||
@ -807,8 +808,8 @@ Bladeburner.prototype.create = function() {
|
||||
"there must be an existing Synthoid community in your current city " +
|
||||
"in order for this Operation to be successful",
|
||||
baseDifficulty:800, difficultyFac:1.045, rewardFac:1.1, reqdRank:3000,
|
||||
rankGain:50,rankLoss:2.5,hpLoss:50,
|
||||
count:getRandomInt(25, 150), countGrowth:0.2,
|
||||
rankGain:55,rankLoss:2.5,hpLoss:50,
|
||||
count:getRandomInt(25, 150), countGrowth:getRandomInt(2, 40)/10,
|
||||
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
|
||||
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
|
||||
isKill:true
|
||||
@ -819,8 +820,8 @@ Bladeburner.prototype.create = function() {
|
||||
"objective is to complete the task without " +
|
||||
"drawing any attention. Stealth and discretion are key.",
|
||||
baseDifficulty:1000, difficultyFac:1.05, rewardFac:1.11, reqdRank:20e3,
|
||||
rankGain:20, rankLoss:2, hpLoss:10,
|
||||
count:getRandomInt(25, 250), countGrowth:0.1,
|
||||
rankGain:22, rankLoss:2, hpLoss:10,
|
||||
count:getRandomInt(25, 250), countGrowth:getRandomInt(1, 20)/10,
|
||||
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
|
||||
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
|
||||
isStealth:true, isKill:true
|
||||
@ -831,8 +832,8 @@ Bladeburner.prototype.create = function() {
|
||||
"important, high-profile social and political leaders " +
|
||||
"in the Synthoid communities.",
|
||||
baseDifficulty:1500, difficultyFac:1.06, rewardFac:1.14, reqdRank:50e3,
|
||||
rankGain:40, rankLoss:4, hpLoss:5,
|
||||
count:getRandomInt(25, 200), countGrowth:0.1,
|
||||
rankGain:44, rankLoss:4, hpLoss:5,
|
||||
count:getRandomInt(25, 200), countGrowth:getRandomInt(1, 20)/10,
|
||||
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
|
||||
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.8},
|
||||
isStealth:true, isKill:true
|
||||
@ -852,8 +853,12 @@ Bladeburner.prototype.process = function() {
|
||||
//If the Player starts doing some other actions, set action to idle and alert
|
||||
if (Augmentations[AugmentationNames.BladesSimulacrum].owned === false && Player.isWorking) {
|
||||
if (this.action.type !== ActionTypes["Idle"]) {
|
||||
dialogBoxCreate("Your Bladeburner action was cancelled because you started " +
|
||||
"doing something else");
|
||||
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
|
||||
if (this.automateEnabled) {
|
||||
msg += `<br><br>Your automation was disabled as well. You will have to re-enable it through the Bladeburner console`
|
||||
this.automateEnabled = false;
|
||||
}
|
||||
dialogBoxCreate(msg);
|
||||
}
|
||||
this.resetAction();
|
||||
}
|
||||
@ -915,7 +920,7 @@ Bladeburner.prototype.process = function() {
|
||||
}
|
||||
}
|
||||
|
||||
if (Engine.currentPage === Engine.Page.Bladeburner) {
|
||||
if (routing.isOn(Page.Bladeburner)) {
|
||||
this.updateContent();
|
||||
}
|
||||
}
|
||||
@ -1257,7 +1262,7 @@ Bladeburner.prototype.completeAction = function() {
|
||||
return hackWorldDaemon(Player.bitNodeN);
|
||||
}
|
||||
|
||||
if (Engine.currentPage === Engine.Page.Bladeburner) {
|
||||
if (routing.isOn(Page.Bladeburner)) {
|
||||
this.createActionAndSkillsContent();
|
||||
}
|
||||
|
||||
@ -1338,7 +1343,7 @@ Bladeburner.prototype.completeAction = function() {
|
||||
Player.gainHackingExp(hackingExpGain);
|
||||
Player.gainIntelligenceExp(BaseIntGain);
|
||||
Player.gainCharismaExp(charismaExpGain);
|
||||
this.changeRank(0.1);
|
||||
this.changeRank(0.1 * BitNodeMultipliers.BladeburnerRank);
|
||||
console.log("DEBUG: Field Analysis effectiveness is " + (eff * this.skillMultipliers.successChanceEstimate));
|
||||
this.getCurrentCity().improvePopulationEstimateByPercentage(eff * this.skillMultipliers.successChanceEstimate);
|
||||
if (this.logging.general) {
|
||||
@ -1527,7 +1532,7 @@ Bladeburner.prototype.randomEvent = function() {
|
||||
var destCity = this.cities[destCityName];
|
||||
|
||||
if (!(sourceCity instanceof City) || !(destCity instanceof City)) {
|
||||
throw new Error("sourceCity was not a City object in Bladeburner.randomEvent()");
|
||||
throw new Error("sourceCity/destCity was not a City object in Bladeburner.randomEvent()");
|
||||
}
|
||||
|
||||
if (chance <= 0.05) {
|
||||
@ -1824,8 +1829,8 @@ Bladeburner.prototype.createOverviewContent = function() {
|
||||
DomElems.overviewBonusTime = createElement("p", {
|
||||
innerText: "Bonus time: ",
|
||||
display: "inline-block",
|
||||
tooltip: "You gain bonus time while offline or when you're not performing any action. " +
|
||||
"Bonus time makes the game progress faster."
|
||||
tooltip: "You gain bonus time while offline or when the game is inactive (e.g. when the tab is throttled by browser). " +
|
||||
"Bonus time makes the Bladeburner mechanic progress faster, up to 5x the normal speed."
|
||||
});
|
||||
DomElems.overviewSkillPoints = createElement("p", {display:"block"});
|
||||
|
||||
@ -2194,7 +2199,7 @@ Bladeburner.prototype.updateContent = function() {
|
||||
}
|
||||
|
||||
Bladeburner.prototype.updateOverviewContent = function() {
|
||||
if (Engine.currentPage !== Engine.Page.Bladeburner) {return;}
|
||||
if (!routing.isOn(Page.Bladeburner)) {return;}
|
||||
DomElems.overviewRank.childNodes[0].nodeValue = "Rank: " + formatNumber(this.rank, 2);
|
||||
DomElems.overviewStamina.innerText = "Stamina: " + formatNumber(this.stamina, 3) + " / " + formatNumber(this.maxStamina, 3);
|
||||
DomElems.overviewGen1.innerHTML =
|
||||
@ -3465,6 +3470,27 @@ Bladeburner.prototype.getSkillLevelNetscriptFn = function(skillName, workerScrip
|
||||
}
|
||||
}
|
||||
|
||||
Bladeburner.prototype.getSkillUpgradeCostNetscriptFn = function(skillName, workerScript) {
|
||||
var errorLogText = "ERROR: bladeburner.getSkillUpgradeCostNetscriptFn() failed due to an invalid skill specified: " +
|
||||
skillName + ". Note that the name of the skill is case-sensitive";
|
||||
|
||||
if (skillName === "") {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!Skills.hasOwnProperty(skillName)) {
|
||||
workerScript.log(errorLogText);
|
||||
return -1;
|
||||
}
|
||||
|
||||
var skill = Skills[skillName];
|
||||
if (this.skills[skillName] == null) {
|
||||
return skill.calculateCost(0);
|
||||
} else {
|
||||
return skill.calculateCost(this.skills[skillName]);
|
||||
}
|
||||
}
|
||||
|
||||
Bladeburner.prototype.upgradeSkillNetscriptFn = function(skillName, workerScript) {
|
||||
var errorLogText = "ERROR: bladeburner.upgradeSkill() failed due to an invalid skill specified: " +
|
||||
skillName + ". Note that the name of the skill is case-sensitive";
|
||||
@ -3498,7 +3524,7 @@ Bladeburner.prototype.upgradeSkillNetscriptFn = function(skillName, workerScript
|
||||
|
||||
this.skillPoints -= cost;
|
||||
this.upgradeSkill(skill);
|
||||
if (Engine.currentPage === Engine.Page.Bladeburner && DomElems.currentTab.toLowerCase() === "skills") {
|
||||
if (routing.isOn(Page.Bladeburner) && DomElems.currentTab.toLowerCase() === "skills") {
|
||||
this.createActionAndSkillsContent();
|
||||
}
|
||||
if (workerScript.shouldLog("upgradeSkill")) {
|
||||
@ -3620,7 +3646,7 @@ Bladeburner.prototype.joinBladeburnerFactionNetscriptFn = function(workerScript)
|
||||
if (workerScript.shouldLog("joinBladeburnerFaction")) {
|
||||
workerScript.log("Joined Bladeburners Faction");
|
||||
}
|
||||
if (Engine.currentPage === Engine.Page.Bladeburner) {
|
||||
if (routing.isOn(Page.Bladeburner)) {
|
||||
removeChildrenFromElement(DomElems.overviewDiv);
|
||||
this.createOverviewContent();
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Locations} from "./Location";
|
||||
import {Player} from "./Player";
|
||||
import {Locations} from "./Locations";
|
||||
|
||||
import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver";
|
||||
|
@ -1,8 +1,7 @@
|
||||
import {BitNodeMultipliers} from "./BitNode";
|
||||
import {Engine} from "./engine";
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {Factions} from "./Faction";
|
||||
import {showLiterature} from "./Literature";
|
||||
import {Locations} from "./Location";
|
||||
import {Locations} from "./Locations";
|
||||
import {Player} from "./Player";
|
||||
|
||||
import Decimal from "decimal.js";
|
||||
@ -13,6 +12,7 @@ import {Reviver, Generic_toJSON,
|
||||
import numeral from "numeral/min/numeral.min";
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {createPopup} from "../utils/uiHelpers/createPopup";
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
import {formatNumber, generateRandomString} from "../utils/StringHelperFunctions";
|
||||
import {getRandomInt} from "../utils/helpers/getRandomInt";
|
||||
import {isString} from "../utils/helpers/isString";
|
||||
@ -3118,7 +3118,7 @@ Corporation.prototype.process = function() {
|
||||
|
||||
this.state.nextState();
|
||||
|
||||
if (Engine.currentPage === Engine.Page.Corporation) {this.updateUIContent();}
|
||||
if (routing.isOn(Page.Corporation)) {this.updateUIContent();}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
let CONSTANTS = {
|
||||
Version: "0.40.0",
|
||||
Version: "0.40.2",
|
||||
|
||||
//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
|
||||
@ -115,6 +115,8 @@ let CONSTANTS = {
|
||||
//Stock market constants
|
||||
WSEAccountCost: 200e6,
|
||||
TIXAPICost: 5e9,
|
||||
MarketData4SCost: 1e9,
|
||||
MarketDataTixApi4SCost: 20e9,
|
||||
StockMarketCommission: 100e3,
|
||||
|
||||
//Hospital/Health
|
||||
@ -491,19 +493,32 @@ let CONSTANTS = {
|
||||
"World Stock Exchange account and TIX API Access<br>",
|
||||
|
||||
LatestUpdate:
|
||||
"v0.40.1 - Community Update<br>" +
|
||||
"* Added getPurchasedServerCost() Netscript function (by kopelli)<br>" +
|
||||
"* Added getFavorToDonate() Netscript function (by hydroflame)<br>" +
|
||||
"* Added getFactionFavorGain() and getCompanyFavorGain() Singularity functions (by hydroflame)<br>" +
|
||||
"* Accumulated 'bonus' time in Bladeburner is now displayed in the UI (by hydroflame)<br>" +
|
||||
"* The Red Pill can now be purchased with negative money (since its supposed to be free) (by hydroflame)<br>" +
|
||||
"* Cranial Signal Processor Augmentations now have the previous generation as a prerequisite. i.e. Cranial Signal Processor - Gen II requires Gen I (by Kline-)<br>" +
|
||||
"* Bladeburner Raid operations can no longer be performed if your estimate of Synthoid communities is zero (by hydroflame)<br>" +
|
||||
"* The difficulty of BN-12 now scales faster (by hydroflame)<br>" +
|
||||
"* Active Scripts UI now shows a RAM Usage bar for each server (by kopelli)<br>" +
|
||||
"* Bug Fix: Corrected terminal timestamp format (by kopelli)<br>" +
|
||||
"* Bug Fix: NetscriptJS scripts should now die properly if they don't have a 'main' function (by hydroflame)<br>" +
|
||||
"* Various minor UI/QOL fixes by hydroflame, kopelli, and Kline-"
|
||||
"v0.40.2<br>" +
|
||||
"------------------------------<br>" +
|
||||
"* Bladeburner Changes:<br>" +
|
||||
"*** Added getBonusTime(), getSkillUpgradeCost(), and getCity() Netscript functions to the API<br>" +
|
||||
"*** Buffed the effects of many Bladeburner Augmentations<br>" +
|
||||
"*** The Blade's Simulacrum Augmentation requires significantly less reputation but slightly more money<br>" +
|
||||
"*** Slightly increased the amount of successes needed for a Contract/Operation in order to increase its max level<br>" +
|
||||
"*** Increased the amount of money gained from Contracts by ~25%<br>" +
|
||||
"*** Increased the base amount of rank gained from Operations by 10%<br>" +
|
||||
"*** Significantly increased the 'randomness' in determining a Contract/Operation's initial count and rate of count increase<br>" +
|
||||
"*** The number (count) of Operations should now increase significantly faster<br>" +
|
||||
"*** There are now, on average, more Synthoid communities in a city<br>" +
|
||||
"*** If automation is enabled (the feature in Bladeburner console), then switching to another action such as working for a company will now disable the automation<br>" +
|
||||
"------------------------------<br>" +
|
||||
"* Stock Market Changes:<br>" +
|
||||
"***Added a watchlist filter feature to the UI that allows you to specify which stocks to show<br>" +
|
||||
"***Added the Four Sigma (4S) Market Data feed, which provides volatility and price forecast information about stocks<br>" +
|
||||
"***Added the 4S Market Data TIX API, which lets you access the aforementioned data through Netscript<br>" +
|
||||
"------------------------------<br>" +
|
||||
"* There is now a setting for enabling/disabling the popup that appears when you are hospitalized<br>" +
|
||||
"* Bug Fix: Stock market should now be correctly initialized in BitNode-8 (by Kline-)<br>" +
|
||||
"* Bug Fix: bladeburner.getCurrentAction() should now properly an 'Idle' object rather than null (by Kline-)<br>" +
|
||||
"* Bug Fix: Bladeburner skill cost multiplier should now properly increase in BitNode-12 (by hydroflame)<br>" +
|
||||
"* Bug Fix: 'document', 'hacknet', and 'window' keywords should no longer be counted multiple times in RAM calculations<br>" +
|
||||
"* Bug Fix: Joining factions through Singularity functions should now prevent you from joining opposing factions<br>" +
|
||||
"* Bug Fix: Four Sigma should no longer have two 'Speech Enhancement' Augmentations (by Kline-)<br>"
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {Programs} from "./CreateProgram";
|
||||
import {Player} from "./Player";
|
||||
import {SpecialServerIps} from "./SpecialServerIps";
|
||||
import {post} from "./Terminal";
|
||||
import {post} from "./ui/postToTerminal";
|
||||
|
||||
import {isValidIPAddress} from "../utils/helpers/isValidIPAddress";
|
||||
import {formatNumber} from "../utils/StringHelperFunctions";
|
||||
|
@ -1,6 +1,6 @@
|
||||
import {Augmentations, AugmentationNames,
|
||||
PlayerOwnedAugmentation} from "./Augmentations";
|
||||
import {BitNodeMultipliers} from "./BitNode";
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Engine} from "./engine";
|
||||
import {FactionInfos} from "./FactionInfo";
|
||||
@ -9,6 +9,7 @@ import {HackingMission, setInMission} from "./Missions";
|
||||
import {Player} from "./Player";
|
||||
import {Settings} from "./Settings";
|
||||
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {factionInvitationBoxCreate} from "../utils/FactionInvitationBox";
|
||||
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
@ -137,7 +138,7 @@ function inviteToFaction(faction) {
|
||||
if (Settings.SuppressFactionInvites) {
|
||||
faction.alreadyInvited = true;
|
||||
Player.factionInvitations.push(faction.name);
|
||||
if (Engine.currentPage === Engine.Page.Factions) {
|
||||
if (routing.isOn(Page.Factions)) {
|
||||
Engine.loadFactionsContent();
|
||||
}
|
||||
} else {
|
||||
|
@ -64,166 +64,360 @@ class FactionInfo {
|
||||
*/
|
||||
// tslint:disable-next-line:variable-name
|
||||
export const FactionInfos: IMap<FactionInfo> = {
|
||||
// Endgame
|
||||
Illuminati: new FactionInfo("Humanity never changes. No matter how civilized society becomes, it will eventually " +
|
||||
"fall back into chaos. And from this chaos, we are the Invisible hand that guides them to order. ",
|
||||
[], true, true, true, false),
|
||||
// Endgame
|
||||
Illuminati: new FactionInfo(
|
||||
"Humanity never changes. No matter how civilized society becomes, it will eventually fall back into chaos. " +
|
||||
"And from this chaos, we are the Invisible hand that guides them to order. ",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false),
|
||||
|
||||
Daedalus: new FactionInfo("Yesterday we obeyed kings and bent our necks to emperors. Today we kneel only to truth.",
|
||||
[], true, true, true, false),
|
||||
Daedalus: new FactionInfo(
|
||||
"Yesterday we obeyed kings and bent our necks to emperors. Today we kneel only to truth.",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false),
|
||||
|
||||
"The Covenant": new FactionInfo("Surrender yourself. Give up your empty individuality to become part of something " +
|
||||
"great, something eternal. Become a slave. Submit your mind, body, and soul. Only " +
|
||||
"then can you set yourself free.<br><br> Only then can you discover immortality.",
|
||||
[], true, true, true, false),
|
||||
"The Covenant": new FactionInfo(
|
||||
"Surrender yourself. Give up your empty individuality to become part of something great, something eternal. " +
|
||||
"Become a slave. Submit your mind, body, and soul. Only then can you set yourself free.<br>" +
|
||||
"<br>" +
|
||||
"Only then can you discover immortality.",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false),
|
||||
|
||||
// Megacorporations, each forms its own faction
|
||||
ECorp: new FactionInfo("ECorp's mission is simple: to connect the world of today with the technology of tomorrow. " +
|
||||
"With our wide range of Internet-related software and commercial hardware, ECorp makes " +
|
||||
"the world's information universally accessible.",
|
||||
[], true, true, true, true),
|
||||
// Megacorporations, each forms its own faction
|
||||
ECorp: new FactionInfo(
|
||||
"ECorp's mission is simple: to connect the world of today with the technology of tomorrow. With our wide " +
|
||||
"range of Internet-related software and commercial hardware, ECorp makes the world's information " +
|
||||
"universally accessible.",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
MegaCorp: new FactionInfo("MegaCorp does things that others don't. We imagine. We create. We invent. We build " +
|
||||
"things that others have never even dreamed of. Our work fills the world's needs for " +
|
||||
"food, water, power, and transporation on an unprecendented scale, in ways that no " +
|
||||
"other company can.<br><br>In our labs and factories and on the ground with customers, " +
|
||||
"MegaCorp is ushering in a new era for the world.",
|
||||
[], true, true, true, true),
|
||||
MegaCorp: new FactionInfo(
|
||||
"MegaCorp does things that others don't. We imagine. We create. We invent. We build things that others have " +
|
||||
"never even dreamed of. Our work fills the world's needs for food, water, power, and transporation on an " +
|
||||
"unprecendented scale, in ways that no other company can.<br>" +
|
||||
"<br>" +
|
||||
"In our labs and factories and on the ground with customers, MegaCorp is ushering in a new era for the world.",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
"Bachman & Associates": new FactionInfo("Where Law and Business meet - thats where we are. <br><br>" +
|
||||
"Legal Insight - Business Instinct - Experience Innovation",
|
||||
[], true, true, true, true),
|
||||
"Bachman & Associates": new FactionInfo(
|
||||
"Where Law and Business meet - thats where we are.<br>" +
|
||||
"<br>" +
|
||||
"Legal Insight - Business Instinct - Experience Innovation",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
"Blade Industries": new FactionInfo("Augmentation is salvation", [], true, true, true, true),
|
||||
"Blade Industries": new FactionInfo(
|
||||
"Augmentation is salvation",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
NWO: new FactionInfo("The human being does not truly desire freedom. It wants " +
|
||||
"to be observed, understood, and judged. It wants to be given purpose and " +
|
||||
"direction in its life. That is why humans created God. " +
|
||||
"And that is why humans created civilization - " +
|
||||
"not because of willingness, " +
|
||||
"but because of a need to be incorporated into higher orders of structure and meaning.",
|
||||
[], true, true, true, true),
|
||||
NWO: new FactionInfo(
|
||||
"The human being does not truly desire freedom. It wants to be observed, understood, and judged. It wants to " +
|
||||
"be given purpose and direction in its life. That is why humans created God. And that is why humans created " +
|
||||
"civilization - not because of willingness, but because of a need to be incorporated into higher orders of " +
|
||||
"structure and meaning.",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
"Clarke Incorporated": new FactionInfo("Unlocking the power of the genome",
|
||||
[], true, true, true, true),
|
||||
"Clarke Incorporated": new FactionInfo(
|
||||
"Unlocking the power of the genome",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
"OmniTek Incorporated": new FactionInfo("Simply put, our mission is to design and build robots that make a difference",
|
||||
[], true, true, true, true),
|
||||
"OmniTek Incorporated": new FactionInfo(
|
||||
"Simply put, our mission is to design and build robots that make a difference",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
"Four Sigma": new FactionInfo("The scientific method is the best way to approach investing. Big strategies backed " +
|
||||
"up with big data. Driven by deep learning and innovative ideas. And improved by iteration. That's Four Sigma.",
|
||||
[], true, true, true, true),
|
||||
"Four Sigma": new FactionInfo(
|
||||
"The scientific method is the best way to approach investing. Big strategies backed up with big data. Driven " +
|
||||
"by deep learning and innovative ideas. And improved by iteration. That's Four Sigma.",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
"KuaiGong International": new FactionInfo("Dream big. Work hard. Make history.",
|
||||
[], true, true, true, true),
|
||||
"KuaiGong International": new FactionInfo(
|
||||
"Dream big. Work hard. Make history.",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
// Other Corporations
|
||||
"Fulcrum Secret Technologies": new FactionInfo("The human organism has an innate desire to worship. " +
|
||||
"That is why they created gods. If there were no gods, " +
|
||||
"it would be necessary to create them. And now we can.",
|
||||
[], true, true, false, true),
|
||||
// Other Corporations
|
||||
"Fulcrum Secret Technologies": new FactionInfo(
|
||||
"The human organism has an innate desire to worship. That is why they created gods. If there were no gods, it " +
|
||||
"would be necessary to create them. And now we can.",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true),
|
||||
|
||||
// Hacker groups
|
||||
BitRunners: new FactionInfo("Our entire lives are controlled by bits. All of our actions, our thoughts, our " +
|
||||
"personal information. It's all transformed into bits, stored in bits, communicated through bits. " +
|
||||
"It’s impossible for any person to move, to live, to operate at any level without the use of " +
|
||||
"bits. And when a person moves, lives, and operates, they leave behind their bits, mere traces of " +
|
||||
"seemingly meaningless fragments of information. But these bits can be reconstructed. " +
|
||||
"Transformed. Used.<br><br>Those who run the bits, run the world",
|
||||
[], true, true, false, false),
|
||||
// Hacker groups
|
||||
BitRunners: new FactionInfo(
|
||||
"Our entire lives are controlled by bits. All of our actions, our thoughts, our personal information. It's " +
|
||||
"all transformed into bits, stored in bits, communicated through bits. It’s impossible for any person to move, " +
|
||||
"to live, to operate at any level without the use of bits. And when a person moves, lives, and operates, they " +
|
||||
"leave behind their bits, mere traces of seemingly meaningless fragments of information. But these bits can be " +
|
||||
"reconstructed. Transformed. Used.<br>" +
|
||||
"<br>" +
|
||||
"Those who run the bits, run the world",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false),
|
||||
|
||||
"The Black Hand": new FactionInfo("The world, so afraid of strong government, now has no government. " +
|
||||
"Only power - Digital power. Financial power. Technological power. And those at the top rule with " +
|
||||
"an invisible hand. They built a society where the rich get richer, and everyone else suffers." +
|
||||
"<br><br>So much pain. So many lives. Their darkness must end.",
|
||||
[], true, true, true, false),
|
||||
"The Black Hand": new FactionInfo(
|
||||
"The world, so afraid of strong government, now has no government. Only power - Digital power. Financial " +
|
||||
"power. Technological power. And those at the top rule with an invisible hand. They built a society where the " +
|
||||
"rich get richer, and everyone else suffers.<br>" +
|
||||
"<br>" +
|
||||
"So much pain. So many lives. Their darkness must end.",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false),
|
||||
|
||||
NiteSec: new FactionInfo(
|
||||
" __..__ <br>" +
|
||||
" _.nITESECNIt. <br>" +
|
||||
" .-'NITESECNITESEc. <br>" +
|
||||
" .' NITESECNITESECn <br>" +
|
||||
" / NITESECNITESEC; <br>" +
|
||||
" : :NITESECNITESEC; <br>" +
|
||||
" ; $ NITESECNITESECN <br>" +
|
||||
" : _, ,N'ITESECNITESEC <br>" +
|
||||
" : .+^^`, : `NITESECNIT <br>" +
|
||||
" ) /), `-,-=,NITESECNI <br>" +
|
||||
" / ^ ,-;|NITESECN; <br>" +
|
||||
" / _.' '-';NITESECN <br>" +
|
||||
" ( , ,-''`^NITE' <br>" +
|
||||
" )` :`. .' <br>" +
|
||||
" )-- ; `- / <br>" +
|
||||
" \' _.-' : <br>" +
|
||||
" ( _.-' \. \ <br>" +
|
||||
" \------. \ \ <br>" +
|
||||
" \. \ \ <br>" +
|
||||
" \ _.nIt <br>" +
|
||||
" \ _.nITESECNi <br>" +
|
||||
" nITESECNIT^' \ <br>" +
|
||||
" NITE^' ___ \ <br>" +
|
||||
" / .gP''''Tp. \ <br>" +
|
||||
" : d' . `b \ <br>" +
|
||||
" ; d' o `b ; <br>" +
|
||||
" / d; `b| <br>" +
|
||||
" /, $; @ `: <br>" +
|
||||
" /' $$ ; <br>" +
|
||||
" .' $$b o | <br>" +
|
||||
" .' d$$$; : <br>" +
|
||||
" / .d$$$$; , ; <br>" +
|
||||
" d .dNITESEC $ | <br>" +
|
||||
" :bp.__.gNITESEC$$ :$ ; <br>" +
|
||||
" NITESECNITESECNIT $$b : <br>",
|
||||
[], true, true, false, false),
|
||||
NiteSec: new FactionInfo(
|
||||
" __..__ <br>" +
|
||||
" _.nITESECNIt. <br>" +
|
||||
" .-'NITESECNITESEc. <br>" +
|
||||
" .' NITESECNITESECn <br>" +
|
||||
" / NITESECNITESEC; <br>" +
|
||||
" : :NITESECNITESEC; <br>" +
|
||||
" ; $ NITESECNITESECN <br>" +
|
||||
" : _, ,N'ITESECNITESEC <br>" +
|
||||
" : .+^^`, : `NITESECNIT <br>" +
|
||||
" ) /), `-,-=,NITESECNI <br>" +
|
||||
" / ^ ,-;|NITESECN; <br>" +
|
||||
" / _.' '-';NITESECN <br>" +
|
||||
" ( , ,-''`^NITE' <br>" +
|
||||
" )` :`. .' <br>" +
|
||||
" )-- ; `- / <br>" +
|
||||
" \' _.-' : <br>" +
|
||||
" ( _.-' \. \ <br>" +
|
||||
" \------. \ \ <br>" +
|
||||
" \. \ \ <br>" +
|
||||
" \ _.nIt <br>" +
|
||||
" \ _.nITESECNi <br>" +
|
||||
" nITESECNIT^' \ <br>" +
|
||||
" NITE^' ___ \ <br>" +
|
||||
" / .gP''''Tp. \ <br>" +
|
||||
" : d' . `b \ <br>" +
|
||||
" ; d' o `b ; <br>" +
|
||||
" / d; `b| <br>" +
|
||||
" /, $; @ `: <br>" +
|
||||
" /' $$ ; <br>" +
|
||||
" .' $$b o | <br>" +
|
||||
" .' d$$$; : <br>" +
|
||||
" / .d$$$$; , ; <br>" +
|
||||
" d .dNITESEC $ | <br>" +
|
||||
" :bp.__.gNITESEC$$ :$ ; <br>" +
|
||||
" NITESECNITESECNIT $$b : <br>",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false),
|
||||
|
||||
// City factions, essentially governments
|
||||
Aevum: new FactionInfo("The Silicon City",
|
||||
["Chongqing", "New Tokyo", "Ishima", "Volhaven"], true, true, true, true),
|
||||
Chongqing: new FactionInfo("Serve the people",
|
||||
["Sector-12", "Aevum", "Volhaven"], true, true, true, true),
|
||||
Ishima: new FactionInfo("The East Asian Order of the Future",
|
||||
["Sector-12", "Aevum", "Volhaven"], true, true, true, true),
|
||||
"New Tokyo": new FactionInfo("Asia's World City",
|
||||
["Sector-12", "Aevum", "Volhaven"], true, true, true, true),
|
||||
"Sector-12": new FactionInfo("The City of the Future",
|
||||
["Chongqing", "New Tokyo", "Ishima", "Volhaven"], true, true, true, true),
|
||||
Volhaven: new FactionInfo("Benefit, Honour, and Glory",
|
||||
["Chongqing", "Sector-12", "New Tokyo", "Aevum", "Ishima"], true, true, true, true),
|
||||
// City factions, essentially governments
|
||||
Aevum: new FactionInfo(
|
||||
"The Silicon City",
|
||||
[
|
||||
"Chongqing",
|
||||
"New Tokyo",
|
||||
"Ishima",
|
||||
"Volhaven",
|
||||
],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
Chongqing: new FactionInfo(
|
||||
"Serve the people",
|
||||
[
|
||||
"Sector-12",
|
||||
"Aevum",
|
||||
"Volhaven",
|
||||
],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
Ishima: new FactionInfo(
|
||||
"The East Asian Order of the Future",
|
||||
[
|
||||
"Sector-12",
|
||||
"Aevum",
|
||||
"Volhaven",
|
||||
],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
"New Tokyo": new FactionInfo(
|
||||
"Asia's World City",
|
||||
[
|
||||
"Sector-12",
|
||||
"Aevum",
|
||||
"Volhaven",
|
||||
],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
"Sector-12": new FactionInfo(
|
||||
"The City of the Future",
|
||||
[
|
||||
"Chongqing",
|
||||
"New Tokyo",
|
||||
"Ishima",
|
||||
"Volhaven",
|
||||
],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
Volhaven: new FactionInfo(
|
||||
"Benefit, Honour, and Glory",
|
||||
[
|
||||
"Chongqing",
|
||||
"Sector-12",
|
||||
"New Tokyo",
|
||||
"Aevum",
|
||||
"Ishima",
|
||||
],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
// Criminal Organizations/Gangs
|
||||
"Speakers for the Dead": new FactionInfo("It is better to reign in hell than to serve in heaven.",
|
||||
[], true, true, true, true),
|
||||
// Criminal Organizations/Gangs
|
||||
"Speakers for the Dead": new FactionInfo(
|
||||
"It is better to reign in hell than to serve in heaven.",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
"The Dark Army": new FactionInfo("The World doesn't care about right or wrong. It's all about power.",
|
||||
[], true, true, true, false),
|
||||
"The Dark Army": new FactionInfo(
|
||||
"The World doesn't care about right or wrong. It's all about power.",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false),
|
||||
|
||||
"The Syndicate": new FactionInfo("Honor holds you back", [], true, true, true, true),
|
||||
"The Syndicate": new FactionInfo(
|
||||
"Honor holds you back",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
Silhouette: new FactionInfo("Corporations have filled the void of power left behind by the collapse of Western " +
|
||||
"government. The issue is they've become so big that you don't know who they're working for. And " +
|
||||
"if you're employed at one of these corporations, you don't even know who you're working for.\n\n" +
|
||||
"That's terror. Terror, fear, and corruption. All born into the system, all propagated by the " +
|
||||
"system.",
|
||||
[], true, true, true, false),
|
||||
Silhouette: new FactionInfo(
|
||||
"Corporations have filled the void of power left behind by the collapse of Western government. The issue is " +
|
||||
"they've become so big that you don't know who they're working for. And if you're employed at one of these " +
|
||||
"corporations, you don't even know who you're working for.<br>" +
|
||||
"<br>" +
|
||||
"That's terror. Terror, fear, and corruption. All born into the system, all propagated by the system.",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false),
|
||||
|
||||
Tetrads: new FactionInfo("Following the Mandate of Heaven and Carrying out the Way", [], false, false, true, true),
|
||||
Tetrads: new FactionInfo(
|
||||
"Following the Mandate of Heaven and Carrying out the Way",
|
||||
[],
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true),
|
||||
|
||||
"Slum Snakes": new FactionInfo("Slum Snakes rule!", [], false, false, true, true),
|
||||
"Slum Snakes": new FactionInfo(
|
||||
"Slum Snakes rule!",
|
||||
[],
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true),
|
||||
|
||||
// Earlygame factions - factions the player will prestige with early on that don't belong in other categories.
|
||||
Netburners: new FactionInfo("~~//*>H4CK|\|3T 8URN3R5**>?>\\~~", [], true, true, false, false),
|
||||
// Earlygame factions - factions the player will prestige with early on that don't belong in other categories.
|
||||
Netburners: new FactionInfo(
|
||||
"~~//*>H4CK|\|3T 8URN3R5**>?>\\~~",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false),
|
||||
|
||||
"Tian Di Hui": new FactionInfo("Obey Heaven and Work Righteousness", [], true, true, false, true),
|
||||
"Tian Di Hui": new FactionInfo(
|
||||
"Obey Heaven and Work Righteousness",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true),
|
||||
|
||||
CyberSec: new FactionInfo("The Internet is the first thing that humanity has built that humanity doesn’t " +
|
||||
"understand, the largest experiment in anarchy that we have ever had. And as the world becomes " +
|
||||
"increasingly dominated by the internet, society approaches the brink of total chaos. We serve only " +
|
||||
"to protect society, to protect humanity, to protect the world from its imminent collapse.",
|
||||
[], true, true, false, false),
|
||||
CyberSec: new FactionInfo(
|
||||
"The Internet is the first thing that humanity has built that humanity doesn’t understand, the largest " +
|
||||
"experiment in anarchy that we have ever had. And as the world becomes increasingly dominated by the internet, " +
|
||||
"society approaches the brink of total chaos. We serve only to protect society, to protect humanity, to " +
|
||||
"protect the world from its imminent collapse.",
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false),
|
||||
|
||||
// Special Factions
|
||||
Bladeburners: new FactionInfo("It's too bad they won't live. But then again, who does?<br><br>Note that for this " +
|
||||
"faction, reputation can only be gained through Bladeburner actions. Completing " +
|
||||
"Bladeburner contracts/operations will increase your reputation.",
|
||||
[], false, false, false, false),
|
||||
// Special Factions
|
||||
Bladeburners: new FactionInfo(
|
||||
"It's too bad they won't live. But then again, who does?<br><br>Note that for this faction, reputation can " +
|
||||
"only be gained through Bladeburner actions. Completing Bladeburner contracts/operations will increase your " +
|
||||
"reputation.",
|
||||
[],
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false),
|
||||
};
|
||||
|
@ -9,6 +9,7 @@ import {Reviver, Generic_toJSON,
|
||||
import {createAccordionElement} from "../utils/uiHelpers/createAccordionElement";
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {createPopup} from "../utils/uiHelpers/createPopup";
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
import numeral from "numeral/min/numeral.min";
|
||||
import {formatNumber} from "../utils/StringHelperFunctions";
|
||||
import {getRandomInt} from "../utils/helpers/getRandomInt";
|
||||
@ -24,7 +25,7 @@ import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
|
||||
/* Gang.js */
|
||||
//Switch between territory and management screen with 1 and 2
|
||||
$(document).keydown(function(event) {
|
||||
if (Engine.currentPage == Engine.Page.Gang && !yesNoBoxOpen) {
|
||||
if (routing.isOn(Page.Gang) && !yesNoBoxOpen) {
|
||||
if (gangMemberFilter != null && gangMemberFilter === document.activeElement) {return;}
|
||||
if (event.keyCode === 49) {
|
||||
if(gangTerritorySubpage.style.display === "block") {
|
||||
|
@ -1,14 +1,15 @@
|
||||
import {BitNodeMultipliers} from "./BitNode";
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Engine} from "./engine";
|
||||
import {iTutorialSteps, iTutorialNextStep,
|
||||
iTutorialIsRunning, currITutorialStep} from "./InteractiveTutorial";
|
||||
ITutorial} from "./InteractiveTutorial";
|
||||
import {Player} from "./Player";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";
|
||||
import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver";
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
import {formatNumber} from "../utils/StringHelperFunctions";
|
||||
import {getElementById} from "../utils/uiHelpers/getElementById";
|
||||
|
||||
@ -244,8 +245,8 @@ Reviver.constructors.HacknetNode = HacknetNode;
|
||||
|
||||
function purchaseHacknet() {
|
||||
/* INTERACTIVE TUTORIAL */
|
||||
if (iTutorialIsRunning) {
|
||||
if (currITutorialStep == iTutorialSteps.HacknetNodesIntroduction) {
|
||||
if (ITutorial.isRunning) {
|
||||
if (ITutorial.currStep === iTutorialSteps.HacknetNodesIntroduction) {
|
||||
iTutorialNextStep();
|
||||
} else {
|
||||
return;
|
||||
@ -273,7 +274,7 @@ function purchaseHacknet() {
|
||||
Player.loseMoney(cost);
|
||||
Player.hacknetNodes.push(node);
|
||||
|
||||
if (Engine.currentPage === Engine.Page.HacknetNodes) {
|
||||
if (routing.isOn(Page.HacknetNodes)) {
|
||||
displayHacknetNodesContent();
|
||||
}
|
||||
updateTotalHacknetProduction();
|
||||
@ -445,7 +446,7 @@ function updateHacknetNodesContent() {
|
||||
|
||||
//Update player's money
|
||||
updateText("hacknet-nodes-player-money", "$" + formatNumber(Player.money.toNumber(), 2));
|
||||
updateText("hacknet-nodes-total-production", "$" + formatNumber(Player.totalHacknetNodeProduction, 2) + " / second");
|
||||
updateText("hacknet-nodes-total-production", "$" + formatNumber(Player.totalHacknetNodeProduction, 2) + " / sec");
|
||||
|
||||
//Update information in each owned hacknet node
|
||||
for (var i = 0; i < Player.hacknetNodes.length; ++i) {
|
||||
@ -547,7 +548,7 @@ function updateHacknetNodeDomElement(nodeObj) {
|
||||
|
||||
updateText("hacknet-node-name-" + nodeName, nodeName);
|
||||
updateText("hacknet-node-total-production-" + nodeName, "$" + formatNumber(nodeObj.totalMoneyGenerated, 2));
|
||||
updateText("hacknet-node-production-rate-" + nodeName, "($" + formatNumber(nodeObj.moneyGainRatePerSecond, 2) + " / second)");
|
||||
updateText("hacknet-node-production-rate-" + nodeName, "($" + formatNumber(nodeObj.moneyGainRatePerSecond, 2) + " / sec)");
|
||||
updateText("hacknet-node-level-" + nodeName, nodeObj.level);
|
||||
updateText("hacknet-node-ram-" + nodeName, nodeObj.ram + "GB");
|
||||
updateText("hacknet-node-cores-" + nodeName, nodeObj.cores);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {BitNodeMultipliers} from "./BitNode";
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Engine} from "./engine";
|
||||
import {Player} from "./Player";
|
||||
|
@ -1,55 +1,77 @@
|
||||
import {Engine} from "./engine";
|
||||
import {Player} from "./Player";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {Settings} from "./Settings";
|
||||
import {Terminal} from "./Terminal";
|
||||
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {createPopup} from "../utils/uiHelpers/createPopup";
|
||||
import {removeElementById} from "../utils/uiHelpers/removeElementById";
|
||||
|
||||
/* InteractiveTutorial.js */
|
||||
let iTutorialSteps = {
|
||||
Start: "Start",
|
||||
GoToCharacterPage: "Click on the Character page menu link",
|
||||
CharacterPage: "Introduction to Character page",
|
||||
CharacterGoToTerminalPage: "Click on the Terminal link",
|
||||
TerminalIntro: "Introduction to terminal interface",
|
||||
TerminalHelp: "Using the help command to display all options in terminal",
|
||||
TerminalLs: "Use the ls command to show all programs/scripts. Right now we have NUKE.exe",
|
||||
TerminalScan: "Using the scan command to display all available connections",
|
||||
TerminalScanAnalyze1: "Use the scan-analyze command to show hacking related information",
|
||||
TerminalScanAnalyze2: "Use the scan-analyze command with a depth of 3",
|
||||
TerminalConnect: "Using the telnet/connect command to connect to another server",
|
||||
TerminalAnalyze: "Use the analyze command to display details about this server",
|
||||
TerminalNuke: "Use the NUKE Program to gain root access to a server",
|
||||
TerminalManualHack: "Use the hack command to manually hack a server",
|
||||
TerminalHackingMechanics: "Briefly explain hacking mechanics",
|
||||
TerminalCreateScript: "Create a script using nano",
|
||||
TerminalTypeScript: "This occurs in the Script Editor page...type the script then save and close",
|
||||
TerminalFree: "Use the free command to check RAM",
|
||||
TerminalRunScript: "Use the run command to run a script",
|
||||
TerminalGoToActiveScriptsPage: "Go to the ActiveScriptsPage",
|
||||
ActiveScriptsPage: "Introduction to the Active Scripts Page",
|
||||
ActiveScriptsToTerminal: "Go from Active Scripts Page Back to Terminal",
|
||||
TerminalTailScript: "Use the tail command to show a script's logs",
|
||||
GoToHacknetNodesPage: "Go to the Hacknet Nodes page",
|
||||
HacknetNodesIntroduction: "Introduction to Hacknet Nodesm and have user purchase one",
|
||||
HacknetNodesGoToWorldPage: "Go to the world page",
|
||||
WorldDescription: "Tell the user to explore..theres a lot of different stuff to do out there",
|
||||
TutorialPageInfo: "The tutorial page contains a lot of info on different subjects",
|
||||
End: "End",
|
||||
//Ordered array of keys to Interactive Tutorial Steps
|
||||
const orderedITutorialSteps = [
|
||||
"Start",
|
||||
"GoToCharacterPage", //Click on 'Stats' page
|
||||
"CharacterPage", //Introduction to 'Stats' page
|
||||
"CharacterGoToTerminalPage", //Go back to Terminal
|
||||
"TerminalIntro", //Introduction to Terminal
|
||||
"TerminalHelp", //Using 'help' Terminal command
|
||||
"TerminalLs", //Using 'ls' Terminal command
|
||||
"TerminalScan", //Using 'scan' Terminal command
|
||||
"TerminalScanAnalyze1", //Using 'scan-analyze' Terminal command
|
||||
"TerminalScanAnalyze2", //Using 'scan-analyze 3' Terminal command
|
||||
"TerminalConnect", //Connecting to foodnstuff
|
||||
"TerminalAnalyze", //Analyzing foodnstuff
|
||||
"TerminalNuke", //NUKE foodnstuff
|
||||
"TerminalManualHack", //Hack foodnstuff
|
||||
"TerminalHackingMechanics", //Explanation of hacking mechanics
|
||||
"TerminalCreateScript", //Create a script using 'nano'
|
||||
"TerminalTypeScript", //Script Editor page - Type script and then save & close
|
||||
"TerminalFree", //Using 'Free' Terminal command
|
||||
"TerminalRunScript", //Running script using 'run' Terminal command
|
||||
"TerminalGoToActiveScriptsPage",
|
||||
"ActiveScriptsPage",
|
||||
"ActiveScriptsToTerminal",
|
||||
"TerminalTailScript",
|
||||
"GoToHacknetNodesPage",
|
||||
"HacknetNodesIntroduction",
|
||||
"HacknetNodesGoToWorldPage",
|
||||
"WorldDescription",
|
||||
"TutorialPageInfo",
|
||||
"End"
|
||||
]
|
||||
|
||||
//Create an 'enum' for the Steps
|
||||
const iTutorialSteps = {};
|
||||
for (let i = 0; i < orderedITutorialSteps.length; ++i) {
|
||||
iTutorialSteps[orderedITutorialSteps[i]] = i;
|
||||
}
|
||||
|
||||
var currITutorialStep = iTutorialSteps.Start;
|
||||
var iTutorialIsRunning = false;
|
||||
var ITutorial = {
|
||||
currStep: 0, //iTutorialSteps.Start
|
||||
isRunning: false,
|
||||
|
||||
//Keeps track of whether each step has been done
|
||||
stepIsDone: {},
|
||||
}
|
||||
|
||||
function iTutorialStart() {
|
||||
//Initialize Interactive Tutorial state by settings 'done' for each state to false
|
||||
ITutorial.stepIsDone = {};
|
||||
for (let i = 0; i < orderedITutorialSteps.length; ++i) {
|
||||
ITutorial.stepIsDone[i] = false;
|
||||
}
|
||||
|
||||
Engine.loadTerminalContent();
|
||||
Terminal.resetTerminalInput();
|
||||
|
||||
//Don't autosave during this interactive tutorial
|
||||
Engine.Counters.autoSaveCounter = 999000000000;
|
||||
Engine.Counters.autoSaveCounter = Infinity;
|
||||
console.log("Interactive Tutorial started");
|
||||
currITutorialStep = iTutorialSteps.Start;
|
||||
iTutorialIsRunning = true;
|
||||
ITutorial.currStep = 0;
|
||||
ITutorial.isRunning = true;
|
||||
|
||||
document.getElementById("interactive-tutorial-container").style.display = "block";
|
||||
|
||||
iTutorialEvaluateStep();
|
||||
|
||||
//Exit tutorial button
|
||||
var exitButton = clearEventListeners("interactive-tutorial-exit");
|
||||
exitButton.addEventListener("click", function() {
|
||||
@ -59,142 +81,150 @@ function iTutorialStart() {
|
||||
|
||||
//Back button
|
||||
var backButton = clearEventListeners("interactive-tutorial-back");
|
||||
backButton.style.display = "none";
|
||||
backButton.addEventListener("click", function() {
|
||||
iTutorialPrevStep();
|
||||
return false;
|
||||
});
|
||||
|
||||
//Next button
|
||||
var nextButton = clearEventListeners("interactive-tutorial-next");
|
||||
nextButton.addEventListener("click", function() {
|
||||
iTutorialNextStep();
|
||||
return false;
|
||||
});
|
||||
|
||||
iTutorialEvaluateStep();
|
||||
}
|
||||
|
||||
function iTutorialEvaluateStep() {
|
||||
if (!iTutorialIsRunning) {console.log("Interactive Tutorial not running"); return;}
|
||||
switch(currITutorialStep) {
|
||||
if (!ITutorial.isRunning) {console.log("Interactive Tutorial not running"); return;}
|
||||
|
||||
//Disable and clear main menu
|
||||
var terminalMainMenu = clearEventListeners("terminal-menu-link");
|
||||
var statsMainMenu = clearEventListeners("stats-menu-link");
|
||||
var activeScriptsMainMenu = clearEventListeners("active-scripts-menu-link");
|
||||
var hacknetMainMenu = clearEventListeners("hacknet-nodes-menu-link");
|
||||
var cityMainMenu = clearEventListeners("city-menu-link");
|
||||
var tutorialMainMenu = clearEventListeners("tutorial-menu-link");
|
||||
terminalMainMenu.removeAttribute("class");
|
||||
statsMainMenu.removeAttribute("class");
|
||||
activeScriptsMainMenu.removeAttribute("class");
|
||||
hacknetMainMenu.removeAttribute("class");
|
||||
cityMainMenu.removeAttribute("class");
|
||||
tutorialMainMenu.removeAttribute("class");
|
||||
|
||||
//Interactive Tutorial Next button
|
||||
var nextBtn = document.getElementById("interactive-tutorial-next");
|
||||
|
||||
switch(ITutorial.currStep) {
|
||||
case iTutorialSteps.Start:
|
||||
Engine.loadTerminalContent();
|
||||
|
||||
iTutorialSetText("Welcome to Bitburner, a cyberpunk-themed incremental RPG! " +
|
||||
"The game takes place in a dark, dystopian future...The year is 2077...<br><br>" +
|
||||
"This tutorial will show you the basics of the game. " +
|
||||
"You may skip the tutorial at any time.");
|
||||
var next = clearEventListeners("interactive-tutorial-next");
|
||||
next.style.display = "inline-block";
|
||||
next.addEventListener("click", function() {
|
||||
iTutorialNextStep();
|
||||
return false;
|
||||
});
|
||||
nextBtn.style.display = "inline-block";
|
||||
break;
|
||||
case iTutorialSteps.GoToCharacterPage:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("Let's start by heading to the Stats page. Click the 'Stats' tab on " +
|
||||
"the main navigation menu (left-hand side of the screen)");
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
//No next button
|
||||
var next = clearEventListeners("interactive-tutorial-next");
|
||||
next.style.display = "none";
|
||||
|
||||
//Flash Character tab
|
||||
document.getElementById("stats-menu-link").setAttribute("class", "flashing-button");
|
||||
|
||||
//Initialize everything necessary to open the "Character" page
|
||||
var charaterMainMenuButton = document.getElementById("stats-menu-link");
|
||||
charaterMainMenuButton.addEventListener("click", function() {
|
||||
//Flash 'Stats' menu and set its tutorial click handler
|
||||
statsMainMenu.setAttribute("class", "flashing-button");
|
||||
statsMainMenu.addEventListener("click", function() {
|
||||
Engine.loadCharacterContent();
|
||||
iTutorialNextStep(); //Opening the character page will go to the next step
|
||||
clearEventListeners("stats-menu-link");
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case iTutorialSteps.CharacterPage:
|
||||
Engine.loadCharacterContent();
|
||||
iTutorialSetText("The Stats page shows a lot of important information about your progress, " +
|
||||
"such as your skills, money, and bonuses/multipliers. ")
|
||||
var next = clearEventListeners("interactive-tutorial-next");
|
||||
next.style.display = "inline-block";
|
||||
next.addEventListener("click", function() {
|
||||
iTutorialNextStep();
|
||||
return false;
|
||||
});
|
||||
nextBtn.style.display = "inline-block";
|
||||
break;
|
||||
case iTutorialSteps.CharacterGoToTerminalPage:
|
||||
Engine.loadCharacterContent();
|
||||
iTutorialSetText("Let's head to your computer's terminal by clicking the 'Terminal' tab on the " +
|
||||
"main navigation menu.");
|
||||
//No next button
|
||||
var next = clearEventListeners("interactive-tutorial-next");
|
||||
next.style.display = "none";
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
document.getElementById("terminal-menu-link").setAttribute("class", "flashing-button");
|
||||
|
||||
//Initialize everything necessary to open the 'Terminal' Page
|
||||
var terminalMainMenuButton = document.getElementById("terminal-menu-link");
|
||||
terminalMainMenuButton.addEventListener("click", function() {
|
||||
//Flash 'Terminal' menu and set its tutorial click handler
|
||||
terminalMainMenu.setAttribute("class", "flashing-button");
|
||||
terminalMainMenu.addEventListener("click", function() {
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialNextStep();
|
||||
clearEventListeners("terminal-menu-link");
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case iTutorialSteps.TerminalIntro:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("The Terminal is used to interface with your home computer as well as " +
|
||||
"all of the other machines around the world.");
|
||||
var next = clearEventListeners("interactive-tutorial-next");
|
||||
next.style.display = "inline-block";
|
||||
next.addEventListener("click", function() {
|
||||
iTutorialNextStep();
|
||||
return false;
|
||||
});
|
||||
nextBtn.style.display = "inline-block";
|
||||
break;
|
||||
case iTutorialSteps.TerminalHelp:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("Let's try it out. Start by entering the 'help' command into the Terminal " +
|
||||
"(Don't forget to press Enter after typing the command)");
|
||||
var next = clearEventListeners("interactive-tutorial-next");
|
||||
next.style.display = "none";
|
||||
//next step triggered by terminal command
|
||||
nextBtn.style.display = "none"; //next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalLs:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("The 'help' command displays a list of all available Terminal commands, how to use them, " +
|
||||
"and a description of what they do. <br><br>Let's try another command. Enter the 'ls' command");
|
||||
//next step triggered by terminal command
|
||||
nextBtn.style.display = "none"; //next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalScan:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("'ls' is a basic command that shows all of the contents (programs/scripts) " +
|
||||
"on the computer. Right now, it shows that you have a program called 'NUKE.exe' on your computer. " +
|
||||
"We'll get to what this does later. <br><br>Using your home computer's terminal, you can connect " +
|
||||
"to other machines throughout the world. Let's do that now by first entering " +
|
||||
"the 'scan' command. ");
|
||||
//next step triggered by terminal command
|
||||
"the 'scan' command.");
|
||||
nextBtn.style.display = "none"; //next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalScanAnalyze1:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("The 'scan' command shows all available network connections. In other words, " +
|
||||
"it displays a list of all servers that can be connected to from your " +
|
||||
"current machine. A server is identified by either its IP or its hostname. <br><br> " +
|
||||
"That's great and all, but there's so many servers. Which one should you go to? " +
|
||||
"The 'scan-analyze' command gives some more detailed information about servers on the " +
|
||||
"network. Try it now");
|
||||
//next step triggered by terminal command
|
||||
nextBtn.style.display = "none"; //next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalScanAnalyze2:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("You just ran 'scan-analyze' with a depth of one. This command shows more detailed " +
|
||||
"information about each server that you can connect to (servers that are a distance of " +
|
||||
"one node away). <br><br> It is also possible to run 'scan-analyze' with " +
|
||||
"a higher depth. Let's try a depth of two with the following command: 'scan-analyze 2'.")
|
||||
//next step triggered by terminal command
|
||||
nextBtn.style.display = "none"; //next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalConnect:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("Now you can see information about all servers that are up to two nodes away, as well " +
|
||||
"as figure out how to navigate to those servers through the network. You can only connect to " +
|
||||
"a server that is one node away. To connect to a machine, use the 'connect [ip/hostname]' command. You can type in " +
|
||||
"the ip or the hostname, but dont use both.<br><br>" +
|
||||
"From the results of the 'scan-analyze' command, we can see that the 'foodnstuff' server is " +
|
||||
"only one node away. Let's connect so it now using: 'connect foodnstuff'");
|
||||
//next step triggered by terminal command
|
||||
nextBtn.style.display = "none"; //next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalAnalyze:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("You are now connected to another machine! What can you do now? You can hack it!<br><br> In the year 2077, currency has " +
|
||||
"become digital and decentralized. People and corporations store their money " +
|
||||
"on servers and computers. Using your hacking abilities, you can hack servers " +
|
||||
"to steal money and gain experience. <br><br> " +
|
||||
"Before you try to hack a server, you should run diagnostics using the 'analyze' command");
|
||||
//next step triggered by terminal command
|
||||
nextBtn.style.display = "none"; //next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalNuke:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("When the 'analyze' command finishes running it will show useful information " +
|
||||
"about hacking the server. <br><br> For this server, the required hacking skill is only 1, " +
|
||||
"which means you can hack it right now. However, in order to hack a server " +
|
||||
@ -203,14 +233,16 @@ function iTutorialEvaluateStep() {
|
||||
"open ports.<br><br> The 'analyze' results shows that there do not need to be any open ports " +
|
||||
"on this machine for the NUKE virus to work, so go ahead and run the virus using the " +
|
||||
"'run NUKE.exe' command.");
|
||||
//next step triggered by terminal command
|
||||
nextBtn.style.display = "none"; //next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalManualHack:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("You now have root access! You can hack the server using the 'hack' command. " +
|
||||
"Try doing that now.");
|
||||
//next step triggered by terminal command
|
||||
nextBtn.style.display = "none"; //next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalHackingMechanics:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("You are now attempting to hack the server. Note that performing a hack takes time and " +
|
||||
"only has a certain percentage chance " +
|
||||
"of success. This time and success chance is determined by a variety of factors, including " +
|
||||
@ -220,25 +252,20 @@ function iTutorialEvaluateStep() {
|
||||
"the server's security level.<br><br>The amount of money on a server is not limitless. So, if " +
|
||||
"you constantly hack a server and deplete its money, then you will encounter " +
|
||||
"diminishing returns in your hacking.");
|
||||
var next = clearEventListeners("interactive-tutorial-next");
|
||||
next.style.display = "inline-block";
|
||||
next.addEventListener("click", function() {
|
||||
iTutorialNextStep();
|
||||
return false;
|
||||
});
|
||||
nextBtn.style.display = "inline-block";
|
||||
break;
|
||||
case iTutorialSteps.TerminalCreateScript:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("Hacking is the core mechanic of the game and is necessary for progressing. However, " +
|
||||
"you don't want to be hacking manually the entire time. You can automate your hacking " +
|
||||
"by writing scripts!<br><br>To create a new script or edit an existing one, you can use the 'nano' " +
|
||||
"command. Scripts must end with the '.script' extension. Let's make a script now by " +
|
||||
"entering 'nano foodnstuff.script' after the hack command finishes running (Sidenote: Pressing ctrl + c" +
|
||||
" will end a command like hack early)");
|
||||
var next = clearEventListeners("interactive-tutorial-next");
|
||||
next.style.display = "none";
|
||||
//next step triggered by terminal command
|
||||
nextBtn.style.display = "none"; //next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalTypeScript:
|
||||
Engine.loadScriptEditorContent("foodnstuff.script", "");
|
||||
iTutorialSetText("This is the script editor. You can use it to program your scripts. Scripts are " +
|
||||
"written in the Netscript language, a programming language created for " +
|
||||
"this game. <strong style='background-color:#444;'>There are details about the Netscript language in the documentation, which " +
|
||||
@ -251,21 +278,24 @@ function iTutorialEvaluateStep() {
|
||||
"For anyone with basic programming experience, this code should be straightforward. " +
|
||||
"This script will continuously hack the 'foodnstuff' server.<br><br>" +
|
||||
"To save and close the script editor, press the button in the bottom left, or press ctrl + b.");
|
||||
//next step triggered in saveAndCloseScriptEditor() (Script.js)
|
||||
nextBtn.style.display = "none"; //next step triggered in saveAndCloseScriptEditor() (Script.js)
|
||||
break;
|
||||
case iTutorialSteps.TerminalFree:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("Now we'll run the script. Scripts require a certain amount of RAM to run, and can be " +
|
||||
"run on any machine which you have root access to. Different servers have different " +
|
||||
"amounts of RAM. You can also purchase more RAM for your home server.<br><br>To check how much " +
|
||||
"RAM is available on this machine, enter the 'free' command.");
|
||||
//next step triggered by terminal commmand
|
||||
nextBtn.style.display = "none"; //next step triggered by terminal commmand
|
||||
break;
|
||||
case iTutorialSteps.TerminalRunScript:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("We have 16GB of free RAM on this machine, which is enough to run our " +
|
||||
"script. Let's run our script using 'run foodnstuff.script'.");
|
||||
//next step triggered by terminal commmand
|
||||
nextBtn.style.display = "none"; //next step triggered by terminal commmand
|
||||
break;
|
||||
case iTutorialSteps.TerminalGoToActiveScriptsPage:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("Your script is now running! The script might take a few seconds to 'fully start up'. " +
|
||||
"Your scripts will continuously run in the background and will automatically stop if " +
|
||||
"the code ever completes (the 'foodnstuff.script' will never complete because it " +
|
||||
@ -274,117 +304,114 @@ function iTutorialEvaluateStep() {
|
||||
"much slower rate. <br><br> " +
|
||||
"Let's check out some statistics for our running scripts by clicking the " +
|
||||
"'Active Scripts' link in the main navigation menu.");
|
||||
document.getElementById("active-scripts-menu-link").setAttribute("class", "flashing-button");
|
||||
var activeScriptsMainMenuButton = document.getElementById("active-scripts-menu-link");
|
||||
activeScriptsMainMenuButton.addEventListener("click", function() {
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
//Flash 'Active Scripts' menu and set its tutorial click handler
|
||||
activeScriptsMainMenu.setAttribute("class", "flashing-button");
|
||||
activeScriptsMainMenu.addEventListener("click", function() {
|
||||
Engine.loadActiveScriptsContent();
|
||||
iTutorialNextStep();
|
||||
clearEventListeners("active-scripts-menu-link");
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case iTutorialSteps.ActiveScriptsPage:
|
||||
Engine.loadActiveScriptsContent();
|
||||
iTutorialSetText("This page displays stats/information about all of your scripts that are " +
|
||||
"running across every existing server. You can use this to gauge how well " +
|
||||
"your scripts are doing. Let's go back to the Terminal now using the 'Terminal'" +
|
||||
"link.");
|
||||
document.getElementById("terminal-menu-link").setAttribute("class", "flashing-button");
|
||||
//Initialize everything necessary to open the 'Terminal' Page
|
||||
var terminalMainMenuButton = clearEventListeners("terminal-menu-link");
|
||||
terminalMainMenuButton.addEventListener("click", function() {
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
//Flash 'Terminal' button and set its tutorial click handler
|
||||
terminalMainMenu.setAttribute("class", "flashing-button");
|
||||
terminalMainMenu.addEventListener("click", function() {
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialNextStep();
|
||||
clearEventListeners("terminal-menu-link");
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case iTutorialSteps.ActiveScriptsToTerminal:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("One last thing about scripts, each active script contains logs that detail " +
|
||||
"what it's doing. We can check these logs using the 'tail' command. Do that " +
|
||||
"now for the script we just ran by typing 'tail foodnstuff.script'");
|
||||
//next step triggered by terminal command
|
||||
nextBtn.style.display = "none"; //next step triggered by terminal command
|
||||
break;
|
||||
case iTutorialSteps.TerminalTailScript:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("The log for this script won't show much right now (it might show nothing at all) because it " +
|
||||
"just started running...but check back again in a few minutes! <br><br>" +
|
||||
"This pretty much covers the basics of hacking. To learn more about writing " +
|
||||
"scripts using the Netscript language, select the 'Tutorial' link in the " +
|
||||
"main navigation menu to look at the documentation. For now, let's move on " +
|
||||
"to something else!");
|
||||
var next = clearEventListeners("interactive-tutorial-next");
|
||||
next.style.display = "inline-block";
|
||||
next.addEventListener("click", function() {
|
||||
iTutorialNextStep();
|
||||
return false;
|
||||
});
|
||||
"main navigation menu to look at the documentation. " +
|
||||
"<strong style='background-color:#444;'>If you are an experienced JavaScript " +
|
||||
"developer, I would highly suggest you check out the section on " +
|
||||
"NetscriptJS/Netscript 2.0.</strong><br><br>For now, let's move on to something else!");
|
||||
nextBtn.style.display = "inline-block";
|
||||
break;
|
||||
case iTutorialSteps.GoToHacknetNodesPage:
|
||||
Engine.loadTerminalContent();
|
||||
iTutorialSetText("Hacking is not the only way to earn money. One other way to passively " +
|
||||
"earn money is by purchasing and upgrading Hacknet Nodes. Let's go to " +
|
||||
"the 'Hacknet Nodes' page through the main navigation menu now.");
|
||||
document.getElementById("hacknet-nodes-menu-link").setAttribute("class", "flashing-button");
|
||||
var hacknetNodesButton = clearEventListeners("hacknet-nodes-menu-link");
|
||||
var next = clearEventListeners("interactive-tutorial-next");
|
||||
next.style.display = "none";
|
||||
hacknetNodesButton.addEventListener("click", function() {
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
//Flash 'Hacknet' menu and set its tutorial click handler
|
||||
hacknetMainMenu.setAttribute("class", "flashing-button");
|
||||
hacknetMainMenu.addEventListener("click", function() {
|
||||
Engine.loadHacknetNodesContent();
|
||||
iTutorialNextStep();
|
||||
clearEventListeners("hacknet-nodes-menu-link");
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case iTutorialSteps.HacknetNodesIntroduction:
|
||||
Engine.loadHacknetNodesContent();
|
||||
iTutorialSetText("From this page you can purchase new Hacknet Nodes and upgrade your " +
|
||||
"existing ones. Let's purchase a new one now.");
|
||||
//Next step triggered by purchaseHacknet() (HacknetNode.js)
|
||||
nextBtn.style.display = "none"; //Next step triggered by purchaseHacknet() (HacknetNode.js)
|
||||
break;
|
||||
case iTutorialSteps.HacknetNodesGoToWorldPage:
|
||||
Engine.loadHacknetNodesContent();
|
||||
iTutorialSetText("You just purchased a Hacknet Node! This Hacknet Node will passively " +
|
||||
"earn you money over time, both online and offline. When you get enough " +
|
||||
" money, you can upgrade " +
|
||||
"your newly-purchased Hacknet Node below.<br><br>" +
|
||||
"Let's go to the 'City' page through the main navigation menu.");
|
||||
document.getElementById("city-menu-link").setAttribute("class", "flashing-button");
|
||||
var worldButton = clearEventListeners("city-menu-link");
|
||||
worldButton.addEventListener("click", function() {
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
//Flash 'City' menu and set its tutorial click handler
|
||||
cityMainMenu.setAttribute("class", "flashing-button");
|
||||
cityMainMenu.addEventListener("click", function() {
|
||||
Engine.loadWorldContent();
|
||||
iTutorialNextStep();
|
||||
clearEventListeners("city-menu-link");
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case iTutorialSteps.WorldDescription:
|
||||
Engine.loadWorldContent();
|
||||
iTutorialSetText("This page lists all of the different locations you can currently " +
|
||||
"travel to. Each location has something that you can do. " +
|
||||
"There's a lot of content out in the world, make sure " +
|
||||
"you explore and discover!<br><br>" +
|
||||
"Lastly, click on the 'Tutorial' link in the main navigation menu.");
|
||||
document.getElementById("tutorial-menu-link").setAttribute("class", "flashing-button");
|
||||
var tutorialButton = clearEventListeners("tutorial-menu-link");
|
||||
tutorialButton.addEventListener("click", function() {
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
//Flash 'Tutorial' menu and set its tutorial click handler
|
||||
tutorialMainMenu.setAttribute("class", "flashing-button");
|
||||
tutorialMainMenu.addEventListener("click", function() {
|
||||
Engine.loadTutorialContent();
|
||||
iTutorialNextStep();
|
||||
clearEventListeners("tutorial-menu-link");
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
|
||||
case iTutorialSteps.TutorialPageInfo:
|
||||
Engine.loadTutorialContent();
|
||||
iTutorialSetText("This page contains a lot of different documentation about the game's " +
|
||||
"content and mechanics. <strong style='background-color:#444;'> I know it's a lot, but I highly suggest you read " +
|
||||
"(or at least skim) through this before you start playing</strong>. That's the end of the tutorial. " +
|
||||
"Hope you enjoy the game!");
|
||||
var next = clearEventListeners("interactive-tutorial-next");
|
||||
next.style.display = "inline-block";
|
||||
next.innerHTML = "Finish Tutorial";
|
||||
|
||||
var backButton = clearEventListeners("interactive-tutorial-back");
|
||||
backButton.style.display = "none";
|
||||
|
||||
next.addEventListener("click", function() {
|
||||
iTutorialNextStep();
|
||||
return false;
|
||||
});
|
||||
nextBtn.style.display = "inline-block";
|
||||
nextBtn.innerHTML = "Finish Tutorial";
|
||||
break;
|
||||
case iTutorialSteps.End:
|
||||
iTutorialEnd();
|
||||
@ -392,264 +419,85 @@ function iTutorialEvaluateStep() {
|
||||
default:
|
||||
throw new Error("Invalid tutorial step");
|
||||
}
|
||||
|
||||
if (ITutorial.stepIsDone[ITutorial.currStep] === true) {
|
||||
nextBtn.style.display = "inline-block";
|
||||
}
|
||||
}
|
||||
|
||||
//Go to the next step and evaluate it
|
||||
function iTutorialNextStep() {
|
||||
switch(currITutorialStep) {
|
||||
case iTutorialSteps.Start:
|
||||
currITutorialStep = iTutorialSteps.GoToCharacterPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.GoToCharacterPage:
|
||||
//Special behavior for certain steps
|
||||
if (ITutorial.currStep === iTutorialSteps.GoToCharacterPage) {
|
||||
document.getElementById("stats-menu-link").removeAttribute("class");
|
||||
currITutorialStep = iTutorialSteps.CharacterPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.CharacterPage:
|
||||
currITutorialStep = iTutorialSteps.CharacterGoToTerminalPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.CharacterGoToTerminalPage:
|
||||
document.getElementById("terminal-menu-link").removeAttribute("class");
|
||||
currITutorialStep = iTutorialSteps.TerminalIntro;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalIntro:
|
||||
currITutorialStep = iTutorialSteps.TerminalHelp;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalHelp:
|
||||
currITutorialStep = iTutorialSteps.TerminalLs;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalLs:
|
||||
currITutorialStep = iTutorialSteps.TerminalScan;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalScan:
|
||||
currITutorialStep = iTutorialSteps.TerminalScanAnalyze1;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalScanAnalyze1:
|
||||
currITutorialStep = iTutorialSteps.TerminalScanAnalyze2;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalScanAnalyze2:
|
||||
currITutorialStep = iTutorialSteps.TerminalConnect;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalConnect:
|
||||
currITutorialStep = iTutorialSteps.TerminalAnalyze;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalAnalyze:
|
||||
currITutorialStep = iTutorialSteps.TerminalNuke;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalNuke:
|
||||
currITutorialStep = iTutorialSteps.TerminalManualHack;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalManualHack:
|
||||
currITutorialStep = iTutorialSteps.TerminalHackingMechanics;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalHackingMechanics:
|
||||
currITutorialStep = iTutorialSteps.TerminalCreateScript;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalCreateScript:
|
||||
currITutorialStep = iTutorialSteps.TerminalTypeScript;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalTypeScript:
|
||||
currITutorialStep = iTutorialSteps.TerminalFree;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalFree:
|
||||
currITutorialStep = iTutorialSteps.TerminalRunScript;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalRunScript:
|
||||
currITutorialStep = iTutorialSteps.TerminalGoToActiveScriptsPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalGoToActiveScriptsPage:
|
||||
document.getElementById("active-scripts-menu-link").removeAttribute("class");
|
||||
currITutorialStep = iTutorialSteps.ActiveScriptsPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.ActiveScriptsPage:
|
||||
document.getElementById("terminal-menu-link").removeAttribute("class");
|
||||
currITutorialStep = iTutorialSteps.ActiveScriptsToTerminal;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.ActiveScriptsToTerminal:
|
||||
currITutorialStep = iTutorialSteps.TerminalTailScript;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalTailScript:
|
||||
currITutorialStep = iTutorialSteps.GoToHacknetNodesPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.GoToHacknetNodesPage:
|
||||
document.getElementById("hacknet-nodes-menu-link").removeAttribute("class");
|
||||
currITutorialStep = iTutorialSteps.HacknetNodesIntroduction;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.HacknetNodesIntroduction:
|
||||
currITutorialStep = iTutorialSteps.HacknetNodesGoToWorldPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.HacknetNodesGoToWorldPage:
|
||||
document.getElementById("city-menu-link").removeAttribute("class");
|
||||
currITutorialStep = iTutorialSteps.WorldDescription;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.WorldDescription:
|
||||
document.getElementById("tutorial-menu-link").removeAttribute("class");
|
||||
currITutorialStep = iTutorialSteps.TutorialPageInfo;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TutorialPageInfo:
|
||||
currITutorialStep = iTutorialSteps.End;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.End:
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid tutorial step");
|
||||
}
|
||||
if (ITutorial.currStep === iTutorialSteps.CharacterGoToTerminalPage) {
|
||||
document.getElementById("terminal-menu-link").removeAttribute("class");
|
||||
}
|
||||
if (ITutorial.currStep === iTutorialSteps.TerminalGoToActiveScriptsPage) {
|
||||
document.getElementById("active-scripts-menu-link").removeAttribute("class");
|
||||
}
|
||||
if (ITutorial.currStep === iTutorialSteps.ActiveScriptsPage) {
|
||||
document.getElementById("terminal-menu-link").removeAttribute("class");
|
||||
}
|
||||
if (ITutorial.currStep === iTutorialSteps.GoToHacknetNodesPage) {
|
||||
document.getElementById("hacknet-nodes-menu-link").removeAttribute("class");
|
||||
}
|
||||
if (ITutorial.currStep === iTutorialSteps.HacknetNodesGoToWorldPage) {
|
||||
document.getElementById("city-menu-link").removeAttribute("class");
|
||||
}
|
||||
if (ITutorial.currStep === iTutorialSteps.WorldDescription) {
|
||||
document.getElementById("tutorial-menu-link").removeAttribute("class");
|
||||
}
|
||||
|
||||
ITutorial.stepIsDone[ITutorial.currStep] = true;
|
||||
if (ITutorial.currStep < iTutorialSteps.End) {
|
||||
ITutorial.currStep += 1;
|
||||
}
|
||||
iTutorialEvaluateStep();
|
||||
}
|
||||
|
||||
//Go to previous step and evaluate
|
||||
function iTutorialPrevStep() {
|
||||
switch(currITutorialStep) {
|
||||
case iTutorialSteps.Start:
|
||||
currITutorialStep = iTutorialSteps.Start;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.GoToCharacterPage:
|
||||
currITutorialStep = iTutorialSteps.Start;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.CharacterPage:
|
||||
currITutorialStep = iTutorialSteps.GoToCharacterPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.CharacterGoToTerminalPage:
|
||||
currITutorialStep = iTutorialSteps.CharacterPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalIntro:
|
||||
currITutorialStep = iTutorialSteps.CharacterGoToTerminalPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalHelp:
|
||||
currITutorialStep = iTutorialSteps.TerminalIntro;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalLs:
|
||||
currITutorialStep = iTutorialSteps.TerminalHelp;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalScan:
|
||||
currITutorialStep = iTutorialSteps.TerminalLs;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalConnect:
|
||||
currITutorialStep = iTutorialSteps.TerminalScan;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalAnalyze:
|
||||
currITutorialStep = iTutorialSteps.TerminalConnect;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalNuke:
|
||||
currITutorialStep = iTutorialSteps.TerminalAnalyze;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalManualHack:
|
||||
currITutorialStep = iTutorialSteps.TerminalNuke;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalHackingMechanics:
|
||||
currITutorialStep = iTutorialSteps.TerminalManualHack;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalCreateScript:
|
||||
currITutorialStep = iTutorialSteps.TerminalManualHack;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalTypeScript:
|
||||
currITutorialStep = iTutorialSteps.TerminalCreateScript;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalFree:
|
||||
currITutorialStep = iTutorialSteps.TerminalTypeScript;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalRunScript:
|
||||
currITutorialStep = iTutorialSteps.TerminalFree;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalGoToActiveScriptsPage:
|
||||
currITutorialStep = iTutorialSteps.TerminalRunScript;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.ActiveScriptsPage:
|
||||
currITutorialStep = iTutorialSteps.TerminalGoToActiveScriptsPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.ActiveScriptsToTerminal:
|
||||
currITutorialStep = iTutorialSteps.ActiveScriptsPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TerminalTailScript:
|
||||
currITutorialStep = iTutorialSteps.ActiveScriptsToTerminal;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.GoToHacknetNodesPage:
|
||||
currITutorialStep = iTutorialSteps.TerminalTailScript;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.HacknetNodesIntroduction:
|
||||
currITutorialStep = iTutorialSteps.GoToHacknetNodesPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.HacknetNodesGoToWorldPage:
|
||||
currITutorialStep = iTutorialSteps.HacknetNodesIntroduction;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.WorldDescription:
|
||||
currITutorialStep = iTutorialSteps.HacknetNodesGoToWorldPage;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.TutorialPageInfo:
|
||||
currITutorialStep = iTutorialSteps.WorldDescription;
|
||||
iTutorialEvaluateStep();
|
||||
break;
|
||||
case iTutorialSteps.End:
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid tutorial step");
|
||||
if (ITutorial.currStep > iTutorialSteps.Start) {
|
||||
ITutorial.currStep -= 1;
|
||||
}
|
||||
iTutorialEvaluateStep();
|
||||
}
|
||||
|
||||
function iTutorialEnd() {
|
||||
//Re-enable auto save
|
||||
Engine.Counters.autoSaveCounter = 300;
|
||||
if (Settings.AutosaveInterval === 0) {
|
||||
Engine.Counters.autoSaveCounter = Infinity;
|
||||
} else {
|
||||
Engine.Counters.autoSaveCounter = Settings.AutosaveInterval * 5;
|
||||
}
|
||||
|
||||
console.log("Ending interactive tutorial");
|
||||
Engine.init();
|
||||
currITutorialStep = iTutorialSteps.End;
|
||||
iTutorialIsRunning = false;
|
||||
ITutorial.currStep = iTutorialSteps.End;
|
||||
ITutorial.isRunning = false;
|
||||
document.getElementById("interactive-tutorial-container").style.display = "none";
|
||||
dialogBoxCreate("If you are new to the game, the following links may be useful for you!<br><br>" +
|
||||
"<a class='a-link-button' href='http://bitburner.wikia.com/wiki/Chapt3rs_Guide_to_Getting_Started_with_Bitburner' target='_blank'>Getting Started Guide</a>" +
|
||||
"<a class='a-link-button' href='http://bitburner.wikia.com/wiki/Bitburner_Wiki' target='_blank'>Wiki</a><br><br>" +
|
||||
"The Beginner's Guide to Hacking was added to your home computer! It contains some tips/pointers for starting out with the game. " +
|
||||
"To read it, go to Terminal and enter<br><br>cat hackers-starting-handbook.lit");
|
||||
|
||||
//Create a popup with final introductory stuff
|
||||
var popupId = "interactive-tutorial-ending-popup";
|
||||
var txt = createElement("p", {
|
||||
innerHTML:
|
||||
"If you are new to the game, the following links may be useful for you!<br><br>" +
|
||||
"<a class='a-link-button' href='http://bitburner.wikia.com/wiki/Chapt3rs_Guide_to_Getting_Started_with_Bitburner' target='_blank'>Getting Started Guide</a>" +
|
||||
"<a class='a-link-button' href='http://bitburner.wikia.com/wiki/Bitburner_Wiki' target='_blank'>Wiki</a>" +
|
||||
"<a class='a-link-button' href='https://bitburner.readthedocs.io/en/latest/' target='_blank'>Documentation</a><br><br>" +
|
||||
"The Beginner's Guide to Hacking was added to your home computer! It contains some tips/pointers for starting out with the game. " +
|
||||
"To read it, go to Terminal and enter<br><br>cat hackers-starting-handbook.lit"
|
||||
});
|
||||
var gotitBtn = createElement("a", {
|
||||
class:"a-link-button", float:"right", padding:"6px", innerText:"Got it!",
|
||||
clickListener:()=>{
|
||||
removeElementById(popupId);
|
||||
}
|
||||
});
|
||||
createPopup(popupId, [txt, gotitBtn]);
|
||||
|
||||
Player.getHomeComputer().messages.push("hackers-starting-handbook.lit");
|
||||
}
|
||||
|
||||
@ -660,5 +508,4 @@ function iTutorialSetText(txt) {
|
||||
textBox.parentElement.scrollTop = 0; // this resets scroll position
|
||||
}
|
||||
|
||||
export {iTutorialSteps, iTutorialEnd, iTutorialStart, iTutorialNextStep, currITutorialStep,
|
||||
iTutorialIsRunning};
|
||||
export {iTutorialSteps, iTutorialEnd, iTutorialStart, iTutorialNextStep, ITutorial};
|
||||
|
@ -23,7 +23,11 @@ function initLiterature() {
|
||||
var title, fn, txt;
|
||||
title = "The Beginner's Guide to Hacking";
|
||||
fn = "hackers-starting-handbook.lit";
|
||||
txt = "When starting out, hacking is the most profitable way to earn money and progress. This " +
|
||||
txt = "Some resources:<br><br>" +
|
||||
"<a class='a-link-button' href='https://bitburner.readthedocs.io/en/latest/netscriptlearntoprogram.html' target='_blank' style='margin:4px'>Learn to Program</a><br><br>" +
|
||||
"<a class='a-link-button' href='https://bitburner.readthedocs.io/en/latest/netscriptjs.html' target='_blank' style='margin:4px'>For Experienced JavaScript Developers: NetscriptJS</a><br><br>" +
|
||||
"<a class='a-link-button' href='https://bitburner.readthedocs.io/en/latest/netscript.html' target='_blank' style='margin:4px'>Netscript Documentation</a><br><br>" +
|
||||
"When starting out, hacking is the most profitable way to earn money and progress. This " +
|
||||
"is a brief collection of tips/pointers on how to make the most out of your hacking scripts.<br><br>" +
|
||||
"-hack() and grow() both work by percentages. hack() steals a certain percentage of the " +
|
||||
"money on a server, and grow() increases the amount of money on a server by some percentage (multiplicatively)<br><br>" +
|
||||
|
421
src/Location.js
421
src/Location.js
File diff suppressed because it is too large
Load Diff
90
src/Locations.ts
Normal file
90
src/Locations.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import { IMap } from "./types";
|
||||
|
||||
/**
|
||||
* Display Location Content when visiting somewhere in the World
|
||||
*/
|
||||
// tslint:disable-next-line:variable-name
|
||||
export const Locations: IMap<string> = {
|
||||
// Cities
|
||||
Aevum: "Aevum",
|
||||
Chongqing: "Chongqing",
|
||||
Ishima: "Ishima",
|
||||
NewTokyo: "New Tokyo",
|
||||
Sector12: "Sector-12",
|
||||
Volhaven: "Volhaven",
|
||||
|
||||
// Aevum Locations
|
||||
AevumAeroCorp: "AeroCorp",
|
||||
AevumBachmanAndAssociates: "Bachman & Associates",
|
||||
AevumClarkeIncorporated: "Clarke Incorporated",
|
||||
AevumCrushFitnessGym: "Crush Fitness Gym",
|
||||
AevumECorp: "ECorp",
|
||||
AevumFulcrumTechnologies: "Fulcrum Technologies",
|
||||
AevumGalacticCybersystems: "Galactic Cybersystems",
|
||||
AevumNetLinkTechnologies: "NetLink Technologies",
|
||||
AevumPolice: "Aevum Police Headquarters",
|
||||
AevumRhoConstruction: "Rho Construction",
|
||||
AevumSlums: "Aevum Slums",
|
||||
AevumSnapFitnessGym: "Snap Fitness Gym",
|
||||
AevumSummitUniversity: "Summit University",
|
||||
AevumTravelAgency: "Aevum Travel Agency",
|
||||
AevumWatchdogSecurity: "Watchdog Security",
|
||||
|
||||
// Chongqing locations
|
||||
ChongqingKuaiGongInternational: "KuaiGong International",
|
||||
ChongqingSlums: "Chongqing Slums",
|
||||
ChongqingSolarisSpaceSystems: "Solaris Space Systems",
|
||||
ChongqingTravelAgency: "Chongqing Travel Agency",
|
||||
|
||||
// Sector 12
|
||||
Sector12AlphaEnterprises: "Alpha Enterprises",
|
||||
Sector12BladeIndustries: "Blade Industries",
|
||||
Sector12CIA: "Central Intelligence Agency",
|
||||
Sector12CarmichaelSecurity: "Carmichael Security",
|
||||
Sector12CityHall: "Sector-12 City Hall",
|
||||
Sector12DeltaOne: "DeltaOne",
|
||||
Sector12FoodNStuff: "FoodNStuff",
|
||||
Sector12FourSigma: "Four Sigma",
|
||||
Sector12IcarusMicrosystems: "Icarus Microsystems",
|
||||
Sector12IronGym: "Iron Gym",
|
||||
Sector12JoesGuns: "Joe's Guns",
|
||||
Sector12MegaCorp: "MegaCorp",
|
||||
Sector12NSA: "National Security Agency",
|
||||
Sector12PowerhouseGym: "Powerhouse Gym",
|
||||
Sector12RothmanUniversity: "Rothman University",
|
||||
Sector12Slums: "Sector-12 Slums",
|
||||
Sector12TravelAgency: "Sector-12 Travel Agency",
|
||||
Sector12UniversalEnergy: "Universal Energy",
|
||||
|
||||
// New Tokyo
|
||||
NewTokyoDefComm: "DefComm",
|
||||
NewTokyoGlobalPharmaceuticals: "Global Pharmaceuticals",
|
||||
NewTokyoNoodleBar: "Noodle Bar",
|
||||
NewTokyoSlums: "New Tokyo Slums",
|
||||
NewTokyoTravelAgency: "New Tokyo Travel Agency",
|
||||
NewTokyoVitaLife: "VitaLife",
|
||||
|
||||
// Ishima
|
||||
IshimaNovaMedical: "Nova Medical",
|
||||
IshimaOmegaSoftware: "Omega Software",
|
||||
IshimaSlums: "Ishima Slums",
|
||||
IshimaStormTechnologies: "Storm Technologies",
|
||||
IshimaTravelAgency: "Ishima Travel Agency",
|
||||
|
||||
// Volhaven
|
||||
VolhavenCompuTek: "CompuTek",
|
||||
VolhavenHeliosLabs: "Helios Labs",
|
||||
VolhavenLexoCorp: "LexoCorp",
|
||||
VolhavenMilleniumFitnessGym: "Millenium Fitness Gym",
|
||||
VolhavenNWO: "NWO",
|
||||
VolhavenOmniTekIncorporated: "OmniTek Incorporated",
|
||||
VolhavenOmniaCybersystems: "Omnia Cybersystems",
|
||||
VolhavenSlums: "Volhaven Slums",
|
||||
VolhavenSysCoreSecurities: "SysCore Securities",
|
||||
VolhavenTravelAgency: "Volhaven Travel Agency",
|
||||
VolhavenZBInstituteOfTechnology: "ZB Institute of Technology",
|
||||
|
||||
// Generic locations
|
||||
Hospital: "Hospital",
|
||||
WorldStockExchange: "World Stock Exchange",
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
import {BitNodeMultipliers} from "./BitNode";
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Player} from "./Player";
|
||||
import {Environment} from "./NetscriptEnvironment";
|
||||
|
@ -5,7 +5,7 @@ import {updateActiveScriptsItems} from "./ActiveScriptsUI";
|
||||
import {Augmentations, Augmentation,
|
||||
augmentationExists, installAugmentations,
|
||||
AugmentationNames} from "./Augmentations";
|
||||
import {BitNodeMultipliers} from "./BitNode";
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {determineCrimeSuccess, findCrime} from "./Crimes";
|
||||
import {Bladeburner} from "./Bladeburner";
|
||||
import {Companies, Company, CompanyPosition,
|
||||
@ -13,12 +13,11 @@ import {Companies, Company, CompanyPosition,
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Programs} from "./CreateProgram";
|
||||
import {DarkWebItems} from "./DarkWeb";
|
||||
import {Engine} from "./engine";
|
||||
import {AllGangs} from "./Gang";
|
||||
import {Factions, Faction, joinFaction,
|
||||
factionExists, purchaseAugmentation} from "./Faction";
|
||||
import {getCostOfNextHacknetNode, purchaseHacknet} from "./HacknetNode";
|
||||
import {Locations} from "./Location";
|
||||
import {Locations} from "./Locations";
|
||||
import {Message, Messages} from "./Message";
|
||||
import {inMission} from "./Missions";
|
||||
import {Player} from "./Player";
|
||||
@ -35,7 +34,7 @@ import {StockMarket, StockSymbols, SymbolToStockMap, initStockSymbols,
|
||||
updateStockTicker, updateStockPlayerPosition,
|
||||
Stock, shortStock, sellShort, OrderTypes,
|
||||
PositionTypes, placeOrder, cancelOrder} from "./StockMarket";
|
||||
import {post} from "./Terminal";
|
||||
import {post} from "./ui/postToTerminal";
|
||||
import {TextFile, getTextFile, createTextFile} from "./TextFile";
|
||||
|
||||
import {unknownBladeburnerActionErrorMessage,
|
||||
@ -50,6 +49,7 @@ import {makeRuntimeRejectMsg, netscriptDelay, runScriptFromScript,
|
||||
import {NetscriptPort} from "./NetscriptPort";
|
||||
|
||||
import Decimal from "decimal.js";
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {isPowerOfTwo} from "../utils/helpers/isPowerOfTwo";
|
||||
import {arrayToString} from "../utils/helpers/arrayToString";
|
||||
@ -183,11 +183,11 @@ function NetscriptFunctions(workerScript) {
|
||||
/**
|
||||
* @param {number} ram The amount of server RAM to calculate cost of.
|
||||
* @exception {Error} If the value passed in is not numeric, out of range, or too large of a value.
|
||||
* @returns {number} The cost of
|
||||
* @returns {number} The cost of
|
||||
*/
|
||||
const getPurchaseServerRamCostGuard = (ram) => {
|
||||
const guardedRam = Math.round(ram);
|
||||
if (isNaN(guardedRam) || !powerOfTwo(guardedRam)) {
|
||||
if (isNaN(guardedRam) || !isPowerOfTwo(guardedRam)) {
|
||||
throw Error("failed due to invalid ram argument. Must be numeric and a power of 2");
|
||||
}
|
||||
|
||||
@ -1415,7 +1415,7 @@ function NetscriptFunctions(workerScript) {
|
||||
var newTotal = origTotal + totalPrice;
|
||||
stock.playerShares += shares;
|
||||
stock.playerAvgPx = newTotal / stock.playerShares;
|
||||
if (Engine.currentPage == Engine.Page.StockMarket) {
|
||||
if (routing.isOn(Page.StockMarket)) {
|
||||
updateStockPlayerPosition(stock);
|
||||
}
|
||||
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.buyStock == null) {
|
||||
@ -1456,7 +1456,7 @@ function NetscriptFunctions(workerScript) {
|
||||
if (stock.playerShares == 0) {
|
||||
stock.playerAvgPx = 0;
|
||||
}
|
||||
if (Engine.currentPage == Engine.Page.StockMarket) {
|
||||
if (routing.isOn(Page.StockMarket)) {
|
||||
updateStockPlayerPosition(stock);
|
||||
}
|
||||
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.sellStock == null) {
|
||||
@ -1599,6 +1599,36 @@ function NetscriptFunctions(workerScript) {
|
||||
};
|
||||
return cancelOrder(params, workerScript);
|
||||
},
|
||||
getStockVolatility : function(symbol) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("getStockVolatility", CONSTANTS.ScriptBuySellStockRamCost);
|
||||
}
|
||||
updateDynamicRam("getStockVolatility", CONSTANTS.ScriptBuySellStockRamCost);
|
||||
if (!Player.has4SDataTixApi) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "You don't have 4S Market Data TIX API Access! Cannot use getStockVolatility()");
|
||||
}
|
||||
var stock = SymbolToStockMap[symbol];
|
||||
if (stock == null) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid stock symbol passed into getStockVolatility()");
|
||||
}
|
||||
return stock.mv / 100; //Convert from percentage to decimal
|
||||
},
|
||||
getStockForecast : function(symbol) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("getStockForecast", CONSTANTS.ScriptBuySellStockRamCost);
|
||||
}
|
||||
updateDynamicRam("getStockForecast", CONSTANTS.ScriptBuySellStockRamCost);
|
||||
if (!Player.has4SDataTixApi) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "You don't have 4S Market Data TIX API Access! Cannot use getStockForecast()");
|
||||
}
|
||||
var stock = SymbolToStockMap[symbol];
|
||||
if (stock == null) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid stock symbol passed into getStockForecast()");
|
||||
}
|
||||
var forecast = 50;
|
||||
stock.b ? forecast += stock.otlkMag : forecast -= stock.otlkMag;
|
||||
return forecast / 100; //Convert from percentage to decimal
|
||||
},
|
||||
getPurchasedServerLimit : function() {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("getPurchasedServerLimit", CONSTANTS.ScriptGetPurchasedServerLimit);
|
||||
@ -2844,16 +2874,16 @@ function NetscriptFunctions(workerScript) {
|
||||
workerScript.scriptRef.log("ERROR: Cannot join " + name + " Faction because you have not been invited. joinFaction() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
var index = Player.factionInvitations.indexOf(name);
|
||||
if (index === -1) {
|
||||
//Redundant and should never happen...
|
||||
workerScript.scriptRef.log("ERROR: Cannot join " + name + " Faction because you have not been invited. joinFaction() failed");
|
||||
return false;
|
||||
}
|
||||
Player.factionInvitations.splice(index, 1);
|
||||
var fac = Factions[name];
|
||||
joinFaction(fac);
|
||||
|
||||
//Update Faction Invitation list to account for joined + banned factions
|
||||
for (var i = 0; i < Player.factionInvitations.length; ++i) {
|
||||
if (Player.factionInvitations[i] == name || Factions[Player.factionInvitations[i]].isBanned) {
|
||||
Player.factionInvitations.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
|
||||
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.joinFaction == null) {
|
||||
workerScript.scriptRef.log("Joined the " + name + " faction.");
|
||||
@ -3424,12 +3454,7 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
updateDynamicRam("getCurrentAction", CONSTANTS.ScriptBladeburnerApiBaseRamCost / 4);
|
||||
if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || hasBladeburner2079SF)) {
|
||||
let res = Player.bladeburner.getTypeAndNameFromActionId(Player.bladeburner.action);
|
||||
if (res.type === "Idle" && res.name === "Idle") {
|
||||
return null;
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
return Player.bladeburner.getTypeAndNameFromActionId(Player.bladeburner.action);
|
||||
}
|
||||
throw makeRuntimeRejectMsg(workerScript, "getCurrentAction() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " +
|
||||
"at the Bladeburner division or because you do not have Source-File 7");
|
||||
@ -3644,6 +3669,21 @@ function NetscriptFunctions(workerScript) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "getSkillLevel() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " +
|
||||
"at the Bladeburner division or because you do not have Source-File 7");
|
||||
},
|
||||
getSkillUpgradeCost : function(skillName="") {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("getSkillUpgradeCost", CONSTANTS.ScriptBladeburnerApiBaseRamCost);
|
||||
}
|
||||
updateDynamicRam("getSkillUpgradeCost", CONSTANTS.ScriptBladeburnerApiBaseRamCost);
|
||||
if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || hasBladeburner2079SF)) {
|
||||
try {
|
||||
return Player.bladeburner.getSkillUpgradeCostNetscriptFn(skillName, workerScript);
|
||||
} catch(e) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Bladeburner.getSkillUpgradeCost() failed with exception: " + e);
|
||||
}
|
||||
}
|
||||
throw makeRuntimeRejectMsg(workerScript, "getSkillUpgradeCost() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " +
|
||||
"at the Bladeburner division or because you do not have Source-File 7");
|
||||
},
|
||||
upgradeSkill : function(skillName) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("upgradeSkill", CONSTANTS.ScriptBladeburnerApiBaseRamCost);
|
||||
@ -3734,6 +3774,21 @@ function NetscriptFunctions(workerScript) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "getCityChaos() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " +
|
||||
"at the Bladeburner division or because you do not have Source-File 7");
|
||||
},
|
||||
getCity : function() {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("getCity", CONSTANTS.ScriptBladeburnerApiBaseRamCost);
|
||||
}
|
||||
updateDynamicRam("getCity", CONSTANTS.ScriptBladeburnerApiBaseRamCost);
|
||||
if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || hasBladeburner2079SF)) {
|
||||
try {
|
||||
return Player.bladeburner.city;
|
||||
} catch(e) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Bladeburner.getCity() failed with exception: " + e);
|
||||
}
|
||||
}
|
||||
throw makeRuntimeRejectMsg(workerScript, "getCity() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " +
|
||||
"at the Bladeburner division or because you do not have Source-File 7");
|
||||
},
|
||||
switchCity : function(cityName) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("switchCity", CONSTANTS.ScriptBladeburnerApiBaseRamCost);
|
||||
@ -3791,6 +3846,14 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
throw makeRuntimeRejectMsg(workerScript, "joinBladeburnerDivision() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " +
|
||||
"at the Bladeburner division or because you do not have Source-File 7");
|
||||
},
|
||||
getBonusTime : function() {
|
||||
if (workerScript.checkingRam) {return 0;}
|
||||
if ((Player.bitNodeN === 7 || hasBladeburner2079SF)) {
|
||||
return Math.round(Player.bladeburner.storedCycles / 5);
|
||||
}
|
||||
throw makeRuntimeRejectMsg(workerScript, "getBonusTime() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " +
|
||||
"at the Bladeburner division or because you do not have Source-File 7");
|
||||
}
|
||||
}
|
||||
} //End return
|
||||
|
@ -199,7 +199,8 @@ function startNetscript1Script(workerScript) {
|
||||
});
|
||||
}
|
||||
int.setProperty(scope, name, int.createAsyncFunction(tempWrapper));
|
||||
} else if (name === "sprintf" || name === "vsprintf" || name === "scp") {
|
||||
} else if (name === "sprintf" || name === "vsprintf" || name === "scp" ||
|
||||
name == "write" || name === "read" || name === "tryWrite") {
|
||||
let tempWrapper = function() {
|
||||
let fnArgs = [];
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {Augmentations, applyAugmentation,
|
||||
AugmentationNames,
|
||||
PlayerOwnedAugmentation} from "./Augmentations";
|
||||
import {BitNodes, BitNode, BitNodeMultipliers} from "./BitNode";
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {Company, Companies, getNextCompanyPosition,
|
||||
getJobRequirementText, CompanyPosition,
|
||||
CompanyPositions} from "./Company";
|
||||
@ -13,9 +13,10 @@ import {Engine} from "./engine";
|
||||
import {Factions, Faction,
|
||||
displayFactionContent} from "./Faction";
|
||||
import {Gang, resetGangs} from "./Gang";
|
||||
import {Locations} from "./Location";
|
||||
import {Locations} from "./Locations";
|
||||
import {hasBn11SF, hasWallStreetSF,hasAISF} from "./NetscriptFunctions";
|
||||
import {AllServers, Server, AddToAllServers} from "./Server";
|
||||
import {Settings} from "./Settings";
|
||||
import {SpecialServerIps, SpecialServerNames} from "./SpecialServerIps";
|
||||
import {SourceFiles, applySourceFile} from "./SourceFile";
|
||||
|
||||
@ -172,6 +173,8 @@ function PlayerObject() {
|
||||
//Stock Market
|
||||
this.hasWseAccount = false;
|
||||
this.hasTixApiAccess = false;
|
||||
this.has4SData = false;
|
||||
this.has4SDataTixApi = false;
|
||||
|
||||
//Gang
|
||||
this.gang = 0;
|
||||
@ -388,6 +391,8 @@ PlayerObject.prototype.prestigeSourceFile = function() {
|
||||
//Reset Stock market
|
||||
this.hasWseAccount = false;
|
||||
this.hasTixApiAccess = false;
|
||||
this.has4SData = false;
|
||||
this.has4SDataTixApi = false;
|
||||
|
||||
//BitNode 3: Corporatocracy
|
||||
if (this.bitNodeN === 3) {this.money = new Decimal(150e9);}
|
||||
@ -561,6 +566,8 @@ PlayerObject.prototype.analyze = function() {
|
||||
|
||||
PlayerObject.prototype.hasProgram = function(programName) {
|
||||
var home = Player.getHomeComputer();
|
||||
if (home == null) {return false;}
|
||||
|
||||
for (var i = 0; i < home.programs.length; ++i) {
|
||||
if (programName.toLowerCase() == home.programs[i].toLowerCase()) {return true;}
|
||||
}
|
||||
@ -1692,9 +1699,14 @@ PlayerObject.prototype.takeDamage = function(amt) {
|
||||
}
|
||||
|
||||
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));
|
||||
if (Settings.SuppressHospitalizationPopup === false) {
|
||||
dialogBoxCreate(
|
||||
"You were in critical condition! You were taken to the hospital where " +
|
||||
"luckily they were able to save your life. You were charged " +
|
||||
numeral(this.max_hp * CONSTANTS.HospitalCostPerHp).format('$0.000a')
|
||||
);
|
||||
}
|
||||
|
||||
this.loseMoney(this.max_hp * CONSTANTS.HospitalCostPerHp);
|
||||
this.hp = this.max_hp;
|
||||
}
|
||||
@ -2039,7 +2051,7 @@ PlayerObject.prototype.reapplyAllSourceFiles = function() {
|
||||
//those requirements and will return an array of all factions that the Player should
|
||||
//receive an invitation to
|
||||
PlayerObject.prototype.checkForFactionInvitations = function() {
|
||||
let invitedFactions = []; //Array which will hold all Factions th eplayer should be invited to
|
||||
let invitedFactions = []; //Array which will hold all Factions the player should be invited to
|
||||
|
||||
var numAugmentations = this.augmentations.length;
|
||||
|
||||
|
57
src/Prestige.js
Normal file → Executable file
57
src/Prestige.js
Normal file → Executable file
@ -109,17 +109,6 @@ function prestigeAugmentation() {
|
||||
//Messages
|
||||
initMessages();
|
||||
|
||||
//Reset Stock market
|
||||
if (Player.hasWseAccount) {
|
||||
initStockMarket();
|
||||
initSymbolToStockMap();
|
||||
}
|
||||
setStockMarketContentCreated(false);
|
||||
var stockMarketList = document.getElementById("stock-market-list");
|
||||
while(stockMarketList.firstChild) {
|
||||
stockMarketList.removeChild(stockMarketList.firstChild);
|
||||
}
|
||||
|
||||
//Gang, in BitNode 2
|
||||
if (Player.bitNodeN == 2 && Player.inGang()) {
|
||||
var faction = Factions[Player.gang.facName];
|
||||
@ -140,6 +129,20 @@ function prestigeAugmentation() {
|
||||
Player.hasTixApiAccess = true;
|
||||
}
|
||||
|
||||
//Reset Stock market
|
||||
if (Player.hasWseAccount) {
|
||||
initStockMarket();
|
||||
initSymbolToStockMap();
|
||||
}
|
||||
setStockMarketContentCreated(false);
|
||||
var stockMarketList = document.getElementById("stock-market-list");
|
||||
while(stockMarketList.firstChild) {
|
||||
stockMarketList.removeChild(stockMarketList.firstChild);
|
||||
}
|
||||
var watchlist = document.getElementById("stock-market-watchlist-filter");
|
||||
watchlist.value = ""; //Reset watchlist filter
|
||||
|
||||
//Load Terminal Screen
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "visible";
|
||||
Terminal.resetTerminalInput();
|
||||
@ -241,22 +244,6 @@ function prestigeSourceFile() {
|
||||
//Reinitialize Bit Node flags
|
||||
initSingularitySFFlags();
|
||||
|
||||
//Reset Stock market, gang, and corporation
|
||||
if (Player.hasWseAccount) {
|
||||
initStockMarket();
|
||||
initSymbolToStockMap();
|
||||
}
|
||||
setStockMarketContentCreated(false);
|
||||
var stockMarketList = document.getElementById("stock-market-list");
|
||||
while(stockMarketList.firstChild) {
|
||||
stockMarketList.removeChild(stockMarketList.firstChild);
|
||||
}
|
||||
|
||||
Player.gang = null;
|
||||
deleteGangDisplayContent();
|
||||
Player.corporation = null;
|
||||
Player.bladeburner = null;
|
||||
|
||||
//BitNode 3: Corporatocracy
|
||||
if (Player.bitNodeN === 3) {
|
||||
Player.money = new Decimal(150e9);
|
||||
@ -316,6 +303,22 @@ function prestigeSourceFile() {
|
||||
Player.hasTixApiAccess = true;
|
||||
}
|
||||
|
||||
//Reset Stock market, gang, and corporation
|
||||
if (Player.hasWseAccount) {
|
||||
initStockMarket();
|
||||
initSymbolToStockMap();
|
||||
}
|
||||
setStockMarketContentCreated(false);
|
||||
var stockMarketList = document.getElementById("stock-market-list");
|
||||
while(stockMarketList.firstChild) {
|
||||
stockMarketList.removeChild(stockMarketList.firstChild);
|
||||
}
|
||||
|
||||
Player.gang = null;
|
||||
deleteGangDisplayContent();
|
||||
Player.corporation = null;
|
||||
Player.bladeburner = null;
|
||||
|
||||
//Gain int exp
|
||||
Player.gainIntelligenceExp(5);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {BitNode, BitNodes} from "./BitNode";
|
||||
import {BitNodes} from "./BitNode";
|
||||
import {Engine} from "./engine";
|
||||
import {Player} from "./Player";
|
||||
import {prestigeSourceFile} from "./Prestige";
|
||||
@ -19,7 +19,7 @@ import {yesNoBoxCreate, yesNoBoxGetYesButton,
|
||||
function writeRedPillLine(line) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
|
||||
var container = document.getElementById("red-pill-container");
|
||||
var container = document.getElementById("red-pill-content");
|
||||
var pElem = document.createElement("p");
|
||||
container.appendChild(pElem);
|
||||
|
||||
@ -134,7 +134,7 @@ function giveSourceFile(bitNodeNumber) {
|
||||
|
||||
function loadBitVerse(destroyedBitNodeNum, flume=false) {
|
||||
//Clear the screen
|
||||
var container = document.getElementById("red-pill-container");
|
||||
var container = document.getElementById("red-pill-content");
|
||||
removeChildrenFromElement(container);
|
||||
|
||||
//Create the Bit Verse
|
||||
|
@ -13,7 +13,7 @@ import {loadMessages, initMessages, Messages} from "./Message";
|
||||
import {Player, loadPlayer} from "./Player";
|
||||
import {loadAllRunningScripts} from "./Script";
|
||||
import {AllServers, loadAllServers} from "./Server";
|
||||
import {loadSettings, initSettings, Settings} from "./Settings";
|
||||
import {Settings} from "./Settings";
|
||||
import {loadSpecialServerIps, SpecialServerIps} from "./SpecialServerIps";
|
||||
import {loadStockMarket, StockMarket} from "./StockMarket";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
@ -23,6 +23,7 @@ import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver";
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {createPopup} from "../utils/uiHelpers/createPopup";
|
||||
import {createStatusText} from "./ui/createStatusText";
|
||||
import {formatNumber} from "../utils/StringHelperFunctions";
|
||||
import {removeElementById} from "../utils/uiHelpers/removeElementById";
|
||||
|
||||
@ -97,7 +98,7 @@ BitburnerSaveObject.prototype.saveGame = function(db) {
|
||||
//console.log("Saved game to LocalStorage!");
|
||||
} catch(e) {
|
||||
if (e.code == 22) {
|
||||
Engine.createStatusText("Save failed for localStorage! Check console(F12)");
|
||||
createStatusText("Save failed for localStorage! Check console(F12)");
|
||||
console.log("Failed to save game to localStorage because the size of the save file " +
|
||||
"is too large. However, the game will still be saved to IndexedDb if your browser " +
|
||||
"supports it. If you would like to save to localStorage as well, then " +
|
||||
@ -106,7 +107,7 @@ BitburnerSaveObject.prototype.saveGame = function(db) {
|
||||
}
|
||||
}
|
||||
|
||||
Engine.createStatusText("Game saved!");
|
||||
createStatusText("Game saved!");
|
||||
}
|
||||
|
||||
function loadGame(saveString) {
|
||||
@ -168,13 +169,13 @@ function loadGame(saveString) {
|
||||
}
|
||||
if (saveObj.hasOwnProperty("SettingsSave")) {
|
||||
try {
|
||||
loadSettings(saveObj.SettingsSave);
|
||||
Settings.load(saveObj.SettingsSave);
|
||||
} catch(e) {
|
||||
console.log("ERROR: Failed to parse Settings. Re-initing default values");
|
||||
initSettings();
|
||||
Settings.init();
|
||||
}
|
||||
} else {
|
||||
initSettings();
|
||||
Settings.init();
|
||||
}
|
||||
if (saveObj.hasOwnProperty("FconfSettingsSave")) {
|
||||
try {
|
||||
@ -387,12 +388,12 @@ function loadImportedGame(saveObj, saveString) {
|
||||
}
|
||||
if (saveObj.hasOwnProperty("SettingsSave")) {
|
||||
try {
|
||||
loadSettings(saveObj.SettingsSave);
|
||||
Settings.load(saveObj.SettingsSave);
|
||||
} catch(e) {
|
||||
initSettings();
|
||||
Settings.init();
|
||||
}
|
||||
} else {
|
||||
initSettings();
|
||||
Settings.init();
|
||||
}
|
||||
if (saveObj.hasOwnProperty("FconfSettingsSave")) {
|
||||
try {
|
||||
@ -581,7 +582,7 @@ BitburnerSaveObject.prototype.deleteGame = function(db) {
|
||||
request.onerror = function(e) {
|
||||
console.log("Failed to delete save from indexedDb: " + e);
|
||||
}
|
||||
Engine.createStatusText("Game deleted!");
|
||||
createStatusText("Game deleted!");
|
||||
}
|
||||
|
||||
function createNewUpdateText() {
|
||||
|
@ -21,7 +21,7 @@ import {CONSTANTS} from "./Constants";
|
||||
import {Engine} from "./engine";
|
||||
import {FconfSettings, parseFconfSettings} from "./Fconf";
|
||||
import {iTutorialSteps, iTutorialNextStep,
|
||||
iTutorialIsRunning, currITutorialStep} from "./InteractiveTutorial";
|
||||
ITutorial} from "./InteractiveTutorial";
|
||||
import {evaluateImport} from "./NetscriptEvaluator";
|
||||
import {NetscriptFunctions} from "./NetscriptFunctions";
|
||||
import {addWorkerScript,
|
||||
@ -29,10 +29,11 @@ import {addWorkerScript,
|
||||
import {Player} from "./Player";
|
||||
import {AllServers, processSingleServerGrowth} from "./Server";
|
||||
import {Settings} from "./Settings";
|
||||
import {post} from "./Terminal";
|
||||
import {post} from "./ui/postToTerminal";
|
||||
import {TextFile} from "./TextFile";
|
||||
|
||||
import {parse, Node} from "../utils/acorn";
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver";
|
||||
@ -260,7 +261,7 @@ function updateScriptEditorContent() {
|
||||
//Define key commands in script editor (ctrl o to save + close, etc.)
|
||||
$(document).keydown(function(e) {
|
||||
if (Settings.DisableHotkeys === true) {return;}
|
||||
if (Engine.currentPage == Engine.Page.ScriptEditor) {
|
||||
if (routing.isOn(Page.ScriptEditor)) {
|
||||
//Ctrl + b
|
||||
if (e.keyCode == 66 && (e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
@ -280,8 +281,9 @@ function saveAndCloseScriptEditor() {
|
||||
var filename = document.getElementById("script-editor-filename").value;
|
||||
var editor = ace.edit('javascript-editor');
|
||||
var code = editor.getValue();
|
||||
if (iTutorialIsRunning && currITutorialStep == iTutorialSteps.TerminalTypeScript) {
|
||||
if (filename != "foodnstuff.script") {
|
||||
if (ITutorial.isRunning && ITutorial.currStep === iTutorialSteps.TerminalTypeScript) {
|
||||
//Make sure filename + code properly follow tutorial
|
||||
if (filename !== "foodnstuff.script") {
|
||||
dialogBoxCreate("Leave the script name as 'foodnstuff'!");
|
||||
return;
|
||||
}
|
||||
@ -290,7 +292,23 @@ function saveAndCloseScriptEditor() {
|
||||
dialogBoxCreate("Please copy and paste the code from the tutorial!");
|
||||
return;
|
||||
}
|
||||
iTutorialNextStep();
|
||||
|
||||
//Save the script
|
||||
let s = Player.getCurrentServer();
|
||||
for (var i = 0; i < s.scripts.length; i++) {
|
||||
if (filename == s.scripts[i].filename) {
|
||||
s.scripts[i].saveScript();
|
||||
Engine.loadTerminalContent();
|
||||
return iTutorialNextStep();
|
||||
}
|
||||
}
|
||||
|
||||
//If the current script does NOT exist, create a new one
|
||||
let script = new Script();
|
||||
script.saveScript();
|
||||
s.scripts.push(script);
|
||||
|
||||
return iTutorialNextStep();
|
||||
}
|
||||
|
||||
if (filename == "") {
|
||||
@ -364,7 +382,7 @@ function Script() {
|
||||
|
||||
//Get the script data from the Script Editor and save it to the object
|
||||
Script.prototype.saveScript = function() {
|
||||
if (Engine.currentPage == Engine.Page.ScriptEditor) {
|
||||
if (routing.isOn(Page.ScriptEditor)) {
|
||||
//Update code and filename
|
||||
var editor = ace.edit('javascript-editor');
|
||||
var code = editor.getValue();
|
||||
@ -461,6 +479,18 @@ function parseOnlyRamCalculate(server, code, workerScript) {
|
||||
const resolvedRefs = new Set();
|
||||
while (unresolvedRefs.length > 0) {
|
||||
const ref = unresolvedRefs.shift();
|
||||
|
||||
// Check if this is one of the special keys, and add the appropriate ram cost if so.
|
||||
if (ref === "hacknet" && !resolvedRefs.has("hacknet")) {
|
||||
ram += CONSTANTS.ScriptHacknetNodesRamCost;
|
||||
}
|
||||
if (ref === "document" && !resolvedRefs.has("document")) {
|
||||
ram += CONSTANTS.ScriptDomRamCost;
|
||||
}
|
||||
if (ref === "window" && !resolvedRefs.has("window")) {
|
||||
ram += CONSTANTS.ScriptDomRamCost;
|
||||
}
|
||||
|
||||
resolvedRefs.add(ref);
|
||||
|
||||
if (ref.endsWith(".*")) {
|
||||
@ -478,13 +508,6 @@ function parseOnlyRamCalculate(server, code, workerScript) {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this is one of the special keys, and add the appropriate ram cost if so.
|
||||
if (ref == specialReferenceIF) ram += CONSTANTS.ScriptIfRamCost;
|
||||
if (ref == specialReferenceFOR) ram += CONSTANTS.ScriptForRamCost;
|
||||
if (ref == specialReferenceWHILE) ram += CONSTANTS.ScriptWhileRamCost;
|
||||
if (ref == "hacknet") ram += CONSTANTS.ScriptHacknetNodesRamCost;
|
||||
if (ref == "document" || ref == "window") ram += CONSTANTS.ScriptDomRamCost;
|
||||
|
||||
// Check if this ident is a function in the workerscript env. If it is, then we need to
|
||||
// get its RAM cost. We do this by calling it, which works because the running script
|
||||
// is in checkingRam mode.
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {BitNodeMultipliers} from "./BitNode";
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Programs} from "./CreateProgram";
|
||||
import {Player} from "./Player";
|
||||
|
129
src/Settings.ts
Normal file
129
src/Settings.ts
Normal file
@ -0,0 +1,129 @@
|
||||
import { ISelfInitializer, ISelfLoading } from "./types";
|
||||
|
||||
/**
|
||||
* Represents the default settings the player could customize.
|
||||
*/
|
||||
interface IDefaultSettings {
|
||||
/**
|
||||
* How often the game should autosave the player's progress, in seconds.
|
||||
*/
|
||||
AutosaveInterval: number;
|
||||
|
||||
/**
|
||||
* How many milliseconds between execution points for Netscript 1 statements.
|
||||
*/
|
||||
CodeInstructionRunTime: number;
|
||||
|
||||
/**
|
||||
* Whether global keyboard shortcuts should be recognized throughout the game.
|
||||
*/
|
||||
DisableHotkeys: boolean;
|
||||
|
||||
/**
|
||||
* Limit the number of log entries for each script being executed on each server.
|
||||
*/
|
||||
MaxLogCapacity: number;
|
||||
|
||||
/**
|
||||
* Limit how many entries can be written to a Netscript Port before entries start to get pushed out.
|
||||
*/
|
||||
MaxPortCapacity: number;
|
||||
|
||||
/**
|
||||
* Whether the player should be asked to confirm purchasing each and every augmentation.
|
||||
*/
|
||||
SuppressBuyAugmentationConfirmation: boolean;
|
||||
|
||||
/**
|
||||
* Whether the user should be prompted to join each faction via a dialog box.
|
||||
*/
|
||||
SuppressFactionInvites: boolean;
|
||||
|
||||
/**
|
||||
* Whether to show a popup message when player is hospitalized from taking too much damage
|
||||
*/
|
||||
SuppressHospitalizationPopup: boolean;
|
||||
|
||||
/**
|
||||
* Whether the user should be shown a dialog box whenever they receive a new message file.
|
||||
*/
|
||||
SuppressMessages: boolean;
|
||||
|
||||
/**
|
||||
* Whether the user should be asked to confirm travelling between cities.
|
||||
*/
|
||||
SuppressTravelConfirmation: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents all possible settings the player wants to customize to their play style.
|
||||
*/
|
||||
interface ISettings extends IDefaultSettings {
|
||||
/**
|
||||
* The keybinding to use in the script editor.
|
||||
* TODO: This should really be an enum of allowed values.
|
||||
*/
|
||||
EditorKeybinding: string;
|
||||
|
||||
/**
|
||||
* The theme used in the script editor.
|
||||
* TODO: This should really be an enum of allowed values.
|
||||
*/
|
||||
EditorTheme: string;
|
||||
|
||||
/**
|
||||
* The CSS background theme color to apply across the game.
|
||||
*/
|
||||
ThemeBackgroundColor: string;
|
||||
|
||||
/**
|
||||
* The CSS text theme color to apply across the game.
|
||||
*/
|
||||
ThemeFontColor: string;
|
||||
|
||||
/**
|
||||
* The CSS foreground theme color to apply across the game.
|
||||
*/
|
||||
ThemeHighlightColor: string;
|
||||
}
|
||||
|
||||
const defaultSettings: IDefaultSettings = {
|
||||
AutosaveInterval: 60,
|
||||
CodeInstructionRunTime: 50,
|
||||
DisableHotkeys: false,
|
||||
MaxLogCapacity: 50,
|
||||
MaxPortCapacity: 50,
|
||||
SuppressBuyAugmentationConfirmation: false,
|
||||
SuppressFactionInvites: false,
|
||||
SuppressHospitalizationPopup: false,
|
||||
SuppressMessages: false,
|
||||
SuppressTravelConfirmation: false,
|
||||
};
|
||||
|
||||
/**
|
||||
* The current options the player has customized to their play style.
|
||||
*/
|
||||
// tslint:disable-next-line:variable-name
|
||||
export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
||||
AutosaveInterval: defaultSettings.AutosaveInterval,
|
||||
CodeInstructionRunTime: 25,
|
||||
DisableHotkeys: defaultSettings.DisableHotkeys,
|
||||
EditorKeybinding: "ace",
|
||||
EditorTheme: "Monokai",
|
||||
MaxLogCapacity: defaultSettings.MaxLogCapacity,
|
||||
MaxPortCapacity: defaultSettings.MaxPortCapacity,
|
||||
SuppressBuyAugmentationConfirmation: defaultSettings.SuppressBuyAugmentationConfirmation,
|
||||
SuppressFactionInvites: defaultSettings.SuppressFactionInvites,
|
||||
SuppressHospitalizationPopup: defaultSettings.SuppressHospitalizationPopup,
|
||||
SuppressMessages: defaultSettings.SuppressMessages,
|
||||
SuppressTravelConfirmation: defaultSettings.SuppressTravelConfirmation,
|
||||
ThemeBackgroundColor: "#000000",
|
||||
ThemeFontColor: "#66ff33",
|
||||
ThemeHighlightColor: "#ffffff",
|
||||
init() {
|
||||
Object.assign(Settings, defaultSettings);
|
||||
},
|
||||
load(saveString: string) {
|
||||
Object.assign(Settings, JSON.parse(saveString));
|
||||
},
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
import {Player} from "./Player";
|
||||
import {BitNode, BitNodes} from "./BitNode";
|
||||
import {BitNodes} from "./BitNode";
|
||||
|
||||
/* SourceFile.js */
|
||||
//Each SourceFile corresponds to a BitNode with the same number
|
||||
|
342
src/StockMarket.js
Normal file → Executable file
342
src/StockMarket.js
Normal file → Executable file
@ -1,6 +1,5 @@
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Engine} from "./engine";
|
||||
import {Locations} from "./Location";
|
||||
import {Locations} from "./Locations";
|
||||
import {hasWallStreetSF, wallStreetSFLvl} from "./NetscriptFunctions";
|
||||
import {WorkerScript} from "./NetscriptWorker";
|
||||
import {Player} from "./Player";
|
||||
@ -9,9 +8,13 @@ import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";
|
||||
import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver";
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
import numeral from "numeral/min/numeral.min";
|
||||
import {formatNumber} from "../utils/StringHelperFunctions";
|
||||
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
|
||||
import {getRandomInt} from "../utils/helpers/getRandomInt";
|
||||
import {KEY} from "../utils/helpers/keyCodes";
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
import {removeElementById} from "../utils/uiHelpers/removeElementById";
|
||||
import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
|
||||
yesNoBoxGetYesButton, yesNoBoxGetNoButton,
|
||||
@ -410,6 +413,7 @@ function stockMarketCycle() {
|
||||
for (var name in StockMarket) {
|
||||
if (StockMarket.hasOwnProperty(name)) {
|
||||
var stock = StockMarket[name];
|
||||
if (!(stock instanceof Stock)) {continue;}
|
||||
var thresh = 0.6;
|
||||
if (stock.b) {thresh = 0.4;}
|
||||
if (Math.random() < thresh) {
|
||||
@ -430,8 +434,8 @@ function buyStock(stock, shares) {
|
||||
|
||||
var totalPrice = stock.price * shares;
|
||||
if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) {
|
||||
dialogBoxCreate("You do not have enough money to purchase this. You need $" +
|
||||
formatNumber(totalPrice + CONSTANTS.StockMarketCommission, 2).toString() + ".");
|
||||
dialogBoxCreate("You do not have enough money to purchase this. You need " +
|
||||
numeral(totalPrice + CONSTANTS.StockMarketCommission).format('($0.000a)') + ".");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -441,9 +445,9 @@ function buyStock(stock, shares) {
|
||||
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.");
|
||||
dialogBoxCreate("Bought " + numeral(shares).format('0,0') + " shares of " + stock.symbol + " at " +
|
||||
numeral(stock.price).format('($0.000a)') + " per share. Paid " +
|
||||
numeral(CONSTANTS.StockMarketCommission).format('($0.000a)') + " in commission fees.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -464,9 +468,9 @@ function sellStock(stock, shares) {
|
||||
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));
|
||||
dialogBoxCreate("Sold " + numeral(shares).format('0,0') + " shares of " + stock.symbol + " at " +
|
||||
numeral(stock.price).format('($0.000a)') + " per share. After commissions, you gained " +
|
||||
"a total of " + numeral(gains).format('($0.000a)') + ".");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -488,12 +492,12 @@ function shortStock(stock, shares, workerScript=null) {
|
||||
var totalPrice = stock.price * shares;
|
||||
if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) {
|
||||
if (tixApi) {
|
||||
workerScript.scriptRef.log("ERROR: shortStock() failed because you do not have " +
|
||||
workerScript.scriptRef.log("ERROR: shortStock() failed because you do not have enough " +
|
||||
"money to purchase this short position. You need " +
|
||||
numeral(totalPrice + CONSTANTS.StockMarketCommission).format('($0.000a)'));
|
||||
numeral(totalPrice + CONSTANTS.StockMarketCommission).format('($0.000a)') + ".");
|
||||
} else {
|
||||
dialogBoxCreate("You do not have enough money to purchase this short position. You need $" +
|
||||
formatNumber(totalPrice + CONSTANTS.StockMarketCommission, 2) + ".");
|
||||
dialogBoxCreate("You do not have enough money to purchase this short position. You need " +
|
||||
numeral(totalPrice + CONSTANTS.StockMarketCommission).format('($0.000a)') + ".");
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -507,14 +511,14 @@ function shortStock(stock, shares, workerScript=null) {
|
||||
updateStockPlayerPosition(stock);
|
||||
if (tixApi) {
|
||||
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.shortStock == null) {
|
||||
workerScript.scriptRef.log("Bought a short position of " + formatNumber(shares, 0) + " shares of " + stock.symbol + " at " +
|
||||
workerScript.scriptRef.log("Bought a short position of " + numeral(shares).format('0,0') + " shares of " + stock.symbol + " at " +
|
||||
numeral(stock.price).format('($0.000a)') + " per share. Paid " +
|
||||
numeral(CONSTANTS.StockMarketCommission).format('($0.000a)') + " in commission fees.");
|
||||
}
|
||||
} else {
|
||||
dialogBoxCreate("Bought a short position of " + formatNumber(shares, 0) + " shares of " + stock.symbol + " at $" +
|
||||
formatNumber(stock.price, 2) + " per share. You also paid $" +
|
||||
formatNumber(CONSTANTS.StockMarketCommission, 2) + " in commission fees.");
|
||||
dialogBoxCreate("Bought a short position of " + numeral(shares).format('0,0') + " shares of " + stock.symbol + " at " +
|
||||
numeral(stock.price).format('($0.000a)') + " per share. Paid " +
|
||||
numeral(CONSTANTS.StockMarketCommission).format('($0.000a)') + " in commission fees.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -551,14 +555,14 @@ function sellShort(stock, shares, workerScript=null) {
|
||||
updateStockPlayerPosition(stock);
|
||||
if (tixApi) {
|
||||
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.sellShort == null) {
|
||||
workerScript.scriptRef.log("Sold your short position of " + shares + " shares of " + stock.symbol + " at " +
|
||||
workerScript.scriptRef.log("Sold your short position of " + numeral(shares).format('0,0') + " shares of " + stock.symbol + " at " +
|
||||
numeral(stock.price).format('($0.000a)') + " per share. After commissions, you gained " +
|
||||
"a total of " + numeral(origCost + profit).format('($0.000a)'));
|
||||
"a total of " + numeral(origCost + profit).format('($0.000a)') + ".");
|
||||
}
|
||||
} else {
|
||||
dialogBoxCreate("Sold your short position of " + formatNumber(shares, 0) + " shares of " + stock.symbol + " at $" +
|
||||
formatNumber(stock.price, 2) + " per share. After commissions, you gained " +
|
||||
"a total of $" + formatNumber(origCost + profit, 2));
|
||||
dialogBoxCreate("Sold your short position of " + numeral(shares).format('0,0') + " shares of " + stock.symbol + " at " +
|
||||
numeral(stock.price).format('($0.000a)') + " per share. After commissions, you gained " +
|
||||
"a total of " + numeral(origCost + profit).format('($0.000a)') + ".");
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -593,7 +597,7 @@ function updateStockPrices() {
|
||||
processOrders(stock, OrderTypes.LimitSell, PositionTypes.Long);
|
||||
processOrders(stock, OrderTypes.StopBuy, PositionTypes.Long);
|
||||
processOrders(stock, OrderTypes.StopSell, PositionTypes.Short);
|
||||
if (Engine.currentPage == Engine.Page.StockMarket) {
|
||||
if (routing.isOn(Page.StockMarket)) {
|
||||
updateStockTicker(stock, true);
|
||||
}
|
||||
} else {
|
||||
@ -602,7 +606,7 @@ function updateStockPrices() {
|
||||
processOrders(stock, OrderTypes.LimitSell, PositionTypes.Short);
|
||||
processOrders(stock, OrderTypes.StopBuy, PositionTypes.Short);
|
||||
processOrders(stock, OrderTypes.StopSell, PositionTypes.Long);
|
||||
if (Engine.currentPage == Engine.Page.StockMarket) {
|
||||
if (routing.isOn(Page.StockMarket)) {
|
||||
updateStockTicker(stock, false);
|
||||
}
|
||||
}
|
||||
@ -694,20 +698,31 @@ var stockMarketContentCreated = false;
|
||||
var stockMarketPortfolioMode = false;
|
||||
var COMM = CONSTANTS.StockMarketCommission;
|
||||
function displayStockMarketContent() {
|
||||
if (Player.hasWseAccount == null) {Player.hasWseAccount = false;}
|
||||
if (Player.hasWseAccount == null) {Player.hasWseAccount = false;}
|
||||
if (Player.hasTixApiAccess == null) {Player.hasTixApiAccess = false;}
|
||||
if (Player.has4SData == null) {Player.has4SData = false;}
|
||||
if (Player.has4SDataTixApi == null) {Player.has4SDataTixApi = false;}
|
||||
|
||||
function stylePurchaseButton(btn, cost, flag, initMsg, purchasedMsg) {
|
||||
btn.innerText = initMsg;
|
||||
btn.classList.remove("a-link-button");
|
||||
btn.classList.remove("a-link-button-bought");
|
||||
btn.classList.remove("a-link-button-inactive");
|
||||
if (!flag && Player.money.gte(cost)) {
|
||||
btn.classList.add("a-link-button");
|
||||
} else if (flag) {
|
||||
btn.innerText = purchasedMsg;
|
||||
btn.classList.add("a-link-button-bought");
|
||||
} else {
|
||||
btn.classList.add("a-link-button-inactive");
|
||||
}
|
||||
}
|
||||
|
||||
//Purchase WSE Account button
|
||||
var wseAccountButton = clearEventListeners("stock-market-buy-account");
|
||||
wseAccountButton.innerText = "Buy WSE Account - $" + formatNumber(CONSTANTS.WSEAccountCost, 2).toString();
|
||||
if (!Player.hasWseAccount && Player.money.gte(CONSTANTS.WSEAccountCost)) {
|
||||
wseAccountButton.setAttribute("class", "a-link-button");
|
||||
} else if (Player.hasWseAccount){
|
||||
wseAccountButton.innerText = "WSE Account - Purchased";
|
||||
wseAccountButton.setAttribute("class", "a-link-button-bought");
|
||||
} else {
|
||||
wseAccountButton.setAttribute("class", "a-link-button-inactive");
|
||||
}
|
||||
stylePurchaseButton(wseAccountButton, CONSTANTS.WSEAccountCost, Player.hasWseAccount,
|
||||
"Buy WSE Account - " + numeral(CONSTANTS.WSEAccountCost).format('($0.000a)'),
|
||||
"WSE Account - Purchased");
|
||||
wseAccountButton.addEventListener("click", function() {
|
||||
Player.hasWseAccount = true;
|
||||
initStockMarket();
|
||||
@ -719,16 +734,9 @@ function displayStockMarketContent() {
|
||||
|
||||
//Purchase TIX API Access account
|
||||
var tixApiAccessButton = clearEventListeners("stock-market-buy-tix-api");
|
||||
tixApiAccessButton.innerText = "Buy Trade Information eXchange (TIX) API Access - $" +
|
||||
formatNumber(CONSTANTS.TIXAPICost, 2).toString();
|
||||
if (!Player.hasTixApiAccess && Player.money.gte(CONSTANTS.TIXAPICost)) {
|
||||
tixApiAccessButton.setAttribute("class", "a-link-button");
|
||||
} else if(Player.hasTixApiAccess) {
|
||||
tixApiAccessButton.innerText = "Trade Information eXchange (TIX) API Access - Purchased"
|
||||
tixApiAccessButton.setAttribute("class", "a-link-button-bought");
|
||||
} else {
|
||||
tixApiAccessButton.setAttribute("class", "a-link-button-inactive");
|
||||
}
|
||||
stylePurchaseButton(tixApiAccessButton, CONSTANTS.TIXAPICost, Player.hasTixApiAccess,
|
||||
"Buy Trade Information eXchange (TIX) API Access - " + numeral(CONSTANTS.TIXAPICost).format('($0.000a)'),
|
||||
"TIX API Access - Purchased");
|
||||
tixApiAccessButton.addEventListener("click", function() {
|
||||
Player.hasTixApiAccess = true;
|
||||
Player.loseMoney(CONSTANTS.TIXAPICost);
|
||||
@ -736,23 +744,111 @@ function displayStockMarketContent() {
|
||||
return false;
|
||||
});
|
||||
|
||||
//Purchase Four Sigma Market Data Feed
|
||||
var marketDataButton = clearEventListeners("stock-market-buy-4s-data");
|
||||
stylePurchaseButton(marketDataButton, CONSTANTS.MarketData4SCost, Player.has4SData,
|
||||
"Buy 4S Market Data Access - " + numeral(CONSTANTS.MarketData4SCost).format('($0.000a)'),
|
||||
"4S Market Data - Purchased");
|
||||
marketDataButton.addEventListener("click", function() {
|
||||
Player.has4SData = true;
|
||||
Player.loseMoney(CONSTANTS.MarketData4SCost);
|
||||
displayStockMarketContent();
|
||||
return false;
|
||||
});
|
||||
marketDataButton.appendChild(createElement("span", {
|
||||
class:"tooltiptext",
|
||||
innerText:"Lets you view additional pricing and volatility information about stocks"
|
||||
}));
|
||||
marketDataButton.style.marginRight = "2px"; //Adjusts following help tip to be slightly closer
|
||||
|
||||
//4S Market Data Help Tip
|
||||
var marketDataHelpTip = clearEventListeners("stock-market-4s-data-help-tip");
|
||||
marketDataHelpTip.style.marginTop = "10px";
|
||||
marketDataHelpTip.addEventListener("click", ()=>{
|
||||
dialogBoxCreate("Access to the 4S Market Data feed will display two additional pieces " +
|
||||
"of information about each stock: Price Forecast & Volatility<br><br>" +
|
||||
"Price Forecast indicates the probability the stock has of increasing or " +
|
||||
"decreasing. A '+' forecast means the stock has a higher chance of increasing " +
|
||||
"than decreasing, and a '-' means the opposite. The number of '+/-' symbols " +
|
||||
"is used to illustrate the magnitude of these probabilities. For example, " +
|
||||
"'+++' means that the stock has a significantly higher chance of increasing " +
|
||||
"than decreasing, while '+' means that the stock only has a slightly higher chance " +
|
||||
"of increasing than decreasing.<br><br>" +
|
||||
"Volatility represents the maximum percentage by which a stock's price " +
|
||||
"can change every tick (a tick occurs every few seconds while the game " +
|
||||
"is running).<br><br>" +
|
||||
"A stock's price forecast can change over time. This is also affected by volatility. " +
|
||||
"The more volatile a stock is, the more its price forecast will change.");
|
||||
return false;
|
||||
});
|
||||
|
||||
//Purchase Four Sigma Market Data TIX API (Requires TIX API Access)
|
||||
var marketDataTixButton = clearEventListeners("stock-market-buy-4s-tix-api");
|
||||
stylePurchaseButton(marketDataTixButton, CONSTANTS.MarketDataTixApi4SCost, Player.has4SDataTixApi,
|
||||
"Buy 4S Market Data TIX API Access - " + numeral(CONSTANTS.MarketDataTixApi4SCost).format('($0.000a)'),
|
||||
"4S Market Data TIX API - Purchased");
|
||||
if (Player.hasTixApiAccess) {
|
||||
marketDataTixButton.addEventListener("click", function() {
|
||||
Player.has4SDataTixApi = true;
|
||||
Player.loseMoney(CONSTANTS.MarketDataTixApi4SCost);
|
||||
displayStockMarketContent();
|
||||
return false;
|
||||
});
|
||||
marketDataTixButton.appendChild(createElement("span", {
|
||||
class:"tooltiptext",
|
||||
innerText:"Lets you access 4S Market Data through Netscript"
|
||||
}));
|
||||
} else {
|
||||
marketDataTixButton.classList.remove("a-link-button");
|
||||
marketDataTixButton.classList.remove("a-link-button-bought");
|
||||
marketDataTixButton.classList.remove("a-link-button-inactive");
|
||||
marketDataTixButton.classList.add("a-link-button-inactive");
|
||||
marketDataTixButton.appendChild(createElement("span", {
|
||||
class:"tooltiptext",
|
||||
innerText:"Requires TIX API Access"
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
var stockList = document.getElementById("stock-market-list");
|
||||
if (stockList == null) {return;}
|
||||
|
||||
//UI Elements that should only appear if you have WSE account access
|
||||
var commissionText = document.getElementById("stock-market-commission");
|
||||
var modeBtn = document.getElementById("stock-market-mode");
|
||||
var expandBtn = document.getElementById("stock-market-expand-tickers");
|
||||
var collapseBtn = document.getElementById("stock-market-collapse-tickers");
|
||||
var watchlistFilter = document.getElementById("stock-market-watchlist-filter");
|
||||
var watchlistUpdateBtn = document.getElementById("stock-market-watchlist-filter-update");
|
||||
|
||||
//If Player doesn't have account, clear stocks UI and return
|
||||
if (!Player.hasWseAccount) {
|
||||
stockMarketContentCreated = false;
|
||||
while (stockList.firstChild) {
|
||||
stockList.removeChild(stockList.firstChild);
|
||||
}
|
||||
commissionText.style.visibility = "hidden";
|
||||
modeBtn.style.visibility = "hidden";
|
||||
expandBtn.style.visibility = "hidden";
|
||||
collapseBtn.style.visibility = "hidden";
|
||||
watchlistFilter.style.visibility = "hidden";
|
||||
watchlistUpdateBtn.style.visibility = "hidden";
|
||||
return;
|
||||
} else {
|
||||
commissionText.style.visibility = "visible";
|
||||
modeBtn.style.visibility = "visible";
|
||||
expandBtn.style.visibility = "visible";
|
||||
collapseBtn.style.visibility = "visible";
|
||||
watchlistFilter.style.visibility = "visible";
|
||||
watchlistUpdateBtn.style.visibility = "visible";
|
||||
}
|
||||
|
||||
//Create stock market content if you have an account
|
||||
if (!stockMarketContentCreated && Player.hasWseAccount) {
|
||||
console.log("Creating Stock Market UI");
|
||||
document.getElementById("stock-market-commission").innerHTML =
|
||||
"Commission Fees: Every transaction you make has a $" +
|
||||
formatNumber(CONSTANTS.StockMarketCommission, 2) + " commission fee.<br><br>" +
|
||||
commissionText.innerHTML =
|
||||
"Commission Fees: Every transaction you make has a " +
|
||||
numeral(CONSTANTS.StockMarketCommission).format('($0.000a)') + " 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!";
|
||||
@ -803,7 +899,6 @@ function displayStockMarketContent() {
|
||||
});
|
||||
|
||||
//Switch to Portfolio Mode Button
|
||||
var modeBtn = clearEventListeners("stock-market-mode");
|
||||
if (modeBtn) {
|
||||
modeBtn.innerHTML = "Switch to 'Portfolio' Mode" +
|
||||
"<span class='tooltiptext'>Displays only the stocks for which you have shares or orders</span>";
|
||||
@ -811,9 +906,7 @@ function displayStockMarketContent() {
|
||||
}
|
||||
|
||||
//Expand/Collapse tickers buttons
|
||||
var expandBtn = clearEventListeners("stock-market-expand-tickers"),
|
||||
collapseBtn = clearEventListeners("stock-market-collapse-tickers"),
|
||||
stockList = document.getElementById("stock-market-list");
|
||||
var stockList = document.getElementById("stock-market-list");
|
||||
if (expandBtn) {
|
||||
expandBtn.addEventListener("click", ()=>{
|
||||
var tickerHdrs = stockList.getElementsByClassName("accordion-header");
|
||||
@ -835,14 +928,30 @@ function displayStockMarketContent() {
|
||||
});
|
||||
}
|
||||
|
||||
for (var name in StockMarket) {
|
||||
if (StockMarket.hasOwnProperty(name)) {
|
||||
var stock = StockMarket[name];
|
||||
if (!(stock instanceof Stock)) {continue;} //orders property is an array
|
||||
createStockTicker(stock);
|
||||
//Watchlish filter
|
||||
if (watchlistFilter && watchlistUpdateBtn) {
|
||||
//Initialize value in watchlist
|
||||
if (StockMarket.watchlistFilter) {
|
||||
watchlistFilter.value = StockMarket.watchlistFilter; //Remove whitespace
|
||||
}
|
||||
watchlistUpdateBtn.addEventListener("click", ()=> {
|
||||
let filterValue = watchlistFilter.value.toString();
|
||||
StockMarket.watchlistFilter = filterValue.replace(/\s/g, '');
|
||||
if (stockMarketPortfolioMode) {
|
||||
switchToPortfolioMode();
|
||||
} else {
|
||||
switchToDisplayAllMode();
|
||||
}
|
||||
});
|
||||
watchlistFilter.addEventListener("keyup", (e)=>{
|
||||
e.preventDefault();
|
||||
if (e.keyCode === KEY.ENTER) {watchlistUpdateBtn.click();}
|
||||
})
|
||||
} else {
|
||||
console.warn("Stock Market Watchlist DOM elements could not be found");
|
||||
}
|
||||
setStockTickerClickHandlers(); //Clicking headers opens/closes panels
|
||||
|
||||
createAllStockTickers();
|
||||
stockMarketContentCreated = true;
|
||||
}
|
||||
|
||||
@ -850,8 +959,10 @@ function displayStockMarketContent() {
|
||||
for (var name in StockMarket) {
|
||||
if (StockMarket.hasOwnProperty(name)) {
|
||||
var stock = StockMarket[name];
|
||||
updateStockTicker(stock, null);
|
||||
updateStockOrderList(stock);
|
||||
if (stock instanceof Stock) {
|
||||
updateStockTicker(stock, null);
|
||||
updateStockOrderList(stock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -860,17 +971,34 @@ function displayStockMarketContent() {
|
||||
//Displays only stocks you have position/order in
|
||||
function switchToPortfolioMode() {
|
||||
stockMarketPortfolioMode = true;
|
||||
var stockList = document.getElementById("stock-market-list");
|
||||
if (stockList == null) {return;}
|
||||
var modeBtn = clearEventListeners("stock-market-mode");
|
||||
if (modeBtn) {
|
||||
modeBtn.innerHTML = "Switch to 'All stocks' Mode" +
|
||||
"<span class='tooltiptext'>Displays all stocks on the WSE</span>";
|
||||
modeBtn.addEventListener("click", switchToDisplayAllMode);
|
||||
}
|
||||
while(stockList.firstChild) {stockList.removeChild(stockList.firstChild);}
|
||||
createAllStockTickers();
|
||||
}
|
||||
|
||||
//Displays all stocks
|
||||
function switchToDisplayAllMode() {
|
||||
stockMarketPortfolioMode = false;
|
||||
var modeBtn = clearEventListeners("stock-market-mode");
|
||||
if (modeBtn) {
|
||||
modeBtn.innerHTML = "Switch to 'Portfolio' Mode" +
|
||||
"<span class='tooltiptext'>Displays only the stocks for which you have shares or orders</span>";
|
||||
modeBtn.addEventListener("click", switchToPortfolioMode);
|
||||
}
|
||||
createAllStockTickers();
|
||||
}
|
||||
|
||||
function createAllStockTickers() {
|
||||
var stockList = document.getElementById("stock-market-list");
|
||||
if (stockList == null) {
|
||||
exceptionAlert("Error creating Stock Tickers UI. DOM element with ID 'stock-market-list' could not be found");
|
||||
}
|
||||
removeChildrenFromElement(stockList);
|
||||
|
||||
//Get Order book (create it if it hasn't been created)
|
||||
var orderBook = StockMarket["Orders"];
|
||||
if (orderBook == null) {
|
||||
var orders = {};
|
||||
@ -882,41 +1010,30 @@ function switchToPortfolioMode() {
|
||||
}
|
||||
}
|
||||
StockMarket["Orders"] = orders;
|
||||
orderBook = StockMarket["Orders"];
|
||||
}
|
||||
|
||||
let watchlist = null;
|
||||
if (StockMarket.watchlistFilter != null && StockMarket.watchlistFilter !== "") {
|
||||
let filter = StockMarket.watchlistFilter.replace(/\s/g, '');
|
||||
watchlist = filter.split(",");
|
||||
}
|
||||
|
||||
for (var name in StockMarket) {
|
||||
if (StockMarket.hasOwnProperty(name)) {
|
||||
var stock = StockMarket[name];
|
||||
if (!(stock instanceof Stock)) {continue;} //orders property is an array
|
||||
var stockOrders = orderBook[stock.symbol];
|
||||
if (stock.playerShares === 0 && stock.playerShortShares === 0 &&
|
||||
stockOrders.length === 0) {continue;}
|
||||
createStockTicker(stock);
|
||||
}
|
||||
}
|
||||
setStockTickerClickHandlers();
|
||||
}
|
||||
if (watchlist && !watchlist.includes(stock.symbol)) {continue;} //Watchlist filtering
|
||||
|
||||
//Displays all stocks
|
||||
function switchToDisplayAllMode() {
|
||||
stockMarketPortfolioMode = false;
|
||||
var stockList = document.getElementById("stock-market-list");
|
||||
if (stockList == null) {return;}
|
||||
var modeBtn = clearEventListeners("stock-market-mode");
|
||||
if (modeBtn) {
|
||||
modeBtn.innerHTML = "Switch to 'Portfolio' Mode" +
|
||||
"<span class='tooltiptext'>Displays only the stocks for which you have shares or orders</span>";
|
||||
modeBtn.addEventListener("click", switchToPortfolioMode);
|
||||
}
|
||||
while(stockList.firstChild) {stockList.removeChild(stockList.firstChild);}
|
||||
for (var name in StockMarket) {
|
||||
if (StockMarket.hasOwnProperty(name)) {
|
||||
var stock = StockMarket[name];
|
||||
if (!(stock instanceof Stock)) {continue;} //orders property is an array
|
||||
let stockOrders = orderBook[stock.symbol];
|
||||
if (stockMarketPortfolioMode) {
|
||||
if (stock.playerShares === 0 && stock.playerShortShares === 0 &&
|
||||
stockOrders.length === 0) {continue;}
|
||||
}
|
||||
createStockTicker(stock);
|
||||
}
|
||||
}
|
||||
setStockTickerClickHandlers();
|
||||
setStockTickerClickHandlers(); //Clicking headers opens/closes panels
|
||||
}
|
||||
|
||||
function createStockTicker(stock) {
|
||||
@ -928,7 +1045,7 @@ function createStockTicker(stock) {
|
||||
var li = document.createElement("li"), hdr = document.createElement("button");
|
||||
hdr.classList.add("accordion-header");
|
||||
hdr.setAttribute("id", tickerId + "-hdr");
|
||||
hdr.innerHTML = stock.name + " - " + stock.symbol + " - $" + stock.price;
|
||||
hdr.innerHTML = stock.name + " - " + stock.symbol + " - " + numeral(stock.price).format('($0.000a)');
|
||||
|
||||
//Div for entire panel
|
||||
var stockDiv = document.createElement("div");
|
||||
@ -1182,7 +1299,7 @@ function setStockTickerClickHandlers() {
|
||||
|
||||
//'increase' argument is a boolean indicating whether the price increased or decreased
|
||||
function updateStockTicker(stock, increase) {
|
||||
if (Engine.currentPage !== Engine.Page.StockMarket) {return;}
|
||||
if (!routing.isOn(Page.StockMarket)) {return;}
|
||||
if (!(stock instanceof Stock)) {
|
||||
console.log("Invalid stock in updateStockTicker():");
|
||||
console.log(stock);
|
||||
@ -1197,17 +1314,32 @@ function updateStockTicker(stock, increase) {
|
||||
var hdr = document.getElementById(tickerId + "-hdr");
|
||||
|
||||
if (hdr == null) {
|
||||
if (!stockMarketPortfolioMode) {console.log("ERROR: Couldn't find ticker element for stock: " + stock.symbol);}
|
||||
if (!stockMarketPortfolioMode) {
|
||||
let watchlist = StockMarket.watchlistFilter;
|
||||
if (watchlist !== "" && watchlist.includes(stock.symbol)) {
|
||||
console.log("ERROR: Couldn't find ticker element for stock: " + stock.symbol);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
hdr.innerHTML = stock.name + " - " + stock.symbol + " - $" + formatNumber(stock.price, 2);
|
||||
let hdrText = stock.name + " (" + stock.symbol + ") - " + numeral(stock.price).format('($0.000a)');
|
||||
if (Player.has4SData) {
|
||||
hdrText += " - Volatility: " + numeral(stock.mv).format('0,0.00') + "%" +
|
||||
" - Price Forecast: ";
|
||||
if (stock.b) {
|
||||
hdrText += "+".repeat(Math.floor(stock.otlkMag/10) + 1);
|
||||
} else {
|
||||
hdrText += "-".repeat(Math.floor(stock.otlkMag/10) + 1);
|
||||
}
|
||||
}
|
||||
hdr.innerText = hdrText;
|
||||
if (increase != null) {
|
||||
increase ? hdr.style.color = "#66ff33" : hdr.style.color = "red";
|
||||
}
|
||||
}
|
||||
|
||||
function updateStockPlayerPosition(stock) {
|
||||
if (Engine.currentPage !== Engine.Page.StockMarket) {return;}
|
||||
if (!routing.isOn(Page.StockMarket)) {return;}
|
||||
if (!(stock instanceof Stock)) {
|
||||
console.log("Invalid stock in updateStockPlayerPosition():");
|
||||
console.log(stock);
|
||||
@ -1256,32 +1388,38 @@ function updateStockPlayerPosition(stock) {
|
||||
"<h1 class='tooltip stock-market-position-text'>Long Position: " +
|
||||
"<span class='tooltiptext'>Shares in the long position will increase " +
|
||||
"in value if the price of the corresponding stock increases</span></h1>" +
|
||||
"<br>Shares: " + formatNumber(stock.playerShares, 0) +
|
||||
"<br>Shares: " + numeral(stock.playerShares).format('0,0') +
|
||||
"<br>Average Price: " + numeral(stock.playerAvgPx).format('$0.000a') +
|
||||
" (Total Cost: " + numeral(totalCost).format('$0.000a') + ")" +
|
||||
"<br>Profit: " + numeral(gains).format('$0.000a') +
|
||||
" (" + formatNumber(percentageGains*100, 2) + "%)<br><br>";
|
||||
" (" + numeral(percentageGains).format('0.00%') + ")<br><br>";
|
||||
if (Player.bitNodeN === 8 || (hasWallStreetSF && wallStreetSFLvl >= 2)) {
|
||||
stock.posTxtEl.innerHTML +=
|
||||
"<h1 class='tooltip stock-market-position-text'>Short Position: " +
|
||||
"<span class='tooltiptext'>Shares in short position will increase " +
|
||||
"in value if the price of the corresponding stock decreases</span></h1>" +
|
||||
"<br>Shares: " + formatNumber(stock.playerShortShares, 0) +
|
||||
"<br>Shares: " + numeral(stock.playerShortShares).format('0,0') +
|
||||
"<br>Average Price: " + numeral(stock.playerAvgShortPx).format('$0.000a') +
|
||||
" (Total Cost: " + numeral(shortTotalCost).format('$0.000a') + ")" +
|
||||
"<br>Profit: " + numeral(shortGains).format('$0.000a') +
|
||||
" (" + formatNumber(shortPercentageGains*100, 2) + "%)" +
|
||||
" (" + numeral(shortPercentageGains).format('0.00%') + ")" +
|
||||
"<br><br><h1 class='stock-market-position-text'>Orders: </h1>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function updateStockOrderList(stock) {
|
||||
if (Engine.currentPage !== Engine.Page.StockMarket) {return;}
|
||||
if (!routing.isOn(Page.StockMarket)) {return;}
|
||||
var tickerId = "stock-market-ticker-" + stock.symbol;
|
||||
var orderList = document.getElementById(tickerId + "-order-list");
|
||||
if (orderList == null) {
|
||||
if (!stockMarketPortfolioMode) {console.log("ERROR: Could not find order list for " + stock.symbol);}
|
||||
//Log only if its a valid error
|
||||
if (!stockMarketPortfolioMode) {
|
||||
let watchlist = StockMarket.watchlistFilter;
|
||||
if (watchlist !== "" && watchlist.includes(stock.symbol)) {
|
||||
console.log("ERROR: Could not find order list for " + stock.symbol);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1327,7 +1465,7 @@ function updateStockOrderList(stock) {
|
||||
var posText = (order.pos === PositionTypes.Long ? "Long Position" : "Short Position");
|
||||
li.style.color = "white";
|
||||
li.innerText = order.type + " - " + posText + " - " +
|
||||
order.shares + " @ $" + formatNumber(order.price, 2);
|
||||
order.shares + " @ " + numeral(order.price).format('($0.000a)');
|
||||
|
||||
var cancelButton = document.createElement("span");
|
||||
cancelButton.classList.add("stock-market-order-cancel-btn");
|
||||
|
120
src/Terminal.js
120
src/Terminal.js
@ -12,8 +12,7 @@ import {FconfSettings, parseFconfSettings,
|
||||
createFconf} from "./Fconf";
|
||||
import {TerminalHelpText, HelpTexts} from "./HelpText";
|
||||
import {iTutorialNextStep, iTutorialSteps,
|
||||
iTutorialIsRunning,
|
||||
currITutorialStep} from "./InteractiveTutorial";
|
||||
ITutorial} from "./InteractiveTutorial";
|
||||
import {showLiterature} from "./Literature";
|
||||
import {showMessage, Message} from "./Message";
|
||||
import {scriptCalculateHackingTime,
|
||||
@ -35,6 +34,8 @@ import {TextFile, getTextFile} from "./TextFile";
|
||||
|
||||
import {containsAllStrings, longestCommonStart,
|
||||
formatNumber} from "../utils/StringHelperFunctions";
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
import {KEY} from "../utils/helpers/keyCodes";
|
||||
import {addOffset} from "../utils/helpers/addOffset";
|
||||
import {isString} from "../utils/helpers/isString";
|
||||
import {arrayToString} from "../utils/helpers/arrayToString";
|
||||
@ -43,86 +44,40 @@ import {logBoxCreate} from "../utils/LogBox";
|
||||
import {yesNoBoxCreate,
|
||||
yesNoBoxGetYesButton,
|
||||
yesNoBoxGetNoButton, yesNoBoxClose} from "../utils/YesNoBox";
|
||||
import {post, hackProgressBarPost,
|
||||
hackProgressPost} from "./ui/postToTerminal";
|
||||
|
||||
import * as JSZip from 'jszip';
|
||||
import * as FileSaver from 'file-saver';
|
||||
|
||||
/* Write text to terminal */
|
||||
//If replace is true then spaces are replaced with " "
|
||||
function post(input) {
|
||||
$("#terminal-input").before('<tr class="posted"><td class="terminal-line" style="color: var(--my-font-color); background-color: var(--my-background-color); white-space:pre-wrap;">' + input + '</td></tr>');
|
||||
updateTerminalScroll();
|
||||
}
|
||||
|
||||
//Same thing as post but the td cells have ids so they can be animated for the hack progress bar
|
||||
function hackProgressBarPost(input) {
|
||||
$("#terminal-input").before('<tr class="posted"><td id="hack-progress-bar" style="color: var(--my-font-color); background-color: var(--my-background-color);">' + input + '</td></tr>');
|
||||
updateTerminalScroll();
|
||||
}
|
||||
|
||||
function hackProgressPost(input) {
|
||||
$("#terminal-input").before('<tr class="posted"><td id="hack-progress" style="color: var(--my-font-color); background-color: var(--my-background-color);">' + input + '</td></tr>');
|
||||
updateTerminalScroll();
|
||||
}
|
||||
|
||||
//Scroll to the bottom of the terminal's 'text area'
|
||||
function updateTerminalScroll() {
|
||||
var element = document.getElementById("terminal-container");
|
||||
element.scrollTop = element.scrollHeight;
|
||||
}
|
||||
|
||||
function postNetburnerText() {
|
||||
post("Bitburner v" + CONSTANTS.Version);
|
||||
}
|
||||
|
||||
|
||||
//Key Codes
|
||||
var KEY = {
|
||||
TAB: 9,
|
||||
ENTER: 13,
|
||||
CTRL: 17,
|
||||
UPARROW: 38,
|
||||
DOWNARROW: 40,
|
||||
A: 65,
|
||||
B: 66,
|
||||
C: 67,
|
||||
D: 68,
|
||||
E: 69,
|
||||
F: 70,
|
||||
H: 72,
|
||||
J: 74,
|
||||
K: 75,
|
||||
L: 76,
|
||||
M: 77,
|
||||
N: 78,
|
||||
O: 79,
|
||||
P: 80,
|
||||
R: 82,
|
||||
S: 83,
|
||||
U: 85,
|
||||
W: 87,
|
||||
}
|
||||
|
||||
//Defines key commands in terminal
|
||||
$(document).keydown(function(event) {
|
||||
//Terminal
|
||||
if (Engine.currentPage == Engine.Page.Terminal) {
|
||||
if (routing.isOn(Page.Terminal)) {
|
||||
var terminalInput = document.getElementById("terminal-input-text-box");
|
||||
if (terminalInput != null && !event.ctrlKey && !event.shiftKey) {terminalInput.focus();}
|
||||
|
||||
if (event.keyCode === KEY.ENTER) {
|
||||
event.preventDefault(); //Prevent newline from being entered in Script Editor
|
||||
var command = $('input[class=terminal-input]').val();
|
||||
if (command.length > 0) {
|
||||
post(
|
||||
"[" +
|
||||
(FconfSettings.ENABLE_TIMESTAMPS ? getTimestamp() + " " : "") +
|
||||
Player.getCurrentServer().hostname +
|
||||
" ~]> " + command
|
||||
);
|
||||
post(
|
||||
"[" +
|
||||
(FconfSettings.ENABLE_TIMESTAMPS ? getTimestamp() + " " : "") +
|
||||
Player.getCurrentServer().hostname +
|
||||
" ~]> " + command
|
||||
);
|
||||
|
||||
if (command.length > 0) {
|
||||
Terminal.resetTerminalInput(); //Clear input first
|
||||
Terminal.executeCommand(command);
|
||||
const commands = command.split(";");
|
||||
for(let i = 0; i < commands.length; i++) {
|
||||
if(commands[i].match(/^\s*$/)) { continue; }
|
||||
Terminal.executeCommand(commands[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,6 +153,12 @@ $(document).keydown(function(event) {
|
||||
if (terminalInput == null) {return;}
|
||||
var input = terminalInput.value;
|
||||
if (input == "") {return;}
|
||||
|
||||
const semiColonIndex = input.lastIndexOf(";");
|
||||
if(semiColonIndex !== -1) {
|
||||
input = input.slice(semiColonIndex+1);
|
||||
}
|
||||
|
||||
input = input.trim();
|
||||
input = input.replace(/\s\s+/g, ' ');
|
||||
|
||||
@ -277,13 +238,13 @@ $(document).keydown(function(event) {
|
||||
//Keep terminal in focus
|
||||
let terminalCtrlPressed = false, shiftKeyPressed = false;
|
||||
$(document).ready(function() {
|
||||
if (Engine.currentPage === Engine.Page.Terminal) {
|
||||
if (routing.isOn(Page.Terminal)) {
|
||||
$('.terminal-input').focus();
|
||||
}
|
||||
});
|
||||
$(document).keydown(function(e) {
|
||||
if (Engine.currentPage == Engine.Page.Terminal) {
|
||||
if (e.which == 17) {
|
||||
if (routing.isOn(Page.Terminal)) {
|
||||
if (e.which == KEY.CTRL) {
|
||||
terminalCtrlPressed = true;
|
||||
} else if (e.shiftKey) {
|
||||
shiftKeyPressed = true;
|
||||
@ -299,8 +260,8 @@ $(document).keydown(function(e) {
|
||||
}
|
||||
})
|
||||
$(document).keyup(function(e) {
|
||||
if (Engine.currentPage == Engine.Page.Terminal) {
|
||||
if (e.which == 17) {
|
||||
if (routing.isOn(Page.Terminal)) {
|
||||
if (e.which == KEY.CTRL) {
|
||||
terminalCtrlPressed = false;
|
||||
}
|
||||
if (e.shiftKey) {
|
||||
@ -350,7 +311,18 @@ function tabCompletion(command, arg, allPossibilities, index=0) {
|
||||
} else {
|
||||
val = command + " " + allPossibilities[0];
|
||||
}
|
||||
document.getElementById("terminal-input-text-box").value = val;
|
||||
|
||||
const textBox = document.getElementById("terminal-input-text-box");
|
||||
const oldValue = textBox.value;
|
||||
const semiColonIndex = oldValue.lastIndexOf(";");
|
||||
if(semiColonIndex === -1) {
|
||||
// no ; replace the whole thing.
|
||||
textBox.value = val;
|
||||
} else {
|
||||
// replace just after the last semicolon
|
||||
textBox.value = textBox.value.slice(0, semiColonIndex+1)+" "+val;
|
||||
}
|
||||
|
||||
document.getElementById("terminal-input-text-box").focus();
|
||||
} else {
|
||||
var longestStartSubstr = longestCommonStart(allPossibilities);
|
||||
@ -789,11 +761,11 @@ let Terminal = {
|
||||
if (commandArray.length == 0) {return;}
|
||||
|
||||
/****************** Interactive Tutorial Terminal Commands ******************/
|
||||
if (iTutorialIsRunning) {
|
||||
if (ITutorial.isRunning) {
|
||||
var foodnstuffServ = GetServerByHostname("foodnstuff");
|
||||
if (foodnstuffServ == null) {throw new Error("Could not get foodnstuff server"); return;}
|
||||
|
||||
switch(currITutorialStep) {
|
||||
switch(ITutorial.currStep) {
|
||||
case iTutorialSteps.TerminalHelp:
|
||||
if (commandArray[0] == "help") {
|
||||
post(TerminalHelpText);
|
||||
@ -1836,7 +1808,7 @@ let Terminal = {
|
||||
* @returns {void}
|
||||
*/
|
||||
/**
|
||||
* @type {Object.<string, ProgramHandler}
|
||||
* @type {Object.<string, ProgramHandler}
|
||||
*/
|
||||
const programHandlers = {};
|
||||
programHandlers[Programs.NukeProgram.name] = (server) => {
|
||||
@ -1885,7 +1857,7 @@ let Terminal = {
|
||||
server.openPortCount++;
|
||||
};
|
||||
programHandlers[Programs.HTTPWormProgram.name] = (server) => {
|
||||
if (serv.httpPortOpen) {
|
||||
if (server.httpPortOpen) {
|
||||
post("HTTP Port (80) is already open!");
|
||||
return;
|
||||
}
|
||||
@ -2084,4 +2056,4 @@ let Terminal = {
|
||||
}
|
||||
};
|
||||
|
||||
export {postNetburnerText, post, Terminal, KEY};
|
||||
export {postNetburnerText, Terminal};
|
||||
|
151
src/engine.js
151
src/engine.js
@ -33,8 +33,9 @@ import {displayFactionContent, joinFaction,
|
||||
processPassiveFactionRepGain, Factions,
|
||||
inviteToFaction, initFactions} from "./Faction";
|
||||
import {FconfSettings} from "./Fconf";
|
||||
import {Locations, displayLocationContent,
|
||||
import {displayLocationContent,
|
||||
initLocationButtons} from "./Location";
|
||||
import {Locations} from "./Locations";
|
||||
import {displayGangContent, updateGangContent,
|
||||
Gang} from "./Gang";
|
||||
import {displayHacknetNodesContent, processAllHacknetNodeEarnings,
|
||||
@ -55,7 +56,8 @@ import {saveObject, loadGame} from "./SaveObject";
|
||||
import {loadAllRunningScripts, scriptEditorInit,
|
||||
updateScriptEditorContent} from "./Script";
|
||||
import {AllServers, Server, initForeignServers} from "./Server";
|
||||
import {Settings, setSettingsLabels} from "./Settings";
|
||||
import {Settings} from "./Settings";
|
||||
import {setSettingsLabels} from "./ui/setSettingsLabels";
|
||||
import {initSourceFiles, SourceFiles,
|
||||
PlayerOwnedSourceFile} from "./SourceFile";
|
||||
import {SpecialServerIps, initSpecialServerIps} from "./SpecialServerIps";
|
||||
@ -64,7 +66,9 @@ import {StockMarket, StockSymbols,
|
||||
initSymbolToStockMap, stockMarketCycle,
|
||||
updateStockPrices,
|
||||
displayStockMarketContent} from "./StockMarket";
|
||||
import {Terminal, postNetburnerText, post, KEY} from "./Terminal";
|
||||
import {Terminal, postNetburnerText} from "./Terminal";
|
||||
import {KEY} from "../utils/helpers/keyCodes";
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
|
||||
// These should really be imported with the module that is presenting that UI, but because they very much depend on the
|
||||
// cascade order, we'll pull them all in here.
|
||||
@ -126,7 +130,7 @@ $(document).keydown(function(e) {
|
||||
Engine.loadCreateProgramContent();
|
||||
} else if (e.keyCode === KEY.F && e.altKey) {
|
||||
//Overriden by Fconf
|
||||
if (Engine.currentPage === Engine.Page.Terminal && FconfSettings.ENABLE_BASH_HOTKEYS) {
|
||||
if (routing.isOn(Page.Terminal) && FconfSettings.ENABLE_BASH_HOTKEYS) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
@ -149,6 +153,7 @@ $(document).keydown(function(e) {
|
||||
let Engine = {
|
||||
version: "",
|
||||
Debug: true,
|
||||
overview: new CharacterOverview(),
|
||||
|
||||
//Clickable objects
|
||||
Clickables: {
|
||||
@ -255,45 +260,15 @@ let Engine = {
|
||||
characterInfo: null,
|
||||
},
|
||||
|
||||
//Current page status
|
||||
Page: {
|
||||
Terminal: "Terminal",
|
||||
CharacterInfo: "CharacterInfo",
|
||||
ScriptEditor: "ScriptEditor",
|
||||
ActiveScripts: "ActiveScripts",
|
||||
HacknetNodes: "HacknetNodes",
|
||||
World: "World",
|
||||
CreateProgram: "CreateProgram",
|
||||
Factions: "Factions",
|
||||
Faction: "Faction",
|
||||
Augmentations: "Augmentations",
|
||||
Tutorial: "Tutorial",
|
||||
DevMenu: "Dev Menu",
|
||||
Location: "Location",
|
||||
workInProgress: "WorkInProgress",
|
||||
RedPill: "RedPill",
|
||||
CinematicText: "CinematicText",
|
||||
Infiltration: "Infiltration",
|
||||
StockMarket: "StockMarket",
|
||||
Gang: "Gang",
|
||||
Mission: "Mission",
|
||||
Corporation: "Corporation",
|
||||
Bladeburner: "Bladeburner",
|
||||
},
|
||||
currentPage: null,
|
||||
overview: new CharacterOverview(),
|
||||
|
||||
|
||||
//Time variables (milliseconds unix epoch time)
|
||||
_lastUpdate: new Date().getTime(),
|
||||
_idleSpeed: 200, //Speed (in ms) at which the main loop is updated
|
||||
|
||||
|
||||
/* Load content when a main menu button is clicked */
|
||||
loadTerminalContent: function() {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.terminalContent.style.display = "block";
|
||||
Engine.currentPage = Engine.Page.Terminal;
|
||||
routing.navigateTo(Page.Terminal);
|
||||
document.getElementById("terminal-menu-link").classList.add("active");
|
||||
},
|
||||
|
||||
@ -301,7 +276,7 @@ let Engine = {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.characterContent.style.display = "block";
|
||||
Engine.displayCharacterInfo();
|
||||
Engine.currentPage = Engine.Page.CharacterInfo;
|
||||
routing.navigateTo(Page.CharacterInfo);
|
||||
document.getElementById("stats-menu-link").classList.add("active");
|
||||
},
|
||||
|
||||
@ -315,7 +290,7 @@ let Engine = {
|
||||
}
|
||||
editor.focus();
|
||||
updateScriptEditorContent();
|
||||
Engine.currentPage = Engine.Page.ScriptEditor;
|
||||
routing.navigateTo(Page.ScriptEditor);
|
||||
document.getElementById("create-script-menu-link").classList.add("active");
|
||||
},
|
||||
|
||||
@ -323,7 +298,7 @@ let Engine = {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.activeScriptsContent.style.display = "block";
|
||||
updateActiveScriptsItems();
|
||||
Engine.currentPage = Engine.Page.ActiveScripts;
|
||||
routing.navigateTo(Page.ActiveScripts);
|
||||
document.getElementById("active-scripts-menu-link").classList.add("active");
|
||||
},
|
||||
|
||||
@ -331,7 +306,7 @@ let Engine = {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.hacknetNodesContent.style.display = "block";
|
||||
displayHacknetNodesContent();
|
||||
Engine.currentPage = Engine.Page.HacknetNodes;
|
||||
routing.navigateTo(Page.HacknetNodes);
|
||||
document.getElementById("hacknet-nodes-menu-link").classList.add("active");
|
||||
},
|
||||
|
||||
@ -339,7 +314,7 @@ let Engine = {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.worldContent.style.display = "block";
|
||||
Engine.displayWorldInfo();
|
||||
Engine.currentPage = Engine.Page.World;
|
||||
routing.navigateTo(Page.World);
|
||||
document.getElementById("city-menu-link").classList.add("active");
|
||||
},
|
||||
|
||||
@ -347,7 +322,7 @@ let Engine = {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.createProgramContent.style.display = "block";
|
||||
displayCreateProgramContent();
|
||||
Engine.currentPage = Engine.Page.CreateProgram;
|
||||
routing.navigateTo(Page.CreateProgram);
|
||||
document.getElementById("create-program-menu-link").classList.add("active");
|
||||
},
|
||||
|
||||
@ -355,21 +330,21 @@ let Engine = {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.factionsContent.style.display = "block";
|
||||
Engine.displayFactionsInfo();
|
||||
Engine.currentPage = Engine.Page.Factions;
|
||||
routing.navigateTo(Page.Factions);
|
||||
document.getElementById("factions-menu-link").classList.add("active");
|
||||
},
|
||||
|
||||
loadFactionContent: function() {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.factionContent.style.display = "block";
|
||||
Engine.currentPage = Engine.Page.Faction;
|
||||
routing.navigateTo(Page.Faction);
|
||||
},
|
||||
|
||||
loadAugmentationsContent: function() {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.augmentationsContent.style.display = "block";
|
||||
displayAugmentationsContent();
|
||||
Engine.currentPage = Engine.Page.Augmentations;
|
||||
routing.navigateTo(Page.Augmentations);
|
||||
document.getElementById("augmentations-menu-link").classList.add("active");
|
||||
},
|
||||
|
||||
@ -377,7 +352,7 @@ let Engine = {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.tutorialContent.style.display = "block";
|
||||
Engine.displayTutorialContent();
|
||||
Engine.currentPage = Engine.Page.Tutorial;
|
||||
routing.navigateTo(Page.Tutorial);
|
||||
document.getElementById("tutorial-menu-link").classList.add("active");
|
||||
},
|
||||
|
||||
@ -385,7 +360,7 @@ let Engine = {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.devMenuContent.style.display = "block";
|
||||
Engine.displayDevMenuContent();
|
||||
Engine.currentPage = Engine.Page.DevMenu;
|
||||
routing.navigateTo(Page.DevMenu);
|
||||
document.getElementById("dev-menu-link").classList.add("active");
|
||||
},
|
||||
|
||||
@ -393,7 +368,7 @@ let Engine = {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.locationContent.style.display = "block";
|
||||
displayLocationContent();
|
||||
Engine.currentPage = Engine.Page.Location;
|
||||
routing.navigateTo(Page.Location);
|
||||
},
|
||||
|
||||
loadTravelContent: function() {
|
||||
@ -439,7 +414,7 @@ let Engine = {
|
||||
//mainMenu.style.visibility = "hidden";
|
||||
mainMenu.style.visibility = "hidden";
|
||||
Engine.Display.workInProgressContent.style.display = "block";
|
||||
Engine.currentPage = Engine.Page.WorkInProgress;
|
||||
routing.navigateTo(Page.WorkInProgress);
|
||||
},
|
||||
|
||||
loadRedPillContent: function() {
|
||||
@ -447,7 +422,7 @@ let Engine = {
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "hidden";
|
||||
Engine.Display.redPillContent.style.display = "block";
|
||||
Engine.currentPage = Engine.Page.RedPill;
|
||||
routing.navigateTo(Page.RedPill);
|
||||
},
|
||||
|
||||
loadCinematicTextContent: function() {
|
||||
@ -455,19 +430,19 @@ let Engine = {
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "hidden";
|
||||
Engine.Display.cinematicTextContent.style.display = "block";
|
||||
Engine.currentPage = Engine.Page.CinematicText;
|
||||
routing.navigateTo(Page.CinematicText);
|
||||
},
|
||||
|
||||
loadInfiltrationContent: function() {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.infiltrationContent.style.display = "block";
|
||||
Engine.currentPage = Engine.Page.Infiltration;
|
||||
routing.navigateTo(Page.Infiltration);
|
||||
},
|
||||
|
||||
loadStockMarketContent: function() {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.stockMarketContent.style.display = "block";
|
||||
Engine.currentPage = Engine.Page.StockMarket;
|
||||
routing.navigateTo(Page.StockMarket);
|
||||
displayStockMarketContent();
|
||||
},
|
||||
|
||||
@ -475,10 +450,10 @@ let Engine = {
|
||||
Engine.hideAllContent();
|
||||
if (document.getElementById("gang-container") || Player.inGang()) {
|
||||
displayGangContent();
|
||||
Engine.currentPage = Engine.Page.Gang;
|
||||
routing.navigateTo(Page.Gang);
|
||||
} else {
|
||||
Engine.loadTerminalContent();
|
||||
Engine.currentPage = Engine.Page.Terminal;
|
||||
routing.navigateTo(Page.Terminal);
|
||||
}
|
||||
},
|
||||
|
||||
@ -487,7 +462,7 @@ let Engine = {
|
||||
document.getElementById("mainmenu-container").style.visibility = "hidden";
|
||||
document.getElementById("character-overview-wrapper").style.visibility = "hidden";
|
||||
Engine.Display.missionContent.style.display = "block";
|
||||
Engine.currentPage = Engine.Page.Mission;
|
||||
routing.navigateTo(Page.Mission);
|
||||
},
|
||||
|
||||
loadCorporationContent: function() {
|
||||
@ -495,7 +470,7 @@ let Engine = {
|
||||
Engine.hideAllContent();
|
||||
document.getElementById("character-overview-wrapper").style.visibility = "hidden";
|
||||
Player.corporation.createUI();
|
||||
Engine.currentPage = Engine.Page.Corporation;
|
||||
routing.navigateTo(Page.Corporation);
|
||||
}
|
||||
},
|
||||
|
||||
@ -503,7 +478,7 @@ let Engine = {
|
||||
if (Player.bladeburner instanceof Bladeburner) {
|
||||
try {
|
||||
Engine.hideAllContent();
|
||||
Engine.currentPage = Engine.Page.Bladeburner;
|
||||
routing.navigateTo(Page.Bladeburner);
|
||||
Player.bladeburner.createContent();
|
||||
} catch(e) {
|
||||
exceptionAlert(e);
|
||||
@ -573,11 +548,11 @@ let Engine = {
|
||||
|
||||
displayCharacterOverviewInfo: function() {
|
||||
Engine.overview.update();
|
||||
|
||||
|
||||
|
||||
const save = document.getElementById("character-overview-save-button");
|
||||
const flashClass = "flashing-button";
|
||||
if(!Settings.AutosaveInterval) {
|
||||
if(!Settings.AutosaveInterval) {
|
||||
save.classList.add(flashClass);
|
||||
} else {
|
||||
save.classList.remove(flashClass);
|
||||
@ -595,7 +570,7 @@ let Engine = {
|
||||
|
||||
var intText = "";
|
||||
if (Player.intelligence > 0) {
|
||||
intText = 'Intelligence: ' + (Player.intelligence).toLocaleString() + "<br><br><br>";
|
||||
intText = 'Intelligence: ' + (Player.intelligence).toLocaleString() + '<br>';
|
||||
}
|
||||
|
||||
let bitNodeTimeText = "";
|
||||
@ -609,21 +584,21 @@ let Engine = {
|
||||
'Current City: ' + Player.city + '<br><br>' +
|
||||
'Employer: ' + Player.companyName + '<br>' +
|
||||
'Job Title: ' + companyPosition + '<br><br>' +
|
||||
'Money: $' + formatNumber(Player.money.toNumber(), 2)+ '<br><br><br>' +
|
||||
'Money: $' + formatNumber(Player.money.toNumber(), 2) + '<br><br><br>' +
|
||||
'<b>Stats</b><br><br>' +
|
||||
'Hacking Level: ' + (Player.hacking_skill).toLocaleString() +
|
||||
" (" + numeral(Player.hacking_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
' (' + numeral(Player.hacking_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
'Strength: ' + (Player.strength).toLocaleString() +
|
||||
" (" + numeral(Player.strength_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
' (' + numeral(Player.strength_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
'Defense: ' + (Player.defense).toLocaleString() +
|
||||
" (" + numeral(Player.defense_exp).format('(0.000a)')+ ' experience)<br>' +
|
||||
' (' + numeral(Player.defense_exp).format('(0.000a)')+ ' experience)<br>' +
|
||||
'Dexterity: ' + (Player.dexterity).toLocaleString() +
|
||||
" (" + numeral(Player.dexterity_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
' (' + numeral(Player.dexterity_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
'Agility: ' + (Player.agility).toLocaleString() +
|
||||
" (" + numeral(Player.agility_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
' (' + numeral(Player.agility_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
'Charisma: ' + (Player.charisma).toLocaleString() +
|
||||
" (" + numeral(Player.charisma_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
intText +
|
||||
' (' + numeral(Player.charisma_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
intText + '<br><br>' +
|
||||
'<b>Multipliers</b><br><br>' +
|
||||
'Hacking Chance multiplier: ' + formatNumber(Player.hacking_chance_mult * 100, 2) + '%<br>' +
|
||||
'Hacking Speed multiplier: ' + formatNumber(Player.hacking_speed_mult * 100, 2) + '%<br>' +
|
||||
@ -1061,7 +1036,7 @@ let Engine = {
|
||||
if (Engine.Counters.updateActiveScriptsDisplay <= 0) {
|
||||
//Always update, but make the interval longer if the page isn't active
|
||||
updateActiveScriptsItems();
|
||||
if (Engine.currentPage === Engine.Page.ActiveScripts) {
|
||||
if (routing.isOn(Page.ActiveScripts)) {
|
||||
Engine.Counters.updateActiveScriptsDisplay = 5;
|
||||
} else {
|
||||
Engine.Counters.updateActiveScriptsDisplay = 10;
|
||||
@ -1070,11 +1045,11 @@ let Engine = {
|
||||
|
||||
if (Engine.Counters.updateDisplays <= 0) {
|
||||
Engine.displayCharacterOverviewInfo();
|
||||
if (Engine.currentPage == Engine.Page.CharacterInfo) {
|
||||
if (routing.isOn(Page.CharacterInfo)) {
|
||||
Engine.displayCharacterInfo();
|
||||
} else if (Engine.currentPage == Engine.Page.HacknetNodes) {
|
||||
} else if (routing.isOn(Page.HacknetNodes)) {
|
||||
updateHacknetNodesContent();
|
||||
} else if (Engine.currentPage == Engine.Page.CreateProgram) {
|
||||
} else if (routing.isOn(Page.CreateProgram)) {
|
||||
displayCreateProgramContent();
|
||||
}
|
||||
|
||||
@ -1086,16 +1061,16 @@ let Engine = {
|
||||
}
|
||||
|
||||
if (Engine.Counters.updateDisplaysMed <= 0) {
|
||||
if (Engine.currentPage === Engine.Page.Corporation) {
|
||||
if (routing.isOn(Page.Corporation)) {
|
||||
Player.corporation.updateUIContent();
|
||||
}
|
||||
Engine.Counters.updateDisplaysMed = 9;
|
||||
}
|
||||
|
||||
if (Engine.Counters.updateDisplaysLong <= 0) {
|
||||
if (Engine.currentPage === Engine.Page.Gang) {
|
||||
if (routing.isOn(Page.Gang)) {
|
||||
updateGangContent();
|
||||
} else if (Engine.currentPage === Engine.Page.ScriptEditor) {
|
||||
} else if (routing.isOn(Page.ScriptEditor)) {
|
||||
updateScriptEditorContent();
|
||||
}
|
||||
Engine.Counters.updateDisplaysLong = 15;
|
||||
@ -1210,23 +1185,6 @@ let Engine = {
|
||||
}
|
||||
},
|
||||
|
||||
_prevTimeout: null,
|
||||
createStatusText: function(txt) {
|
||||
if (Engine._prevTimeout != null) {
|
||||
clearTimeout(Engine._prevTimeout);
|
||||
Engine._prevTimeout = null;
|
||||
}
|
||||
var statusText = document.getElementById("status-text")
|
||||
statusText.style.display = "inline-block";
|
||||
statusText.setAttribute("class", "status-text");
|
||||
statusText.innerHTML = txt;
|
||||
Engine._prevTimeout = setTimeout(function() {
|
||||
statusText.style.display = "none";
|
||||
statusText.removeAttribute("class");
|
||||
statusText.innerHTML = "";
|
||||
}, 3000);
|
||||
},
|
||||
|
||||
//Used when initializing a game
|
||||
//elems should be an array of all DOM elements under the header
|
||||
closeMainMenuHeader: function(elems) {
|
||||
@ -1430,11 +1388,12 @@ let Engine = {
|
||||
bladeburner.style.display = "none";
|
||||
corp.style.display = "none";
|
||||
gang.style.display = "none";
|
||||
dev.style.display = "none";
|
||||
|
||||
Engine.openMainMenuHeader(
|
||||
[terminal, createScript, activeScripts, stats,
|
||||
hacknetnodes, city,
|
||||
tutorial, options, dev]
|
||||
tutorial, options]
|
||||
);
|
||||
|
||||
//Start interactive tutorial
|
||||
@ -1450,7 +1409,7 @@ let Engine = {
|
||||
setDisplayElements: function() {
|
||||
//Content elements
|
||||
Engine.Display.terminalContent = document.getElementById("terminal-container");
|
||||
Engine.currentPage = Engine.Page.Terminal;
|
||||
routing.navigateTo(Page.Terminal);
|
||||
|
||||
Engine.Display.characterContent = document.getElementById("character-container");
|
||||
Engine.Display.characterContent.style.display = "none";
|
||||
@ -1965,7 +1924,9 @@ let Engine = {
|
||||
|
||||
Engine.Clickables.devMainMenuButton = clearEventListeners("dev-menu-link");
|
||||
Engine.Clickables.devMainMenuButton.addEventListener("click", function() {
|
||||
Engine.loadDevMenuContent();
|
||||
if( process.env.NODE_ENV === "development") {
|
||||
Engine.loadDevMenuContent();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
|
26
src/types.ts
26
src/types.ts
@ -9,3 +9,29 @@ export type EqualityFunc<T> = (a: T, b: T) => boolean;
|
||||
export interface IMap<T> {
|
||||
[key: string]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs some action, with no returned value.
|
||||
*/
|
||||
export type Action = () => void;
|
||||
|
||||
/**
|
||||
* Contains a method to initialize itself to a known state.
|
||||
*/
|
||||
export interface ISelfInitializer {
|
||||
/**
|
||||
* Initialize/reset the object to a known, default state.
|
||||
*/
|
||||
init(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains a method to repopulate itself based on a JSON string.
|
||||
*/
|
||||
export interface ISelfLoading {
|
||||
/**
|
||||
* Loads the save state onto the current object.
|
||||
* @param saveState JSON string representing the save state.
|
||||
*/
|
||||
load(saveState: string): void;
|
||||
}
|
||||
|
27
src/ui/createStatusText.ts
Normal file
27
src/ui/createStatusText.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { getElementById } from "../../utils/uiHelpers/getElementById";
|
||||
import { Action } from "../types";
|
||||
|
||||
const threeSeconds: number = 3000;
|
||||
let x: number | undefined;
|
||||
|
||||
/**
|
||||
* Displays a status message to the player for approximately 3 seconds.
|
||||
* @param text The status text to display
|
||||
*/
|
||||
export function createStatusText(text: string) {
|
||||
if (x !== undefined) {
|
||||
clearTimeout(x);
|
||||
// Likely not needed due to clearTimeout, but just in case...
|
||||
x = undefined;
|
||||
}
|
||||
|
||||
const statusElement: HTMLElement = getElementById("status-text");
|
||||
statusElement.classList.add("status-text");
|
||||
statusElement.innerText = text;
|
||||
const handler: Action = () => {
|
||||
statusElement.classList.remove("status-text");
|
||||
statusElement.innerText = "";
|
||||
};
|
||||
|
||||
x = setTimeout(handler, threeSeconds);
|
||||
}
|
146
src/ui/navigationTracking.ts
Normal file
146
src/ui/navigationTracking.ts
Normal file
@ -0,0 +1,146 @@
|
||||
/**
|
||||
* The full-screen page the player is currently be on.
|
||||
* These pages are mutually exclusive.
|
||||
*/
|
||||
export enum Page {
|
||||
/**
|
||||
* (Default) The terminal is where the player issues all commands, executes scripts, etc.
|
||||
*/
|
||||
Terminal = "Terminal",
|
||||
|
||||
/**
|
||||
* Displays most of the statistics about the player.
|
||||
*/
|
||||
CharacterInfo = "CharacterInfo",
|
||||
|
||||
/**
|
||||
* The console for editing Netscript files.
|
||||
*/
|
||||
ScriptEditor = "ScriptEditor",
|
||||
|
||||
/**
|
||||
* Monitor the scripts currently executing across the servers.
|
||||
*/
|
||||
ActiveScripts = "ActiveScripts",
|
||||
|
||||
/**
|
||||
* View, purchase, and upgrade Hacknet nodes.
|
||||
*/
|
||||
HacknetNodes = "HacknetNodes",
|
||||
|
||||
/**
|
||||
* View the city the player is currently in.
|
||||
*/
|
||||
World = "World",
|
||||
|
||||
/**
|
||||
* The list of programs the player could potentially build.
|
||||
*/
|
||||
CreateProgram = "CreateProgram",
|
||||
|
||||
/**
|
||||
* The list of all factions, and invites, available to the player.
|
||||
*/
|
||||
Factions = "Factions",
|
||||
|
||||
/**
|
||||
* Information about a specific faction.
|
||||
*/
|
||||
Faction = "Faction",
|
||||
|
||||
/**
|
||||
* The list of installed, and yet-to-be installed, augmentations the player has purchased.
|
||||
*/
|
||||
Augmentations = "Augmentations",
|
||||
|
||||
/**
|
||||
* A collection of in-game material to learn about the game.
|
||||
*/
|
||||
Tutorial = "Tutorial",
|
||||
|
||||
/**
|
||||
* A collection of items to manipulate the state of the game. Useful for development.
|
||||
*/
|
||||
DevMenu = "Dev Menu",
|
||||
|
||||
/**
|
||||
* Information about the specific location the player at (job, company, etc.);
|
||||
*/
|
||||
Location = "Location",
|
||||
|
||||
/**
|
||||
* A blocking page to show the player they are currently doing some action (building a program, working, etc.).
|
||||
*/
|
||||
workInProgress = "WorkInProgress",
|
||||
|
||||
/**
|
||||
* A special screen to show the player they've reached a certain point in the game.
|
||||
*/
|
||||
RedPill = "RedPill",
|
||||
|
||||
/**
|
||||
* A special screen to show the player they've reached a certain point in the game.
|
||||
*/
|
||||
CinematicText = "CinematicText",
|
||||
|
||||
/**
|
||||
* Mini-game to infiltrate a company, gaining experience from successful progress.
|
||||
*/
|
||||
Infiltration = "Infiltration",
|
||||
|
||||
/**
|
||||
* View the in-game stock market.
|
||||
*/
|
||||
StockMarket = "StockMarket",
|
||||
|
||||
/**
|
||||
* Manage gang actions and members.
|
||||
*/
|
||||
Gang = "Gang",
|
||||
|
||||
/**
|
||||
* Perform missions for a Faction.
|
||||
*/
|
||||
Mission = "Mission",
|
||||
|
||||
/**
|
||||
* Manage a corporation.
|
||||
*/
|
||||
Corporation = "Corporation",
|
||||
|
||||
/**
|
||||
* Manage special Bladeburner activities.
|
||||
*/
|
||||
Bladeburner = "Bladeburner",
|
||||
}
|
||||
|
||||
/**
|
||||
* This class keeps track of player navigation/routing within the game.
|
||||
*/
|
||||
class Routing {
|
||||
/**
|
||||
* Tracking the what page the user is currently on.
|
||||
*/
|
||||
private currentPage: Page | null = null;
|
||||
|
||||
/**
|
||||
* Determines if the player is currently on the specified page.
|
||||
* @param page The page to compare against the current state.
|
||||
*/
|
||||
isOn(page: Page) {
|
||||
return this.currentPage === page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Routes the player to the appropriate page.
|
||||
* @param page The page to navigate to.
|
||||
*/
|
||||
navigateTo(page: Page) {
|
||||
this.currentPage = page;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The routing instance for tracking page navigation.
|
||||
*/
|
||||
export const routing: Routing = new Routing();
|
40
src/ui/postToTerminal.ts
Normal file
40
src/ui/postToTerminal.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { getElementById } from "../../utils/uiHelpers/getElementById";
|
||||
|
||||
/**
|
||||
* Adds some output to the terminal.
|
||||
* @param input Text or HTML to output to the terminal
|
||||
*/
|
||||
export function post(input: string) {
|
||||
postContent(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds some output to the terminal with an identifier of "hack-progress-bar"
|
||||
* @param input Text or HTML to output to the terminal
|
||||
*/
|
||||
export function hackProgressBarPost(input: string) {
|
||||
postContent(input, "hack-progress-bar");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds some output to the terminal with an identifier of "hack-progress"
|
||||
* @param input Text or HTML to output to the terminal
|
||||
*/
|
||||
export function hackProgressPost(input: string) {
|
||||
postContent(input, "hack-progress");
|
||||
}
|
||||
|
||||
function postContent(input: string, id?: string) {
|
||||
// tslint:disable-next-line:max-line-length
|
||||
const style: string = `color: var(--my-font-color); background-color:var(--my-background-color);${id === undefined ? " white-space:pre-wrap;" : ""}`;
|
||||
// tslint:disable-next-line:max-line-length
|
||||
const content: string = `<tr class="posted"><td ${id === undefined ? 'class="terminal-line"' : `id="${id}"`} style="${style}">${input}</td></tr>`;
|
||||
const inputElement: HTMLElement = getElementById("terminal-input");
|
||||
inputElement.insertAdjacentHTML("beforebegin", content);
|
||||
scrollTerminalToBottom();
|
||||
}
|
||||
|
||||
function scrollTerminalToBottom() {
|
||||
const container: HTMLElement = getElementById("terminal-container");
|
||||
container.scrollTop = container.scrollHeight;
|
||||
}
|
@ -1,38 +1,5 @@
|
||||
import {Engine} from "./engine";
|
||||
|
||||
/* Settings.js */
|
||||
let Settings = {
|
||||
CodeInstructionRunTime: 25,
|
||||
MaxLogCapacity: 50,
|
||||
MaxPortCapacity: 50,
|
||||
SuppressMessages: false,
|
||||
SuppressFactionInvites: false,
|
||||
SuppressTravelConfirmation: false,
|
||||
SuppressBuyAugmentationConfirmation: false,
|
||||
AutosaveInterval: 60,
|
||||
DisableHotkeys: false,
|
||||
ThemeHighlightColor: "#ffffff",
|
||||
ThemeFontColor: "#66ff33",
|
||||
ThemeBackgroundColor: "#000000",
|
||||
EditorTheme: "Monokai",
|
||||
EditorKeybinding: "ace",
|
||||
}
|
||||
|
||||
function loadSettings(saveString) {
|
||||
Settings = JSON.parse(saveString);
|
||||
}
|
||||
|
||||
function initSettings() {
|
||||
Settings.CodeInstructionRunTime = 50;
|
||||
Settings.MaxLogCapacity = 50;
|
||||
Settings.MaxPortCapacity = 50;
|
||||
Settings.SuppressMessages = false;
|
||||
Settings.SuppressFactionInvites = false;
|
||||
Settings.SuppressTravelConfirmation = false;
|
||||
Settings.SuppressBuyAugmentationConfirmation = false;
|
||||
Settings.AutosaveInterval = 60;
|
||||
Settings.DisableHotkeys = false;
|
||||
}
|
||||
import {Engine} from "../engine";
|
||||
import {Settings} from "../Settings";
|
||||
|
||||
function setSettingsLabels() {
|
||||
var nsExecTime = document.getElementById("settingsNSExecTimeRangeValLabel");
|
||||
@ -42,6 +9,7 @@ function setSettingsLabels() {
|
||||
var suppressFactionInv = document.getElementById("settingsSuppressFactionInvites")
|
||||
var suppressTravelConfirmation = document.getElementById("settingsSuppressTravelConfirmation");
|
||||
var suppressBuyAugmentationConfirmation = document.getElementById("settingsSuppressBuyAugmentationConfirmation");
|
||||
var suppressHospitalizationPopup = document.getElementById("settingsSuppressHospitalizationPopup");
|
||||
var autosaveInterval = document.getElementById("settingsAutosaveIntervalValLabel");
|
||||
var disableHotkeys = document.getElementById("settingsDisableHotkeys");
|
||||
|
||||
@ -53,6 +21,7 @@ function setSettingsLabels() {
|
||||
suppressFactionInv.checked = Settings.SuppressFactionInvites;
|
||||
suppressTravelConfirmation.checked = Settings.SuppressTravelConfirmation;
|
||||
suppressBuyAugmentationConfirmation.checked = Settings.SuppressBuyAugmentationConfirmation;
|
||||
suppressHospitalizationPopup.checked = Settings.SuppressHospitalizationPopup;
|
||||
autosaveInterval.innerHTML = Settings.AutosaveInterval;
|
||||
disableHotkeys.checked = Settings.DisableHotkeys;
|
||||
|
||||
@ -105,8 +74,11 @@ function setSettingsLabels() {
|
||||
|
||||
suppressBuyAugmentationConfirmation.onclick = function() {
|
||||
Settings.SuppressBuyAugmentationConfirmation = this.checked;
|
||||
console.log('sup buy: '+Settings.SuppressBuyAugmentationConfirmation);
|
||||
};
|
||||
|
||||
suppressHospitalizationPopup.onclick = function() {
|
||||
Settings.SuppressHospitalizationPopup = this.checked;
|
||||
}
|
||||
|
||||
disableHotkeys.onclick = function() {
|
||||
Settings.DisableHotkeys = this.checked;
|
||||
@ -126,4 +98,4 @@ function setSettingsLabels() {
|
||||
}
|
||||
}
|
||||
|
||||
export {Settings, initSettings, setSettingsLabels, loadSettings};
|
||||
export { setSettingsLabels };
|
@ -1,7 +1,8 @@
|
||||
import {Faction, joinFaction} from "../src/Faction";
|
||||
import {joinFaction} from "../src/Faction";
|
||||
import {Engine} from "../src/engine";
|
||||
import {Player} from "../src/Player";
|
||||
import {clearEventListeners} from "./uiHelpers/clearEventListeners";
|
||||
import {Page, routing} from "../src/ui/navigationTracking";
|
||||
|
||||
/* Faction Invitation Pop-up box */
|
||||
function factionInvitationBoxClose() {
|
||||
@ -11,7 +12,7 @@ function factionInvitationBoxClose() {
|
||||
|
||||
function factionInvitationBoxOpen() {
|
||||
var factionInvitationBox = document.getElementById("faction-invitation-box-container");
|
||||
factionInvitationBox.style.display = "block";
|
||||
factionInvitationBox.style.display = "flex";
|
||||
}
|
||||
|
||||
function factionInvitationSetText(txt) {
|
||||
@ -30,7 +31,7 @@ function factionInvitationBoxCreate(faction) {
|
||||
faction.alreadyInvited = true;
|
||||
Player.factionInvitations.push(faction.name);
|
||||
|
||||
if (Engine.currentPage === Engine.Page.Factions) {
|
||||
if (routing.isOn(Page.Factions)) {
|
||||
Engine.loadFactionsContent();
|
||||
}
|
||||
|
||||
@ -45,7 +46,7 @@ function factionInvitationBoxCreate(faction) {
|
||||
}
|
||||
joinFaction(faction);
|
||||
factionInvitationBoxClose();
|
||||
if (Engine.currentPage === Engine.Page.Factions) {
|
||||
if (routing.isOn(Page.Factions)) {
|
||||
Engine.loadFactionsContent();
|
||||
}
|
||||
return false;
|
||||
|
@ -35,7 +35,7 @@ function gameOptionsBoxClose() {
|
||||
|
||||
function gameOptionsBoxOpen() {
|
||||
var box = document.getElementById("game-options-container");
|
||||
box.style.display = "block";
|
||||
box.style.display = "flex";
|
||||
setTimeout(function() {
|
||||
gameOptionsOpened = true;
|
||||
}, 500);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {BitNodeMultipliers} from "../src/BitNode";
|
||||
import {BitNodeMultipliers} from "../src/BitNodeMultipliers";
|
||||
import {CONSTANTS} from "../src/Constants";
|
||||
import {Factions, Faction} from "../src/Faction";
|
||||
import {Player} from "../src/Player";
|
||||
|
@ -32,7 +32,7 @@ function yesNoBoxCreate(txt) {
|
||||
|
||||
var c = document.getElementById("yes-no-box-container");
|
||||
if (c) {
|
||||
c.style.display = "block";
|
||||
c.style.display = "flex";
|
||||
} else {
|
||||
console.log("ERROR: Container not found for YesNoBox");
|
||||
}
|
||||
@ -75,7 +75,7 @@ function yesNoTxtInpBoxCreate(txt) {
|
||||
|
||||
var c = document.getElementById("yes-no-text-input-box-container");
|
||||
if (c) {
|
||||
c.style.display = "block";
|
||||
c.style.display = "flex";
|
||||
} else {
|
||||
console.log("ERROR: Container not found for YesNoTextInputBox");
|
||||
}
|
||||
|
@ -34,11 +34,14 @@ export function createProgressBarText(params: IProgressBarConfiguration) {
|
||||
};
|
||||
|
||||
// tslint:disable-next-line:prefer-object-spread
|
||||
const derivedParams: IProgressBarConfigurationMaterialized = Object.assign({}, defaultParams, params);
|
||||
const derived: IProgressBarConfigurationMaterialized = Object.assign({}, defaultParams, params);
|
||||
// Ensure it is 0..1
|
||||
derived.progress = Math.max(Math.min(derived.progress, 1), 0);
|
||||
|
||||
const bars: number = Math.floor(derivedParams.progress / (1 / derivedParams.totalTicks));
|
||||
const dashes: number = derivedParams.totalTicks - bars;
|
||||
// This way there is always at least one bar filled in...
|
||||
const bars: number = Math.max(Math.floor(derived.progress / (1 / derived.totalTicks)), 1);
|
||||
const dashes: number = Math.max(derived.totalTicks - bars, 0);
|
||||
|
||||
// String.prototype.repeat isn't completley supported, but good enough for our purposes
|
||||
return `[${"|".repeat(bars + 1)}${"-".repeat(dashes + 1)}]`;
|
||||
return `[${"|".repeat(bars)}${"-".repeat(dashes)}]`;
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Formats the current time (to the minute).
|
||||
*/
|
||||
export function getTimestamp() {
|
||||
const d: Date = new Date();
|
||||
// A negative slice value takes from the end of the string rather than the beginning.
|
||||
|
30
utils/helpers/keyCodes.ts
Normal file
30
utils/helpers/keyCodes.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { IMap } from "../../src/types";
|
||||
|
||||
/**
|
||||
* Keyboard key codes
|
||||
*/
|
||||
export const KEY: IMap<number> = {
|
||||
A: 65,
|
||||
B: 66,
|
||||
C: 67,
|
||||
CTRL: 17,
|
||||
D: 68,
|
||||
DOWNARROW: 40,
|
||||
E: 69,
|
||||
ENTER: 13,
|
||||
F: 70,
|
||||
H: 72,
|
||||
J: 74,
|
||||
K: 75,
|
||||
L: 76,
|
||||
M: 77,
|
||||
N: 78,
|
||||
O: 79,
|
||||
P: 80,
|
||||
R: 82,
|
||||
S: 83,
|
||||
TAB: 9,
|
||||
U: 85,
|
||||
UPARROW: 38,
|
||||
W: 87,
|
||||
};
|
@ -4,5 +4,6 @@
|
||||
*/
|
||||
export function roundToTwo(decimal: number) {
|
||||
const leftShift: number = Math.round(parseFloat(`${decimal}e+2`));
|
||||
|
||||
return +(`${leftShift}e-2`);
|
||||
}
|
||||
|
@ -27,18 +27,18 @@ interface IAccordionConfigurationParameters {
|
||||
export function createAccordionElement(params: IAccordionConfigurationParameters) {
|
||||
const liElem: HTMLLIElement = createElement("li") as HTMLLIElement;
|
||||
const header: HTMLButtonElement = createElement("button", {
|
||||
class: "accordion-header",
|
||||
clickListener() {
|
||||
this.classList.toggle("active");
|
||||
const pnl: CSSStyleDeclaration = (this.nextElementSibling as HTMLDivElement).style;
|
||||
pnl.display = pnl.display === "block" ? "none" : "block";
|
||||
},
|
||||
id: params.id !== undefined ? `${params.id}-hdr` : undefined,
|
||||
class:"accordion-header",
|
||||
innerHTML: params.hdrText,
|
||||
}) as HTMLButtonElement;
|
||||
const panel: HTMLDivElement = createElement("div", {
|
||||
class: "accordion-panel",
|
||||
id: params.id !== undefined ? `${params.id}-panel` : undefined,
|
||||
class:"accordion-panel",
|
||||
innerHTML: params.panelText,
|
||||
}) as HTMLDivElement;
|
||||
|
||||
|
@ -9,8 +9,8 @@ import { getElementById } from "./getElementById";
|
||||
export function createPopup(id: string, elems: HTMLElement[]) {
|
||||
const container: HTMLDivElement = createElement("div", {
|
||||
class: "popup-box-container",
|
||||
display: "block",
|
||||
id: id,
|
||||
display: "flex",
|
||||
id,
|
||||
}) as HTMLDivElement;
|
||||
const content: HTMLElement = createElement("div", {
|
||||
class: "popup-box-content",
|
||||
|
Reference in New Issue
Block a user