mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-19 06:03:50 +01:00
commit
e425bcfe6b
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
|
@ -57,8 +57,8 @@ You can contact him through:
|
||||
* Discord
|
||||
* [Reddit](https://www.reddit.com/user/chapt3r/)
|
||||
|
||||
Otherwise, here are some general guidelines for determining what types of changes
|
||||
are okay to contribute:
|
||||
Otherwise, here are some general guidelines for determining what types of
|
||||
changes are okay to contribute:
|
||||
|
||||
##### Contributions that Will Most Likely Be Accepted
|
||||
* Bug Fixes
|
||||
@ -88,12 +88,16 @@ the following rules:
|
||||
the changes to the UI
|
||||
- If your changes affect Netscript, provide some
|
||||
scripts that can be used to test the Netscript changes.
|
||||
- Do not check in any bundled files (`dist\*.bundle.js`). These will be
|
||||
updated as part of official releases.
|
||||
- Ensure you have run `npm run lint` to make sure your changes conform to the
|
||||
rules enforced across the code base. The command will fail if any of the
|
||||
linters find a violation.
|
||||
- Do not check in any bundled files (`dist\*.bundle.js`) or the `index.html`
|
||||
in the root of the repository. These will be updated as part of official
|
||||
releases.
|
||||
|
||||
## As a Documentor
|
||||
To contribute to BitBurner documentation, you will need to have Python
|
||||
installed, along with [Sphinx](http://www.sphinx-doc.org).
|
||||
To contribute to and view your changes to the BitBurner documentation, you will
|
||||
need to have Python installed, along with [Sphinx](http://www.sphinx-doc.org).
|
||||
|
||||
Before submitting your code for a pull request, please try to follow these
|
||||
rules:
|
||||
@ -103,3 +107,5 @@ rules:
|
||||
- Rebase your branch if necessary
|
||||
- When submitting the pull request, make sure that the base fork is
|
||||
_danielyxie/bitburner_ and the base is _dev_.
|
||||
- Do not check in any generated files under `doc\`. The documentation is built
|
||||
automatically by ReadTheDocs.
|
||||
|
@ -1,2 +1,17 @@
|
||||
$fontFamily: 'Lucida Console', 'Lucida Sans Unicode', 'Fira Mono', 'Consolas', 'Courier New', Courier, monospace, 'Times New Roman';
|
||||
$defaultFontSize: 16px;
|
||||
|
||||
/* COLORS */
|
||||
$hacker-green: #adff2f;
|
||||
$success-green: #3adb76;
|
||||
$alert-red: #ff2929;
|
||||
$money-gold: #ffd700;
|
||||
$light-yellow: #faffdf;
|
||||
|
||||
/* Attributes */
|
||||
$my-stat-hp-color: #dd3434;
|
||||
$my-stat-money-color: $money-gold;
|
||||
$my-stat-hack-color: $hacker-green;
|
||||
$my-stat-physical: $light-yellow;
|
||||
$my-stat-cha-color: #a671d1;
|
||||
$my-stat-int-color: #6495ed;
|
||||
|
@ -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;
|
||||
|
@ -92,3 +92,20 @@
|
||||
left: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.killAllMessage {
|
||||
position: absolute;
|
||||
top: 95%;
|
||||
left: 50%;
|
||||
-webkit-transform: translateX(-50%);
|
||||
-moz-transform: translateX(-50%);
|
||||
-ms-transform: translateX(-50%);
|
||||
-o-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.killAllMessageWrapperHidden {
|
||||
display: none;
|
||||
}
|
||||
.killAllMessageWrapperShow {
|
||||
display: block;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
@ -204,38 +200,37 @@
|
||||
.active-scripts-script-header {
|
||||
background-color: #555;
|
||||
color: var(--my-font-color);
|
||||
padding: 4px;
|
||||
padding-left: 10px;
|
||||
padding: 4px 25px 4px 10px;
|
||||
cursor: pointer;
|
||||
width: auto;
|
||||
text-align: left;
|
||||
border: none;
|
||||
outline: none;
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
content: '\02795'; /* "plus" sign (+) */
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 var(--my-font-color);
|
||||
position: absolute;
|
||||
bottom: 4px;
|
||||
}
|
||||
|
||||
.active-scripts-script-header:hover,
|
||||
.active-scripts-script-header.active:hover {
|
||||
&.active:after {
|
||||
content: "\2796"; /* "minus" sign (-) */
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&.active:hover {
|
||||
background-color: #666;
|
||||
}
|
||||
|
||||
.active-scripts-script-header.active {
|
||||
&.active {
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
.active-scripts-script-header:after {
|
||||
content: '\02795'; /* "plus" sign (+) */
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
color: var(--my-font-color);
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.active-scripts-script-panel {
|
||||
@ -244,17 +239,14 @@
|
||||
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 {
|
||||
p, h2, ul, li {
|
||||
background-color: #555;
|
||||
width: auto;
|
||||
color: #fff;
|
||||
margin-left: 5%;
|
||||
}
|
||||
}
|
||||
|
||||
.active-scripts-button {
|
||||
@include borderRadius(12px);
|
||||
@ -266,14 +258,14 @@
|
||||
margin: 4px;
|
||||
padding: 4px;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.active-scripts-button:hover,
|
||||
.active-scripts-button:focus {
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hacknet Nodes */
|
||||
#hacknet-nodes-container {
|
||||
@ -291,6 +283,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,35 +318,25 @@
|
||||
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 {
|
||||
.row {
|
||||
display: table-row;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.hacknet-node-container .row p {
|
||||
p {
|
||||
display: table-cell;
|
||||
}
|
||||
}
|
||||
|
||||
.hacknet-node-container .upgradable-info {
|
||||
.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 {
|
||||
width: 70vw;
|
||||
@ -412,8 +404,8 @@
|
||||
|
||||
#faction-container p,
|
||||
#faction-container pre {
|
||||
padding: 6px;
|
||||
margin: 6px;
|
||||
padding: 4px 6px;
|
||||
margin: 4px 6px;
|
||||
}
|
||||
|
||||
#faction-container pre {
|
||||
@ -429,15 +421,12 @@
|
||||
#faction-augmentations-container {
|
||||
position: fixed;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#faction-augmentations-container p,
|
||||
#faction-augmentations-container a,
|
||||
#faction-augmentations-container ul,
|
||||
#faction-augmentations-container h1{
|
||||
p, a, ul, h1 {
|
||||
margin: 8px;
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
/* World */
|
||||
#world-container li {
|
||||
@ -451,13 +440,22 @@
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.augmentations-list button,
|
||||
.augmentations-list div {
|
||||
.augmentations-list {
|
||||
button,
|
||||
div {
|
||||
color: var(--my-font-color);
|
||||
padding: 8px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
div {
|
||||
padding: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tutorial */
|
||||
#tutorial-container {
|
||||
position: fixed;
|
||||
@ -510,11 +508,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;
|
||||
}
|
||||
|
||||
@ -522,7 +521,13 @@
|
||||
#infiltration-container {
|
||||
position: fixed;
|
||||
padding: 6px;
|
||||
|
||||
span {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#infiltration-left-panel,
|
||||
#infiltration-right-panel {
|
||||
display: inline-block;
|
||||
@ -543,6 +548,10 @@
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
#infiltration-buttons {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#infiltration-buttons .a-link-button {
|
||||
display: inline;
|
||||
width: 25%;
|
||||
@ -552,6 +561,7 @@
|
||||
#stock-market-container {
|
||||
position: fixed;
|
||||
padding: 6px;
|
||||
|
||||
p {
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
}
|
||||
|
@ -87,6 +87,11 @@
|
||||
z-index: 2;
|
||||
background-color: var(--my-background-color);
|
||||
padding: 10px;
|
||||
|
||||
p span {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-box-close-button {
|
||||
@ -138,6 +143,11 @@
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
#infiltration-box-content span {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#infiltration-faction-select {
|
||||
background-color: #000;
|
||||
}
|
||||
|
206
css/styles.scss
206
css/styles.scss
@ -7,6 +7,7 @@
|
||||
--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;
|
||||
|
||||
@ -152,57 +163,61 @@ a:visited {
|
||||
-ms-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.a-link-button:hover {
|
||||
&:hover {
|
||||
background-color: #666;
|
||||
}
|
||||
|
||||
.a-link-button:active {
|
||||
&:active {
|
||||
@include boxShadow(inset 0 1px 4px rgba(0, 0, 0, 0.6));
|
||||
}
|
||||
}
|
||||
|
||||
/* Make anchor tags ("a" elements) inactive (not clickable) */
|
||||
.a-link-button-inactive {
|
||||
text-decoration: none;
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
padding: 5px;
|
||||
padding: 3px 5px;
|
||||
margin: 5px;
|
||||
border: 1px solid #333;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.a-link-button-inactive:hover .tooltiptext,
|
||||
.a-link-button-inactive:hover .tooltiptexthigh,
|
||||
.a-link-button-inactive:hover .tooltiptextleft {
|
||||
&:hover {
|
||||
.tooltiptext,
|
||||
.tooltiptexthigh,
|
||||
.tooltiptextleft {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.a-link-button-inactive:active {
|
||||
&:active {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make anchor tags ("a" elements) for activated actions */
|
||||
.a-link-button-bought {
|
||||
text-decoration: none;
|
||||
background-color: #0a0;
|
||||
color: #fff;
|
||||
padding: 5px;
|
||||
padding: 3px 5px;
|
||||
margin: 5px;
|
||||
border: 1px solid #0a0;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.a-link-button-bought:hover .tooltiptext,
|
||||
.a-link-button-bought:hover .tooltiptexthigh,
|
||||
.a-link-button-bought:hover .tooltiptextleft {
|
||||
&:hover {
|
||||
.tooltiptext,
|
||||
.tooltiptexthigh,
|
||||
.tooltiptextleft {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.a-link-button-bought:active {
|
||||
&:active {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
color: #fff;
|
||||
@ -218,9 +233,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;
|
||||
@ -242,11 +257,10 @@ a:visited {
|
||||
|
||||
/* Tool tips (when hovering over an element */
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
position: relative;
|
||||
|
||||
.tooltip .tooltiptext {
|
||||
.tooltiptext {
|
||||
visibility: hidden;
|
||||
width: 300px;
|
||||
background-color: var(--my-background-color);
|
||||
@ -256,9 +270,11 @@ a:visited {
|
||||
padding: 4px;
|
||||
left: 101%;
|
||||
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
}
|
||||
}
|
||||
|
||||
/* Same thing as a normal tooltip except its a bit higher */
|
||||
.tooltip .tooltiptexthigh {
|
||||
@ -276,7 +292,7 @@ a:visited {
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
/* Similar to a normal tooltip except its positioned on the left of the elemnt
|
||||
/* Similar to a normal tooltip except its positioned on the left of the element
|
||||
rather than the right to avoid exceeding the elements normal width */
|
||||
.tooltip .tooltiptextleft {
|
||||
visibility: hidden;
|
||||
@ -437,47 +453,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: rgba(57, 54, 54, 0.9); /* Fallback color */
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#character-overview-text {
|
||||
color: #fff;
|
||||
background-color: #444;
|
||||
color: $my-stat-physical;
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 2px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.character-stat-text {
|
||||
color: #fff;
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
.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,
|
||||
@ -489,19 +536,16 @@ 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 {
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Accordion menus (Header with collapsible panel) */
|
||||
.accordion-header {
|
||||
@ -509,37 +553,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 {
|
||||
&.active,
|
||||
&:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
.accordion-header.active:hover {
|
||||
&.active:hover {
|
||||
background-color: #666;
|
||||
}
|
||||
|
||||
.accordion-header:after {
|
||||
&:after {
|
||||
content: '\02795'; /* "plus" sign (+) */
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
color: #fff;
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 #fff;
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
right: 6px;
|
||||
}
|
||||
|
||||
.accordion-header.active:after {
|
||||
&.active:after {
|
||||
content: "\2796"; /* "minus" sign (-) */
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
color: #fff;
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.accordion-panel {
|
||||
@ -551,14 +595,11 @@ a:visited {
|
||||
background-color: #555;
|
||||
overflow-y: auto;
|
||||
overflow-x: none;
|
||||
}
|
||||
|
||||
.accordion-panel div,
|
||||
.accordion-panel ul,
|
||||
.accordion-panel p,
|
||||
.accordion-panel ul > li {
|
||||
div, ul, p, ul > li {
|
||||
background-color: #555;
|
||||
}
|
||||
}
|
||||
|
||||
/* override the global <span> styling */
|
||||
#active-scripts-total-production-active,
|
||||
@ -567,3 +608,34 @@ a:visited {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Helper Classes */
|
||||
.hacker-green {
|
||||
color: $hacker-green;
|
||||
}
|
||||
|
||||
.money-gold {
|
||||
color: $money-gold;
|
||||
}
|
||||
|
||||
.light-yellow {
|
||||
color: $light-yellow;
|
||||
}
|
||||
|
||||
.failure {
|
||||
color: $alert-red;
|
||||
text-shadow: 0 0 0 $alert-red;
|
||||
}
|
||||
|
||||
.success {
|
||||
color: $success-green;
|
||||
text-shadow: 0 0 0 $success-green;
|
||||
}
|
||||
|
||||
.physical-yellow {
|
||||
color: $my-stat-physical;
|
||||
}
|
||||
|
||||
.charisma-purple {
|
||||
color: $my-stat-cha-color;
|
||||
}
|
||||
|
@ -19,6 +19,12 @@
|
||||
overflow-y: scroll;
|
||||
background-color: var(--my-background-color);
|
||||
table-layout: fixed;
|
||||
|
||||
.prompt {
|
||||
color: var(--my-prompt-color);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#terminal-input {
|
||||
@ -50,6 +56,12 @@
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#terminal-input-td textarea {
|
||||
overflow: hidden;
|
||||
resize: none;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#terminal-input-header {
|
||||
white-space: pre;
|
||||
}
|
||||
|
2
dist/engine.bundle.js
vendored
2
dist/engine.bundle.js
vendored
File diff suppressed because one or more lines are too long
340
dist/engine.css
vendored
340
dist/engine.css
vendored
@ -1,3 +1,7 @@
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
* {
|
||||
font-size: 16px;
|
||||
font-family: "Lucida Console", "Lucida Sans Unicode", "Fira Mono", "Consolas", "Courier New", Courier, monospace, "Times New Roman"; }
|
||||
@ -13,7 +17,8 @@
|
||||
:root {
|
||||
--my-font-color: #6f3;
|
||||
--my-background-color: #000;
|
||||
--my-highlight-color: #fff; }
|
||||
--my-highlight-color: #fff;
|
||||
--my-prompt-color: #f92672; }
|
||||
|
||||
body {
|
||||
background-color: var(--my-background-color); }
|
||||
@ -81,7 +86,7 @@ tr:focus {
|
||||
display: block;
|
||||
color: #e6e6e6;
|
||||
background-color: #555;
|
||||
padding: 16px;
|
||||
padding: 12px 8px;
|
||||
text-decoration: none; }
|
||||
|
||||
/* Hovering makes them lighter */
|
||||
@ -99,19 +104,31 @@ tr:focus {
|
||||
.mainmenu > li a.active:hover {
|
||||
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: '\2795';
|
||||
font-size: 13px;
|
||||
color: #fff;
|
||||
float: right;
|
||||
margin-left: 5px; }
|
||||
|
||||
.mainmenu-accordion-header.opened:after {
|
||||
content: "\2796"; }
|
||||
font-size: 13px;
|
||||
position: absolute;
|
||||
bottom: 25%;
|
||||
right: 3px;
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 #fff; }
|
||||
|
||||
.mainmenu-accordion-header.opened {
|
||||
background-color: #222; }
|
||||
.mainmenu-accordion-header.opened:after {
|
||||
content: "\2796"; }
|
||||
|
||||
/* Slide down transition */
|
||||
.mainmenu-accordion-panel {
|
||||
@ -119,10 +136,6 @@ tr:focus {
|
||||
opacity: 1;
|
||||
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 {
|
||||
@ -132,17 +145,15 @@ a:visited {
|
||||
text-decoration: none;
|
||||
background-color: #555;
|
||||
color: #fff;
|
||||
padding: 5px;
|
||||
padding: 3px 5px;
|
||||
margin: 5px;
|
||||
border: 1px solid #333;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
|
||||
.a-link-button:hover {
|
||||
background-color: #666; }
|
||||
|
||||
.a-link-button: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);
|
||||
@ -153,16 +164,14 @@ a:visited {
|
||||
text-decoration: none;
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
padding: 5px;
|
||||
padding: 3px 5px;
|
||||
margin: 5px;
|
||||
border: 1px solid #333;
|
||||
cursor: default; }
|
||||
|
||||
.a-link-button-inactive:hover .tooltiptext,
|
||||
.a-link-button-inactive:hover .tooltiptexthigh,
|
||||
.a-link-button-inactive:hover .tooltiptextleft {
|
||||
visibility: visible; }
|
||||
|
||||
.a-link-button-inactive:active {
|
||||
pointer-events: none; }
|
||||
|
||||
@ -171,16 +180,14 @@ a:visited {
|
||||
text-decoration: none;
|
||||
background-color: #0a0;
|
||||
color: #fff;
|
||||
padding: 5px;
|
||||
padding: 3px 5px;
|
||||
margin: 5px;
|
||||
border: 1px solid #0a0;
|
||||
cursor: default; }
|
||||
|
||||
.a-link-button-bought:hover .tooltiptext,
|
||||
.a-link-button-bought:hover .tooltiptexthigh,
|
||||
.a-link-button-bought:hover .tooltiptextleft {
|
||||
visibility: visible; }
|
||||
|
||||
.a-link-button-bought:active {
|
||||
pointer-events: none; }
|
||||
|
||||
@ -217,9 +224,8 @@ a:visited {
|
||||
|
||||
/* Tool tips (when hovering over an element */
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block; }
|
||||
|
||||
display: inline-block;
|
||||
position: relative; }
|
||||
.tooltip .tooltiptext {
|
||||
visibility: hidden;
|
||||
width: 300px;
|
||||
@ -229,6 +235,7 @@ a:visited {
|
||||
text-align: center;
|
||||
padding: 4px;
|
||||
left: 101%;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
z-index: 99; }
|
||||
|
||||
@ -246,7 +253,7 @@ a:visited {
|
||||
position: absolute;
|
||||
z-index: 99; }
|
||||
|
||||
/* Similar to a normal tooltip except its positioned on the left of the elemnt
|
||||
/* Similar to a normal tooltip except its positioned on the left of the element
|
||||
rather than the right to avoid exceeding the elements normal width */
|
||||
.tooltip .tooltiptextleft {
|
||||
visibility: hidden;
|
||||
@ -436,18 +443,24 @@ a:visited {
|
||||
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;
|
||||
background-color: rgba(57, 54, 54, 0.9);
|
||||
/* Fallback color */
|
||||
z-index: 1; }
|
||||
|
||||
#character-overview-text {
|
||||
color: #fff;
|
||||
background-color: #444; }
|
||||
color: #faffdf; }
|
||||
#character-overview-text table {
|
||||
border-collapse: collapse;
|
||||
margin: auto; }
|
||||
#character-overview-text td {
|
||||
padding: 2px;
|
||||
vertical-align: middle; }
|
||||
|
||||
.character-stat-text {
|
||||
color: #fff;
|
||||
@ -456,6 +469,30 @@ a:visited {
|
||||
.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: #dd3434; }
|
||||
|
||||
#character-money-wrapper {
|
||||
color: #ffd700; }
|
||||
|
||||
#character-hack-wrapper {
|
||||
color: #adff2f; }
|
||||
|
||||
#character-cha-wrapper {
|
||||
color: #a671d1; }
|
||||
|
||||
#character-int-wrapper {
|
||||
color: #6495ed; }
|
||||
|
||||
#character-overview-save-button,
|
||||
#character-overview-options-button {
|
||||
-webkit-border-radius: 12px;
|
||||
@ -464,14 +501,17 @@ a:visited {
|
||||
-webkit-box-shadow: 1px 1px 3px #000;
|
||||
-moz-box-shadow: 1px 1px 3px #000;
|
||||
box-shadow: 1px 1px 3px #000;
|
||||
color: #aaa;
|
||||
color: #cecece;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
height: 22px;
|
||||
background-color: #000; }
|
||||
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,
|
||||
#character-overview-save-button:focus,
|
||||
@ -481,15 +521,11 @@ a:visited {
|
||||
text-decoration: none;
|
||||
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; }
|
||||
|
||||
@ -499,35 +535,30 @@ a:visited {
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
margin: 6px 6px 0 6px;
|
||||
padding: 6px;
|
||||
padding: 4px 6px;
|
||||
cursor: pointer;
|
||||
width: 80%;
|
||||
text-align: left;
|
||||
border: none;
|
||||
outline: none; }
|
||||
|
||||
.accordion-header.active,
|
||||
.accordion-header:hover {
|
||||
outline: none;
|
||||
position: relative; }
|
||||
.accordion-header.active, .accordion-header:hover {
|
||||
background-color: #555; }
|
||||
|
||||
.accordion-header.active:hover {
|
||||
background-color: #666; }
|
||||
|
||||
.accordion-header:after {
|
||||
content: '\2795';
|
||||
/* "plus" sign (+) */
|
||||
font-size: 13px;
|
||||
color: #fff;
|
||||
float: right;
|
||||
margin-left: 5px; }
|
||||
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 #fff;
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
right: 6px; }
|
||||
.accordion-header.active:after {
|
||||
content: "\2796";
|
||||
/* "minus" sign (-) */
|
||||
font-size: 13px;
|
||||
color: #fff;
|
||||
float: right;
|
||||
margin-left: 5px; }
|
||||
/* "minus" sign (-) */ }
|
||||
|
||||
.accordion-panel {
|
||||
margin: 0 6px 6px 6px;
|
||||
@ -538,11 +569,7 @@ a:visited {
|
||||
background-color: #555;
|
||||
overflow-y: auto;
|
||||
overflow-x: none; }
|
||||
|
||||
.accordion-panel div,
|
||||
.accordion-panel ul,
|
||||
.accordion-panel p,
|
||||
.accordion-panel ul > li {
|
||||
.accordion-panel div, .accordion-panel ul, .accordion-panel p, .accordion-panel ul > li {
|
||||
background-color: #555; }
|
||||
|
||||
/* override the global <span> styling */
|
||||
@ -552,6 +579,32 @@ a:visited {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
/* Helper Classes */
|
||||
.hacker-green {
|
||||
color: #adff2f; }
|
||||
|
||||
.money-gold {
|
||||
color: #ffd700; }
|
||||
|
||||
.light-yellow {
|
||||
color: #faffdf; }
|
||||
|
||||
.failure {
|
||||
color: #ff2929;
|
||||
text-shadow: 0 0 0 #ff2929; }
|
||||
|
||||
.success {
|
||||
color: #3adb76;
|
||||
text-shadow: 0 0 0 #3adb76; }
|
||||
|
||||
.physical-yellow {
|
||||
color: #faffdf; }
|
||||
|
||||
.charisma-purple {
|
||||
color: #a671d1; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
#terminal-container {
|
||||
position: fixed;
|
||||
margin-left: 10%;
|
||||
@ -570,6 +623,10 @@ a:visited {
|
||||
overflow-y: scroll;
|
||||
background-color: var(--my-background-color);
|
||||
table-layout: fixed; }
|
||||
#terminal .prompt {
|
||||
color: var(--my-prompt-color);
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
#terminal-input {
|
||||
background-color: var(--my-background-color);
|
||||
@ -596,12 +653,19 @@ a:visited {
|
||||
#terminal-input-td {
|
||||
display: flex; }
|
||||
|
||||
#terminal-input-td textarea {
|
||||
overflow: hidden;
|
||||
resize: none;
|
||||
height: auto; }
|
||||
|
||||
#terminal-input-header {
|
||||
white-space: pre; }
|
||||
|
||||
#terminal-input-text-box {
|
||||
flex: 1 1 auto; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
/* CSS for different main menu pages, such as character info, script editor, etc (but excluding
|
||||
terminal which has its own page) */
|
||||
.generic-menupage-container {
|
||||
@ -776,36 +840,30 @@ a:visited {
|
||||
.active-scripts-script-header {
|
||||
background-color: #555;
|
||||
color: var(--my-font-color);
|
||||
padding: 4px;
|
||||
padding-left: 10px;
|
||||
padding: 4px 25px 4px 10px;
|
||||
cursor: pointer;
|
||||
width: auto;
|
||||
text-align: left;
|
||||
border: none;
|
||||
outline: none; }
|
||||
|
||||
.active-scripts-script-header:hover,
|
||||
.active-scripts-script-header.active:hover {
|
||||
background-color: #666; }
|
||||
|
||||
.active-scripts-script-header.active {
|
||||
background-color: #555; }
|
||||
|
||||
outline: none;
|
||||
position: relative; }
|
||||
.active-scripts-script-header:after {
|
||||
content: '\2795';
|
||||
/* "plus" sign (+) */
|
||||
font-size: 13px;
|
||||
color: var(--my-font-color);
|
||||
float: right;
|
||||
margin-left: 5px; }
|
||||
|
||||
margin-left: 5px;
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 var(--my-font-color);
|
||||
position: absolute;
|
||||
bottom: 4px; }
|
||||
.active-scripts-script-header.active:after {
|
||||
content: "\2796";
|
||||
/* "minus" sign (-) */
|
||||
font-size: 13px;
|
||||
color: var(--my-font-color);
|
||||
float: right;
|
||||
margin-left: 5px; }
|
||||
/* "minus" sign (-) */ }
|
||||
.active-scripts-script-header:hover, .active-scripts-script-header.active:hover {
|
||||
background-color: #666; }
|
||||
.active-scripts-script-header.active {
|
||||
background-color: #555; }
|
||||
|
||||
.active-scripts-script-panel {
|
||||
padding: 0 18px;
|
||||
@ -813,11 +871,7 @@ a:visited {
|
||||
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 {
|
||||
.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;
|
||||
@ -836,9 +890,7 @@ a:visited {
|
||||
margin: 4px;
|
||||
padding: 4px;
|
||||
background-color: #000; }
|
||||
|
||||
.active-scripts-button:hover,
|
||||
.active-scripts-button:focus {
|
||||
.active-scripts-button:hover, .active-scripts-button:focus {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
cursor: pointer; }
|
||||
@ -857,6 +909,14 @@ a:visited {
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
white-space: nowrap; }
|
||||
#hacknet-nodes-container li.hacknet-node {
|
||||
-webkit-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.1), 0 0 16px rgba(0, 0, 0, 0.1);
|
||||
-moz-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.1), 0 0 16px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.1), 0 0 16px rgba(0, 0, 0, 0.1);
|
||||
margin: 6px;
|
||||
padding: 7px;
|
||||
width: 35vw;
|
||||
border: 2px solid var(--my-highlight-color); }
|
||||
|
||||
#hacknet-nodes-list {
|
||||
list-style: none;
|
||||
@ -876,25 +936,13 @@ a:visited {
|
||||
#hacknet-nodes-purchase-button {
|
||||
display: inline-block; }
|
||||
|
||||
.hacknet-node {
|
||||
-webkit-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.1), 0 0 16px rgba(0, 0, 0, 0.1);
|
||||
-moz-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.1), 0 0 16px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.1), 0 0 16px rgba(0, 0, 0, 0.1);
|
||||
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; }
|
||||
|
||||
.hacknet-node-container .row p {
|
||||
display: table-cell; }
|
||||
|
||||
.hacknet-node-container .upgradable-info {
|
||||
display: inline-block;
|
||||
margin: 0 4px;
|
||||
@ -957,8 +1005,8 @@ a:visited {
|
||||
|
||||
#faction-container p,
|
||||
#faction-container pre {
|
||||
padding: 6px;
|
||||
margin: 6px; }
|
||||
padding: 4px 6px;
|
||||
margin: 4px 6px; }
|
||||
|
||||
#faction-container pre {
|
||||
width: 70%;
|
||||
@ -977,11 +1025,7 @@ a:visited {
|
||||
#faction-augmentations-container {
|
||||
position: fixed;
|
||||
padding-top: 10px; }
|
||||
|
||||
#faction-augmentations-container p,
|
||||
#faction-augmentations-container a,
|
||||
#faction-augmentations-container ul,
|
||||
#faction-augmentations-container h1 {
|
||||
#faction-augmentations-container p, #faction-augmentations-container a, #faction-augmentations-container ul, #faction-augmentations-container h1 {
|
||||
margin: 8px;
|
||||
padding: 4px; }
|
||||
|
||||
@ -998,9 +1042,14 @@ a:visited {
|
||||
.augmentations-list button,
|
||||
.augmentations-list div {
|
||||
color: var(--my-font-color);
|
||||
padding: 8px;
|
||||
text-decoration: none; }
|
||||
|
||||
.augmentations-list button {
|
||||
padding: 2px 5px; }
|
||||
|
||||
.augmentations-list div {
|
||||
padding: 6px; }
|
||||
|
||||
/* Tutorial */
|
||||
#tutorial-container {
|
||||
position: fixed;
|
||||
@ -1043,16 +1092,20 @@ a:visited {
|
||||
margin: 10px;
|
||||
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; }
|
||||
|
||||
/* Infiltration */
|
||||
#infiltration-container {
|
||||
position: fixed;
|
||||
padding: 6px; }
|
||||
#infiltration-container span {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
#infiltration-left-panel,
|
||||
#infiltration-right-panel {
|
||||
@ -1071,6 +1124,9 @@ a:visited {
|
||||
#infiltration-right-panel p {
|
||||
margin: 4px; }
|
||||
|
||||
#infiltration-buttons {
|
||||
margin-top: 20px; }
|
||||
|
||||
#infiltration-buttons .a-link-button {
|
||||
display: inline;
|
||||
width: 25%; }
|
||||
@ -1139,6 +1195,8 @@ a:visited {
|
||||
float: left;
|
||||
background-color: #555; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
/* Both Work in progress and BitNode stuff */
|
||||
.generic-fullscreen-container {
|
||||
color: var(--my-font-color);
|
||||
@ -1195,6 +1253,8 @@ a:visited {
|
||||
.bitnode-destroyed:hover {
|
||||
color: #fff; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
/* Pop-up boxes */
|
||||
.popup-box-container {
|
||||
display: none;
|
||||
@ -1277,6 +1337,10 @@ a:visited {
|
||||
z-index: 2;
|
||||
background-color: var(--my-background-color);
|
||||
padding: 10px; }
|
||||
.dialog-box-content p span,
|
||||
#log-box-content p span {
|
||||
padding: 0;
|
||||
margin: 0; }
|
||||
|
||||
.dialog-box-close-button {
|
||||
-webkit-border-radius: 12px;
|
||||
@ -1323,6 +1387,10 @@ a:visited {
|
||||
padding: 8px;
|
||||
margin: 8px; }
|
||||
|
||||
#infiltration-box-content span {
|
||||
padding: 0;
|
||||
margin: 0; }
|
||||
|
||||
#infiltration-faction-select {
|
||||
background-color: #000; }
|
||||
|
||||
@ -1375,6 +1443,8 @@ a:visited {
|
||||
#import-game-file-selector {
|
||||
display: none; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
/* interactivetutorial.css */
|
||||
#interactive-tutorial-wrapper {
|
||||
position: relative; }
|
||||
@ -1385,13 +1455,11 @@ a:visited {
|
||||
/* 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; }
|
||||
@ -1402,7 +1470,10 @@ a:visited {
|
||||
padding: 4px;
|
||||
margin: 4px;
|
||||
color: #fff;
|
||||
background-color: #444; }
|
||||
background-color: #444;
|
||||
font-size: 14px;
|
||||
max-height: 350px;
|
||||
overflow-y: auto; }
|
||||
|
||||
#interactive-tutorial-exit,
|
||||
#interactive-tutorial-next,
|
||||
@ -1414,7 +1485,7 @@ a:visited {
|
||||
-moz-box-shadow: 1px 1px 3px #000;
|
||||
box-shadow: 1px 1px 3px #000;
|
||||
color: #aaa;
|
||||
font-size: 20px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
background-color: #000; }
|
||||
#interactive-tutorial-exit:hover, #interactive-tutorial-exit:focus,
|
||||
@ -1426,16 +1497,29 @@ a:visited {
|
||||
text-decoration: none;
|
||||
cursor: pointer; }
|
||||
|
||||
/*
|
||||
#interactive-tutorial-exit {
|
||||
float: left; }
|
||||
float: left;
|
||||
}
|
||||
|
||||
#interactive-tutorial-back {
|
||||
margin-right: 20%;
|
||||
float: right; }
|
||||
float: right;
|
||||
}
|
||||
*/
|
||||
#interactive-tutorial-exit {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0; }
|
||||
|
||||
#interactive-tutorial-back {
|
||||
float: left; }
|
||||
|
||||
#interactive-tutorial-next {
|
||||
float: right; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
* {
|
||||
font-size: 16px;
|
||||
font-family: "Lucida Console", "Lucida Sans Unicode", "Fira Mono", "Consolas", "Courier New", Courier, monospace, "Times New Roman"; }
|
||||
@ -1448,6 +1532,8 @@ a:visited {
|
||||
box-sizing: border-box;
|
||||
vertical-align: top; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
@-webkit-keyframes LOADERSPINNER {
|
||||
0% {
|
||||
-webkit-transform: translate(-50%, -50%) rotate(0deg); }
|
||||
@ -1604,6 +1690,24 @@ a:visited {
|
||||
top: 50%;
|
||||
left: 50%; }
|
||||
|
||||
.killAllMessage {
|
||||
position: absolute;
|
||||
top: 95%;
|
||||
left: 50%;
|
||||
-webkit-transform: translateX(-50%);
|
||||
-moz-transform: translateX(-50%);
|
||||
-ms-transform: translateX(-50%);
|
||||
-o-transform: translateX(-50%);
|
||||
transform: translateX(-50%); }
|
||||
|
||||
.killAllMessageWrapperHidden {
|
||||
display: none; }
|
||||
|
||||
.killAllMessageWrapperShow {
|
||||
display: block; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
/* css for Missions */
|
||||
/* Hacking missions */
|
||||
#mission-container {
|
||||
@ -1720,6 +1824,8 @@ a:visited {
|
||||
.hack-mission-action-buttons-container {
|
||||
border: 2px solid #fff; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
#cmpy-mgmt-container p,
|
||||
#cmpy-mgmt-container a,
|
||||
#cmpy-mgmt-container div {
|
||||
@ -1830,6 +1936,8 @@ a:visited {
|
||||
.cmpy-mgmt-advertising-info {
|
||||
font-size: 12px; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
#bladeburner-container a,
|
||||
#bladeburner-container div,
|
||||
#bladeburner-container p,
|
||||
|
119
dist/vendor.bundle.js
vendored
119
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@ -3,6 +3,31 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
v0.40.3 - 9/15/2018
|
||||
-------------------
|
||||
* Bladeburner Changes:
|
||||
* Increased the effect that agi and dexterity have on action time
|
||||
* Starting number of contracts/operations available will be slightly lower
|
||||
* Random events will now happen slightly more often
|
||||
* Slightly increased the rate at which the Overclock skill point cost increases
|
||||
* The maximum volatility of stocks is now randomized (randomly generated within a certain range every time the game resets)
|
||||
* Increased the range of possible values for initial stock prices
|
||||
* b1t_flum3.exe program can now be created immediately at Hacking level 1 (rather than hacking level 5)
|
||||
* UI improvements for the character overview panel and the left-hand menu (by mat-jaworski)
|
||||
* General UI improvements for displays and Terminal (by mat-jaworski)
|
||||
* Added optional parameters to the getHackTime(), getGrowTime(), and getWeakenTime() Netscript functions
|
||||
* Added isLogEnabled() and getScriptLogs() Netscript functions
|
||||
* Added donateToFaction() Singularity function
|
||||
* Updated documentation to reflect the fact that Netscript port handles (getPortHandle()) only works in NetscriptJS (2.0), NOT Netscript 1.0
|
||||
* Added tryWrite() Netscript function
|
||||
* When working (for a company/faction), experience is gained immediately/continuously rather than all at once when the work is finished
|
||||
* Added a setting in .fconf for enabling line-wrap in the Terminal input
|
||||
* Adding a game option for changing the locale that most numbers are displayed in (this mostly applies for whenever money is displayed)
|
||||
* The randomized parameters of many high-level servers can now take on a higher range of values
|
||||
* Many 'foreign' servers (hackable servers that you don't own) now have a randomized amount of RAM
|
||||
* Added 'wget' Terminal command
|
||||
* Improved the introductory tutorial
|
||||
|
||||
v0.40.2 - 8/27/2018
|
||||
-------------------
|
||||
* Bladeburner Changes:
|
||||
|
@ -3,9 +3,10 @@ Netscript Documentation
|
||||
Netscript is the programming language used in the world of Bitburner.
|
||||
|
||||
When you write scripts in Bitburner, they are written in the Netscript language.
|
||||
Netscript is simply a tiny subset of Javascript. This means that Netscript's
|
||||
syntax is almost idental to Javascript's, but it does not implement many of the
|
||||
features that Javascript has.
|
||||
Netscript is simply a subset of `JavaScript <https://developer.mozilla.org/en-US/docs/Web/JavaScript>`_,.
|
||||
This means that Netscript's syntax is
|
||||
identical to that of JavaScript, but it does not implement some of the features
|
||||
that JavaScript has.
|
||||
|
||||
If you have any requests or suggestions to improve the Netscript language, feel free
|
||||
to reach out to the developer!
|
||||
|
@ -2,14 +2,18 @@
|
||||
|
||||
Netscript 1.0
|
||||
=============
|
||||
Netscript 1.0 is implemented using modified version of Neil Fraser's
|
||||
Netscript 1.0 is implemented using a modified version of Neil Fraser's
|
||||
`JS-Interpreter <https://github.com/NeilFraser/JS-Interpreter>`_.
|
||||
|
||||
This interpreter was created for ES5, which means that the code written
|
||||
for Netscript 1.0 must be compliant for that version. However, some additional
|
||||
ES6+ features are implemented through polyfills.
|
||||
This is an ES5 JavaScript interpreter. This means that (almost) any JavaScript feature
|
||||
that is available in ES5 is also available in Netscript 1.0. However, this also means
|
||||
that the interpreter does not natively support any JavaScript features introduced in versions
|
||||
ES6 or after.
|
||||
|
||||
Netscript 1.0 scripts end with the ".script" extension.
|
||||
If you are confused by the ES5/ES6/etc. terminology, consider reading this:
|
||||
`WTF is ES6, ES8, ES2017, ECMAScript... <https://codeburst.io/javascript-wtf-is-es6-es8-es-2017-ecmascript-dca859e4821c>`_
|
||||
|
||||
Netscript 1.0 scripts end with the ".script" extension in their filenames.
|
||||
|
||||
Which ES6+ features are supported?
|
||||
----------------------------------
|
||||
|
@ -43,3 +43,19 @@ getBitNodeMultipliers
|
||||
mults = getBitNodeMultipliers();
|
||||
print(mults.ServerMaxMoney);
|
||||
print(mults.HackExpGain);
|
||||
|
||||
getHackTime, getGrowTime, & getWeakenTime
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The :js:func:`getHackTime`, :js:func:`getGrowTime`, and :js:func:`getWeakenTime`
|
||||
all take an additional third optional parameter for specifying a specific intelligence
|
||||
level to see how that would affect the hack/grow/weaken times. This parameter
|
||||
defaults to your current intelligence level.
|
||||
|
||||
(Intelligence is unlocked after obtaining Source-File 5).
|
||||
|
||||
The function signatures are then::
|
||||
|
||||
getHackTime(hostname/ip[, hackLvl=current level, intLvl=current level])
|
||||
getGrowTime(hostname/ip[, hackLvl=current level, intLvl=current level])
|
||||
getWeakenTime(hostname/ip[, hackLvl=current level, intLvl=current level])
|
||||
|
@ -129,6 +129,28 @@ enableLog
|
||||
Re-enables logging for the given function. If 'ALL' is passed into this function
|
||||
as an argument, then it will revert the effects of disableLog('ALL')
|
||||
|
||||
isLogEnabled
|
||||
^^^^^^^^^^^^
|
||||
|
||||
.. js:function:: isLogEnabled(fn)
|
||||
|
||||
:param string fn: Name of function to check
|
||||
|
||||
Returns a boolean indicating whether or not logging is enabled for that
|
||||
function (or 'ALL')
|
||||
|
||||
getScriptLogs
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. js:function:: getScriptLogs()
|
||||
|
||||
Returns the script's logs. The logs are returned as an array, where each
|
||||
line is an element in the array. The most recently logged line is at the
|
||||
end of the array.
|
||||
|
||||
Note that there is a maximum number of lines that a script stores in its logs.
|
||||
This is configurable in the game's options.
|
||||
|
||||
scan
|
||||
^^^^
|
||||
|
||||
@ -768,10 +790,22 @@ write
|
||||
when writing to a port.
|
||||
|
||||
If the first argument is a string, then it specifies the name of a text file (.txt) and this function will write *data* to that text file. If the
|
||||
specified text file does not exist, then it will be created. The third argument *mode, defines how the data will be written to the text file. If *mode*
|
||||
specified text file does not exist, then it will be created. The third argument *mode*, defines how the data will be written to the text file. If *mode*
|
||||
is set to "w", then the data is written in "write" mode which means that it will overwrite all existing data on the text file. If *mode* is set to
|
||||
any other value then the data will be written in "append" mode which means that the data will be added at the end of the text file.
|
||||
|
||||
tryWrite
|
||||
^^^^^^^^
|
||||
|
||||
.. js:function:: tryWrite(port, data="")
|
||||
|
||||
:param number port: Port to be written to
|
||||
:param string data: Data to try to write
|
||||
:returns: True if the data is successfully written to the port, and false otherwise
|
||||
|
||||
Attempts to write data to the specified Netscript Port. If the port is full, the data will
|
||||
not be written. Otherwise, the data will be written normally
|
||||
|
||||
read
|
||||
^^^^
|
||||
|
||||
@ -813,6 +847,17 @@ clear
|
||||
|
||||
If the *port/fn* argument is a string, then it specifies the name of a text file (.txt) and will delete all data from that text file.
|
||||
|
||||
getPortHandle
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. js:function:: getPortHandle(port)
|
||||
|
||||
:param number port: Port number
|
||||
|
||||
Get a handle to a Netscript Port. See more details here: :ref:`netscript_ports`
|
||||
|
||||
**WARNING:** Port Handles only work in :ref:`netscriptjs`. They will not work in :ref:`netscript1`.
|
||||
|
||||
rm
|
||||
^^
|
||||
|
||||
@ -879,30 +924,42 @@ getScriptRam
|
||||
getHackTime
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. js:function:: getHackTime(hostname/ip)
|
||||
.. js:function:: getHackTime(hostname/ip[, hackLvl=current level])
|
||||
|
||||
:param string hostname/ip: Hostname or IP of target server
|
||||
:param number hackLvl: Optional hacking level for the calculation. Defaults to player's current hacking level
|
||||
|
||||
Returns the amount of time in seconds it takes to execute the *hack()* Netscript function on the target server.
|
||||
|
||||
The function takes in an optional *hackLvl* parameter that can be specified
|
||||
to see what the hack time would be at different hacking levels.
|
||||
|
||||
getGrowTime
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. js:function:: getGrowTime(hostname/ip)
|
||||
.. js:function:: getGrowTime(hostname/ip[, hackLvl=current level])
|
||||
|
||||
:param string hostname/ip: Hostname or IP of target server
|
||||
:param number hackLvl: Optional hacking level for the calculation. Defaults to player's current hacking level
|
||||
|
||||
Returns the amount of time in seconds it takes to execute the *grow()* Netscript function on the target server.
|
||||
|
||||
The function takes in an optional *hackLvl* parameter that can be specified
|
||||
to see what the grow time would be at different hacking levels.
|
||||
|
||||
getWeakenTime
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. js:function:: getWeakenTime(hostname/ip)
|
||||
.. js:function:: getWeakenTime(hostname/ip[, hackLvl=current level])
|
||||
|
||||
:param string hostname/ip: Hostname or IP of target server
|
||||
:param number hackLvl: Optional hacking level for the calculation. Defaults to player's current hacking level
|
||||
|
||||
Returns the amount of time in seconds it takes to execute the *weaken()* Netscript function on the target server.
|
||||
|
||||
The function takes in an optional *hackLvl* parameter that can be specified
|
||||
to see what the weaken time would be at different hacking levels.
|
||||
|
||||
getScriptIncome
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -1,14 +1,18 @@
|
||||
.. _netscript_misc:
|
||||
|
||||
Netscript Miscellaneous
|
||||
=======================
|
||||
|
||||
.. _netscript_ports:
|
||||
|
||||
Netscript Ports
|
||||
---------------
|
||||
Netscript ports are endpoints that can be used to communicate between scripts.
|
||||
Netscript Ports are endpoints that can be used to communicate between scripts.
|
||||
A port is implemented as a sort of serialized queue, where you can only write
|
||||
and read one element at a time from the port. When you read data from a port,
|
||||
the element that is read is removed from the port.
|
||||
|
||||
The :js:func:`read`, :js:func:`write`, :js:func:`clear`, and :js:func:`peek`
|
||||
The :js:func:`read`, :js:func:`write`, :js:func:`tryWrite`, :js:func:`clear`, and :js:func:`peek`
|
||||
Netscript functions can be used to interact with ports.
|
||||
|
||||
Right now, there are only 20 ports for Netscript, denoted by the number 1
|
||||
@ -55,9 +59,11 @@ And the data in port 1 will look like::
|
||||
|
||||
**Port Handles**
|
||||
|
||||
WARNING: Port Handles only work in :ref:`netscriptjs`. They do not work in :ref:`netscript1`
|
||||
|
||||
The :js:func:`getPortHandle` Netscript function can be used to get a handle to a Netscript Port.
|
||||
This handle allows you to access several new port-related functions and the
|
||||
port's underlying data structure, which is just a Javascript array. The functions are:
|
||||
port's underlying data structure, which is just a JavaScript array. The functions are:
|
||||
|
||||
.. js:method:: NetscriptPort.write(data)
|
||||
|
||||
@ -205,36 +211,12 @@ to specify a namespace for the import::
|
||||
|
||||
Note that exporting functions is not required.
|
||||
|
||||
|
||||
Javascript Math Module
|
||||
----------------------
|
||||
|
||||
The `Javascript Math Module <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math>`_ is
|
||||
supported in Netscript and is used in the same way::
|
||||
|
||||
numThreads = Math.floor(getServerRam("foodnstuff")[1] / 3.4);
|
||||
|
||||
Javascript Date Module
|
||||
----------------------
|
||||
|
||||
The `Javascript Date Module <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date>`_ is supported in Netscript.
|
||||
However, since the 'new' operator does not work in Netscript, only the Date module's static functions can be used:
|
||||
|
||||
* now()
|
||||
* UTC()
|
||||
* Parse()
|
||||
* Maybe some others I don't know about
|
||||
|
||||
Example::
|
||||
|
||||
time = Date.now();
|
||||
|
||||
Javascript Number Module
|
||||
------------------------
|
||||
|
||||
The `Javascript Number module <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number>`_ is supported in Netscript.
|
||||
|
||||
Example::
|
||||
|
||||
tprint(Number.isInteger(1)); //True
|
||||
tprint(Number.isInteger(1.534059)); //False
|
||||
Standard, Built-In JavaScript Objects
|
||||
-------------------------------------
|
||||
Standard built-in JavaScript objects such as
|
||||
`Math <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math>`_,
|
||||
`Date <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date>`_,
|
||||
`Number <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number>`_,
|
||||
and others are supported as expected based on which version
|
||||
of Netscript you use (i.e. :ref:`netscript1` will support built-in objects that are
|
||||
defined in ES5, and :ref:`netscriptjs` will support whatever your browser supports).
|
||||
|
@ -410,6 +410,19 @@ getFactionFavorGain
|
||||
|
||||
This function returns the amount of favor you will gain for the specified faction when you reset by installing Augmentations.
|
||||
|
||||
donateToFaction
|
||||
---------------
|
||||
|
||||
.. js:function:: donateToFaction(factionName, donateAmt)
|
||||
|
||||
:param string factionName: Name of faction to donate to. CASE-SENSITIVE
|
||||
:param number donateAmt: Amount of money to donate
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.
|
||||
|
||||
Attempts to donate money to the specified faction in exchange for reputation.
|
||||
Returns true if you successfully donate the money, and false otherwise.
|
||||
|
||||
createProgram
|
||||
-------------
|
||||
|
||||
|
@ -412,3 +412,18 @@ Then it could be removed using::
|
||||
$ unalias "r"
|
||||
|
||||
It is not necessary to differentiate between global and non-global aliases when using 'unalias'
|
||||
|
||||
wget
|
||||
^^^^
|
||||
|
||||
$ wget [url] [target file]
|
||||
|
||||
Retrieves data from a url and downloads it to a file on the current server.
|
||||
The data can only be downloaded to a script (.script, .ns, .js) or a text file
|
||||
(.txt). If the target file already exists, it will be overwritten by this command.
|
||||
|
||||
Note that will not be possible to download data from many websites because they
|
||||
do not allow cross-origin origin sharing (CORS). This includes websites such
|
||||
as gist and pastebin. One notable site it will work on is rawgithub. Example::
|
||||
|
||||
$ wget https://raw.githubusercontent.com/danielyxie/bitburner/master/README.md game_readme.txt
|
||||
|
110
index.html
110
index.html
@ -8,13 +8,11 @@
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png">
|
||||
<link rel="manifest" href="dist/site.webmanifest">
|
||||
<link rel="mask-icon" href="dist/safari-pinned-tab.svg" color="#000000">
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
<meta name="apple-mobile-web-app-title" content="Bitburner">
|
||||
<meta name="application-name" content="Bitburner">
|
||||
<meta name="msapplication-TileColor" content="#000000">
|
||||
<meta name="msapplication-config" content="dist/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<link rel="stylesheet" type="text/css" href="dist/engine.css" />
|
||||
|
||||
<!-- Google Analytics -->
|
||||
<script>
|
||||
@ -22,11 +20,12 @@
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
</script>
|
||||
<script>
|
||||
ga('create', 'UA-100157497-1', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
</head>
|
||||
<link rel="shortcut icon" href="favicon.ico"><link href="dist/engine.css" rel="stylesheet"></head>
|
||||
<body>
|
||||
<div id="entire-game-container" style="visibility:hidden;">
|
||||
<div id="mainmenu-container">
|
||||
@ -188,9 +187,9 @@
|
||||
provides information about each script's production. The scripts are categorized by the hostname of the servers on which
|
||||
they are running. </p>
|
||||
<p id="active-scripts-total-prod">Total online production of
|
||||
Active scripts: <span id="active-scripts-total-production-active">$0.000</span> / sec<br />
|
||||
Total online production since last Aug installation: <span id="active-scripts-total-prod-aug-total">$0.000</span>
|
||||
(<span id="active-scripts-total-prod-aug-avg">$0.000</span> / sec)</p>
|
||||
Active scripts: <span class="money-gold"><span id="active-scripts-total-production-active">$0.000</span> / sec</span><br/>
|
||||
Total online production since last Aug installation: <span id="active-scripts-total-prod-aug-total" class="money-gold">$0.000</span>
|
||||
(<span class="money-gold"><span id="active-scripts-total-prod-aug-avg" class="money-gold">$0.000</span> / sec</span>)</p>
|
||||
<ul class="active-scripts-list" id="active-scripts-list" style="list-style: none;">
|
||||
</ul>
|
||||
</div>
|
||||
@ -202,20 +201,20 @@
|
||||
The Hacknet is a global, decentralized network of machines. It is used by hackers all around
|
||||
the world to anonymously share computing power and perform distributed cyberattacks without the
|
||||
fear of being traced.
|
||||
<br><br>
|
||||
<br/><br/>
|
||||
Here, you can purchase a Hacknet Node, a specialized machine that can connect and contribute its
|
||||
resources to the Hacknet network. This allows you to take a small percentage of profits
|
||||
from hacks performed on the network. Essentially, you are renting out your Node's computing power.
|
||||
<br><br>
|
||||
<br/><br/>
|
||||
Each Hacknet Node you purchase will passively earn you money. Each Hacknet Node can be upgraded
|
||||
in order to increase its computing power and thereby increase the profit you earn from it.
|
||||
</p>
|
||||
<a id="hacknet-nodes-purchase-button" class="a-link-button"> Purchase Hacknet Node </a>
|
||||
<br>
|
||||
<br/>
|
||||
<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>Money:</span><span id="hacknet-nodes-player-money" class="money-gold"></span><br/>
|
||||
<span>Total Hacknet Node Production:</span><span id="hacknet-nodes-total-production" class="money-gold"></span>
|
||||
</p>
|
||||
<span id="hacknet-nodes-multipliers">
|
||||
<a id="hacknet-nodes-1x-multiplier" class="a-link-button-inactive"> x1 </a>
|
||||
@ -452,7 +451,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>
|
||||
|
||||
@ -472,8 +471,7 @@
|
||||
|
||||
<!-- Tutorial content -->
|
||||
<div id="tutorial-container" class="generic-menupage-container">
|
||||
<a id="tutorial-getting-started-link" class="a-link-button"
|
||||
href="http://bitburner.wikia.com/wiki/Chapt3rs_Guide_to_Getting_Started_with_Bitburner" target="_blank"> Getting Started </a>
|
||||
<a id="tutorial-getting-started-link" class="a-link-button" href="http://bitburner.wikia.com/wiki/Chapt3rs_Guide_to_Getting_Started_with_Bitburner" target="_blank"> Getting Started </a>
|
||||
<a id="tutorial-networking-link" class="a-link-button"> Servers & Networking </a>
|
||||
<a id="tutorial-hacking-link" class="a-link-button"> Hacking </a>
|
||||
<a id="tutorial-scripts-link" class="a-link-button"> Scripts </a>
|
||||
@ -482,8 +480,7 @@
|
||||
<a id="tutorial-jobs-link" class="a-link-button"> Companies and Infiltration </a>
|
||||
<a id="tutorial-factions-link" class="a-link-button"> Factions </a>
|
||||
<a id="tutorial-augmentations-link" class="a-link-button"> Augmentations </a>
|
||||
<a id="tutorial-shortcuts-link" class="a-link-button"
|
||||
href="https://bitburner.wikia.com/wiki/Shortcuts" target="_blank"> Keyboard Shortcuts </a>
|
||||
<a id="tutorial-shortcuts-link" class="a-link-button" href="https://bitburner.wikia.com/wiki/Shortcuts" target="_blank"> Keyboard Shortcuts </a>
|
||||
|
||||
<a id="tutorial-back-button" class="a-link-button"> Back </a>
|
||||
<p id="tutorial-text"> </p>
|
||||
@ -625,9 +622,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>
|
||||
@ -673,7 +670,7 @@
|
||||
|
||||
<div id="stock-market-container" class="generic-menupage-container">
|
||||
<p>
|
||||
Welcome to the World Stock Exchange (WSE)! <br><br>
|
||||
Welcome to the World Stock Exchange (WSE)! <br/><br/>
|
||||
|
||||
To begin trading, you must first purchase an account. WSE accounts will persist
|
||||
after you 'reset' by installing Augmentations.
|
||||
@ -686,7 +683,7 @@
|
||||
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>
|
||||
<br/><br/>
|
||||
If you purchase access to the TIX API, you will retain that access even after
|
||||
you 'reset' by installing Augmentations.
|
||||
</p>
|
||||
@ -696,7 +693,7 @@
|
||||
<p>
|
||||
Four Sigma's (4S) Market Data Feed provides information about stocks
|
||||
that will help your trading strategies.
|
||||
<br><br>
|
||||
<br/><br/>
|
||||
If you purchase access to 4S Market Data and/or the 4S TIX API, you will
|
||||
retain that access even after you 'reset' by installing Augmentations.
|
||||
</p>
|
||||
@ -714,8 +711,8 @@
|
||||
<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>
|
||||
<br/><br/>
|
||||
<input id="stock-market-watchlist-filter" type="text" placeholder="Filter Stocks by symbol (comma-separated list)"/>
|
||||
<a id="stock-market-watchlist-filter-update" class="a-link-button"> Update Watchlist </a>
|
||||
<ul id="stock-market-list" style="list-style:none;">
|
||||
</ul>
|
||||
@ -756,7 +753,7 @@
|
||||
<p id="faction-invitation-box-text"> </p>
|
||||
<p id="faction-invitation-box-message"> </p>
|
||||
<p id="faction-invitation-box-warning">
|
||||
Would you like to join? <br> <br>
|
||||
Would you like to join? <br/> <br/>
|
||||
Warning: Joining this faction may prevent you from joining other factions during this run!
|
||||
</p>
|
||||
<span id="faction-invitation-box-yes" class="popup-box-button"> Yes </span>
|
||||
@ -769,8 +766,8 @@
|
||||
<div id="infiltration-box-content" class="popup-box-content">
|
||||
<p id="infiltration-box-text"> </p>
|
||||
|
||||
<span id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </span> <br><br>
|
||||
<select id="infiltration-faction-select"> </select> <br>
|
||||
<span id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </span> <br/><br/>
|
||||
<select id="infiltration-faction-select"> </select> <br/>
|
||||
<span id="infiltration-box-faction" class="a-link-button"> Give to Faction for Reputation </span>
|
||||
|
||||
</div>
|
||||
@ -856,7 +853,7 @@
|
||||
<div id="game-options-content" class="game-options-box">
|
||||
<span id="game-options-close-button">×</span>
|
||||
<h1> Game Options </h1>
|
||||
<br>
|
||||
<br/>
|
||||
<div id="game-options-left-panel">
|
||||
<!-- Netscript execution time -->
|
||||
<fieldset>
|
||||
@ -927,7 +924,7 @@
|
||||
<!-- Suppress faction invites -->
|
||||
<fieldset>
|
||||
<label for="settingsSuppressFactionInvites" class="tooltip">Suppress Faction Invites:
|
||||
<span class="tooltiptext">
|
||||
<span class="tooltiptexthigh">
|
||||
If this is set, then any faction invites you receive will not appear as popups
|
||||
on the screen. Your outstanding faction invites can be viewed in the 'Factions' page.
|
||||
</span>
|
||||
@ -938,7 +935,7 @@
|
||||
<!-- Suppress travel confirmation -->
|
||||
<fieldset>
|
||||
<label for="settingsSuppressTravelConfirmation" class="tooltip">Suppress Travel Confirmation:
|
||||
<span class="tooltiptext">
|
||||
<span class="tooltiptexthigh">
|
||||
If this is set, the confirmation message before traveling will not show up. You will automatically be deducted the travel cost as soon as you click.
|
||||
</span>
|
||||
</label>
|
||||
@ -949,7 +946,7 @@
|
||||
<!-- Suppress buy aug confirmation -->
|
||||
<fieldset>
|
||||
<label for="settingsSuppressBuyAugmentationConfirmation" class="tooltip">Suppress buy augmentation confirmation:
|
||||
<span class="tooltiptext">
|
||||
<span class="tooltiptexthigh">
|
||||
If this is set, the confirmation message before buying augmentation will not show up.
|
||||
</span>
|
||||
</label>
|
||||
@ -959,7 +956,7 @@
|
||||
<!-- Hospitalization Popup -->
|
||||
<fieldset>
|
||||
<label for="settingsSuppressHospitalizationPopup" class="tooltip">Suppress Hospitalization popup:
|
||||
<span class="tooltiptext">
|
||||
<span class="tooltiptexthigh">
|
||||
If this is set, a popup message will no longer be shown when you are hospitalized after taking too much damage.
|
||||
</span>
|
||||
</label>
|
||||
@ -969,7 +966,7 @@
|
||||
<!-- Disable Terminal and Navigation Shortcuts -->
|
||||
<fieldset>
|
||||
<label for="settingsDisableHotkeys" class="tooltip">Disable Hotkeys:
|
||||
<span class="tooltiptext">
|
||||
<span class="tooltiptexthigh">
|
||||
If this is set, then most hotkeys (keyboard shortcuts) in the game are disabled.
|
||||
This includes Terminal commands, hotkeys to navigate between different parts of the game,
|
||||
and the "Save and Close (Ctrl + b)" hotkey in the Text Editor.
|
||||
@ -978,6 +975,32 @@
|
||||
<input type="checkbox" name="settingsDisableHotkeys" id="settingsDisableHotkeys">
|
||||
</fieldset>
|
||||
|
||||
<!-- Locale for displaying numbers -->
|
||||
<fieldset>
|
||||
<label for="settingsLocale" class="tooltip">Locale:
|
||||
<span class="tooltiptexthigh">
|
||||
Sets the locale for displaying numbers. Defaults to 'en'
|
||||
</span>
|
||||
</label>
|
||||
<select name="settingsLocale" id="settingsLocale">
|
||||
<option value="en">en</option>
|
||||
<option value="bg">bg</option>
|
||||
<option value="cs">cs</option>
|
||||
<option value="da-dk">da-dk</option>
|
||||
<option value="de">de</option>
|
||||
<option value="en-au">en-au</option>
|
||||
<option value="en-gb">en-gb</option>
|
||||
<option value="es">es</option>
|
||||
<option value="fr">fr</option>
|
||||
<option value="hu">hu</option>
|
||||
<option value="it">it</option>
|
||||
<option value="lv">lv</option>
|
||||
<option value="no">no</option>
|
||||
<option value="pl">pl</option>
|
||||
<option value="ru">ru</option>
|
||||
</select>
|
||||
</fieldset>
|
||||
|
||||
<!-- Donate button -->
|
||||
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
|
||||
<input type="hidden" name="cmd" value="_s-xclick">
|
||||
@ -998,15 +1021,15 @@
|
||||
<a id="import-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Import Game </a>
|
||||
<a id="debug-delete-scripts-link" class="a-link-button tooltip" style="display:block;width:46%;">
|
||||
(DEBUG) Delete Active Scripts
|
||||
<span class="tooltiptext">
|
||||
<span class="tooltiptextleft">
|
||||
Debug option used to forcefully kill all active running scripts, in case there is a bug or some unexpected issue with the game. After
|
||||
using this, save the game and then reload the page.
|
||||
</span>
|
||||
</a>
|
||||
<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
|
||||
<span class="tooltiptextleft">
|
||||
Perform a soft reset. Resets everything as if you had just purchased an Augmentation.
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
@ -1018,8 +1041,15 @@
|
||||
<div id="loader" class="loaderoverlay">
|
||||
<div class="loaderspinner"></div>
|
||||
<div class="loaderlabel">Loading Bitburner...</div>
|
||||
<div id="killAllMessageWrapper" class="killAllMessage killAllMessageWrapperHidden">
|
||||
<script>setTimeout(function(){
|
||||
var w = document.getElementById('killAllMessageWrapper');
|
||||
if (w == null) {return;}
|
||||
w.classList.remove("killAllMessageWrapperHidden");
|
||||
w.classList.add("killAllMessageWrapperShow");
|
||||
}, 2000);</script>
|
||||
<p>If the game fails to load, consider <a href="?noScripts">killing all scripts</a></p>
|
||||
</div>
|
||||
<script src="dist/vendor.bundle.js"></script>
|
||||
<script src="dist/engine.bundle.js"></script>
|
||||
</body>
|
||||
</div>
|
||||
<script type="text/javascript" src="dist/vendor.bundle.js"></script><script type="text/javascript" src="dist/engine.bundle.js"></script></body>
|
||||
</html>
|
||||
|
12
netscript.js
12
netscript.js
@ -60,7 +60,7 @@ var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*";
|
||||
|
||||
let NetscriptFunctions =
|
||||
"hack|sleep|grow|weaken|print|tprint|scan|nuke|brutessh|ftpcrack|" + //Netscript functions
|
||||
"clearLog|disableLog|enableLog|" +
|
||||
"clearLog|disableLog|enableLog|isLogEnabled|getScriptLogs|" +
|
||||
"relaysmtp|httpworm|sqlinject|run|exec|spawn|kill|killall|exit|" +
|
||||
"scp|ls|hasRootAccess|" +
|
||||
"getIp|getHackingMultipliers|getBitNodeMultipliers|getStats|isBusy|" +
|
||||
@ -73,22 +73,28 @@ let NetscriptFunctions =
|
||||
"deleteServer|getPurchasedServers|" +
|
||||
"getPurchasedServerLimit|getPurchasedServerMaxRam|" +
|
||||
"getPurchasedServerCost|" +
|
||||
"purchaseServer|round|write|read|peek|clear|rm|getPortHandle|" +
|
||||
"purchaseServer|round|write|tryWrite|read|peek|clear|rm|getPortHandle|" +
|
||||
"scriptRunning|scriptKill|getScriptName|getScriptRam|" +
|
||||
"getHackTime|getGrowTime|getWeakenTime|getScriptIncome|getScriptExpGain|" +
|
||||
"getTimeSinceLastAug|prompt|" +
|
||||
|
||||
//Singularity Functions
|
||||
"universityCourse|getCharacterInformation|" +
|
||||
"gymWorkout|travelToCity|purchaseTor|purchaseProgram|upgradeHomeRam|" +
|
||||
"getUpgradeHomeRamCost|workForCompany|applyToCompany|getCompanyRep|" +
|
||||
"getCompanyFavor|stopAction|getFactionFavor|" +
|
||||
"getFavorToDonate|getFactionFavorGain|getCompanyFavorGain|" +
|
||||
"checkFactionInvitations|joinFaction|workForFaction|getFactionRep|" +
|
||||
"donateToFaction|" +
|
||||
"createProgram|commitCrime|getCrimeChance|getOwnedAugmentations|" +
|
||||
"getOwnedSourceFiles|getAugmentationsFromFaction|" +
|
||||
"getAugmentationCost|purchaseAugmentation|" +
|
||||
"installAugmentations|" +
|
||||
|
||||
//TIX API
|
||||
"getStockPrice|getStockPosition|buyStock|sellStock|shortStock|sellShort|" +
|
||||
"placeOrder|cancelOrder|" +
|
||||
|
||||
//Hacknet Node API
|
||||
"hacknet|numNodes|purchaseNode|getPurchaseNodeCost|getNodeStats|" +
|
||||
"upgradeLevel|upgradeRam|upgradeCore|getLevelUpgradeCost|" +
|
||||
@ -101,7 +107,7 @@ let NetscriptFunctions =
|
||||
"getActionMaxLevel|getActionCurrentLevel|getActionAutolevel|" +
|
||||
"setActionAutolevel|setActionLevel|" +
|
||||
"getRank|getSkillPoints|getSkillLevel|getSkillUpgradeCost|" +
|
||||
"upgradeSkill|getTeamSize|" +
|
||||
"upgradeSkill|getTeamSize|getCity|" +
|
||||
"setTeamSize|getCityEstimatedPopulation|getCityEstimatedCommunities|" +
|
||||
"getCityChaos|switchCity|getStamina|joinBladeburnerFaction|getBonusTime";
|
||||
|
||||
|
321
package-lock.json
generated
321
package-lock.json
generated
@ -608,6 +608,11 @@
|
||||
"postcss-value-parser": "3.3.0"
|
||||
}
|
||||
},
|
||||
"autosize": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/autosize/-/autosize-4.0.2.tgz",
|
||||
"integrity": "sha512-jnSyH2d+qdfPGpWlcuhGiHmqBJ6g3X+8T+iRwFrHPLVcdoGJE/x6Qicm6aDHfTsbgZKxyV8UU/YB2p4cjKDRRA=="
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
|
||||
@ -800,6 +805,12 @@
|
||||
"multicast-dns-service-types": "1.1.0"
|
||||
}
|
||||
},
|
||||
"boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
|
||||
"dev": true
|
||||
},
|
||||
"boom": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
|
||||
@ -1080,6 +1091,16 @@
|
||||
"integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
|
||||
"dev": true
|
||||
},
|
||||
"camel-case": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
|
||||
"integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"no-case": "2.3.2",
|
||||
"upper-case": "1.1.3"
|
||||
}
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
|
||||
@ -1679,6 +1700,23 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"clean-css": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
|
||||
"integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"source-map": "0.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli-cursor": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
|
||||
@ -2181,6 +2219,30 @@
|
||||
"source-list-map": "2.0.0"
|
||||
}
|
||||
},
|
||||
"css-select": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
|
||||
"integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boolbase": "1.0.0",
|
||||
"css-what": "2.1.0",
|
||||
"domutils": "1.5.1",
|
||||
"nth-check": "1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"domutils": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
|
||||
"integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dom-serializer": "0.1.0",
|
||||
"domelementtype": "1.3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"css-selector-tokenizer": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz",
|
||||
@ -2192,6 +2254,12 @@
|
||||
"regexpu-core": "1.0.0"
|
||||
}
|
||||
},
|
||||
"css-what": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz",
|
||||
"integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=",
|
||||
"dev": true
|
||||
},
|
||||
"cssesc": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz",
|
||||
@ -2524,6 +2592,23 @@
|
||||
"esutils": "2.0.2"
|
||||
}
|
||||
},
|
||||
"dom-converter": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz",
|
||||
"integrity": "sha1-pF71cnuJDJv/5tfIduexnLDhfzs=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"utila": "0.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"utila": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz",
|
||||
"integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
|
||||
@ -4790,12 +4875,86 @@
|
||||
"integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
|
||||
"dev": true
|
||||
},
|
||||
"html-minifier": {
|
||||
"version": "3.5.20",
|
||||
"resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.20.tgz",
|
||||
"integrity": "sha512-ZmgNLaTp54+HFKkONyLFEfs5dd/ZOtlquKaTnqIWFmx3Av5zG6ZPcV2d0o9XM2fXOTxxIf6eDcwzFFotke/5zA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camel-case": "3.0.0",
|
||||
"clean-css": "4.2.1",
|
||||
"commander": "2.17.1",
|
||||
"he": "1.1.1",
|
||||
"param-case": "2.1.1",
|
||||
"relateurl": "0.2.7",
|
||||
"uglify-js": "3.4.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.17.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
|
||||
"integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.4.8",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.8.tgz",
|
||||
"integrity": "sha512-WatYTD84gP/867bELqI2F/2xC9PQBETn/L+7RGq9MQOA/7yFBNvY1UwXqvtILeE6n0ITwBXxp34M0/o70dzj6A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "2.17.1",
|
||||
"source-map": "0.6.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"html-tags": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz",
|
||||
"integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=",
|
||||
"dev": true
|
||||
},
|
||||
"html-webpack-plugin": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz",
|
||||
"integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"html-minifier": "3.5.20",
|
||||
"loader-utils": "0.2.17",
|
||||
"lodash": "4.17.10",
|
||||
"pretty-error": "2.1.1",
|
||||
"tapable": "1.0.0",
|
||||
"toposort": "1.0.7",
|
||||
"util.promisify": "1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"json5": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
||||
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
|
||||
"dev": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "0.2.17",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz",
|
||||
"integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"big.js": "3.2.0",
|
||||
"emojis-list": "2.1.0",
|
||||
"json5": "0.5.1",
|
||||
"object-assign": "4.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "3.9.2",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
|
||||
@ -6380,6 +6539,12 @@
|
||||
"signal-exit": "3.0.2"
|
||||
}
|
||||
},
|
||||
"lower-case": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
|
||||
"integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=",
|
||||
"dev": true
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
|
||||
@ -6996,6 +7161,15 @@
|
||||
"integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==",
|
||||
"dev": true
|
||||
},
|
||||
"no-case": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
|
||||
"integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lower-case": "1.1.4"
|
||||
}
|
||||
},
|
||||
"node-forge": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
|
||||
@ -7603,6 +7777,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"nth-check": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz",
|
||||
"integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boolbase": "1.0.0"
|
||||
}
|
||||
},
|
||||
"num2fraction": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
|
||||
@ -7726,6 +7909,16 @@
|
||||
"object-keys": "1.0.11"
|
||||
}
|
||||
},
|
||||
"object.getownpropertydescriptors": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
|
||||
"integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "1.1.2",
|
||||
"es-abstract": "1.12.0"
|
||||
}
|
||||
},
|
||||
"object.omit": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
|
||||
@ -7926,6 +8119,15 @@
|
||||
"readable-stream": "2.3.4"
|
||||
}
|
||||
},
|
||||
"param-case": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
|
||||
"integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"no-case": "2.3.2"
|
||||
}
|
||||
},
|
||||
"parse-asn1": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
|
||||
@ -8979,6 +9181,16 @@
|
||||
"integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
|
||||
"dev": true
|
||||
},
|
||||
"pretty-error": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz",
|
||||
"integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"renderkid": "2.0.1",
|
||||
"utila": "0.4.0"
|
||||
}
|
||||
},
|
||||
"process": {
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||
@ -9355,6 +9567,12 @@
|
||||
"jsesc": "0.5.0"
|
||||
}
|
||||
},
|
||||
"relateurl": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
|
||||
"integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
|
||||
"dev": true
|
||||
},
|
||||
"remark": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz",
|
||||
@ -9417,6 +9635,81 @@
|
||||
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
|
||||
"dev": true
|
||||
},
|
||||
"renderkid": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz",
|
||||
"integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"css-select": "1.2.0",
|
||||
"dom-converter": "0.1.4",
|
||||
"htmlparser2": "3.3.0",
|
||||
"strip-ansi": "3.0.1",
|
||||
"utila": "0.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"domhandler": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz",
|
||||
"integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"domelementtype": "1.3.0"
|
||||
}
|
||||
},
|
||||
"domutils": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz",
|
||||
"integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"domelementtype": "1.3.0"
|
||||
}
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz",
|
||||
"integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"domelementtype": "1.3.0",
|
||||
"domhandler": "2.1.0",
|
||||
"domutils": "1.1.6",
|
||||
"readable-stream": "1.0.34"
|
||||
}
|
||||
},
|
||||
"isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
|
||||
"dev": true
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.0.34",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
||||
"integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"core-util-is": "1.0.2",
|
||||
"inherits": "2.0.3",
|
||||
"isarray": "0.0.1",
|
||||
"string_decoder": "0.10.31"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
|
||||
"dev": true
|
||||
},
|
||||
"utila": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz",
|
||||
"integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeat-element": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
|
||||
@ -11688,6 +11981,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"toposort": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz",
|
||||
"integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=",
|
||||
"dev": true
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz",
|
||||
@ -12227,6 +12526,12 @@
|
||||
"integrity": "sha512-d4SJySNBXDaQp+DPrziv3xGS6w3d2Xt69FijJr86zMPBy23JEloMCEOUBBzuN7xCtjLCnmB9tI/z7SBCahHBOw==",
|
||||
"dev": true
|
||||
},
|
||||
"upper-case": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
|
||||
"integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=",
|
||||
"dev": true
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||
@ -12372,6 +12677,22 @@
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"util.promisify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
|
||||
"integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "1.1.2",
|
||||
"object.getownpropertydescriptors": "2.0.3"
|
||||
}
|
||||
},
|
||||
"utila": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
|
||||
"integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=",
|
||||
"dev": true
|
||||
},
|
||||
"utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
|
@ -11,6 +11,7 @@
|
||||
"ajv": "^5.1.5",
|
||||
"ajv-keywords": "^2.0.0",
|
||||
"async": "^2.6.1",
|
||||
"autosize": "^4.0.2",
|
||||
"bluebird": "^3.5.1",
|
||||
"brace": "^0.11.1",
|
||||
"decimal.js": "7.2.3",
|
||||
@ -45,6 +46,7 @@
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-plugin-node": "^6.0.1",
|
||||
"file-loader": "^1.1.11",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"i18n-webpack-plugin": "^1.0.0",
|
||||
"istanbul": "^0.4.5",
|
||||
"js-beautify": "^1.5.10",
|
||||
|
@ -2,6 +2,7 @@ import {workerScripts,
|
||||
killWorkerScript} from "./NetscriptWorker";
|
||||
import {Player} from "./Player";
|
||||
import {getServer} from "./Server";
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {createAccordionElement} from "../utils/uiHelpers/createAccordionElement";
|
||||
import {arrayToString} from "../utils/helpers/arrayToString";
|
||||
@ -10,7 +11,6 @@ import {createProgressBarText} from "../utils/helpers/createProgressBarText"
|
||||
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
|
||||
import {getElementById} from "../utils/uiHelpers/getElementById";
|
||||
import {logBoxCreate} from "../utils/LogBox";
|
||||
import numeral from "numeral/min/numeral.min";
|
||||
import {formatNumber} from "../utils/StringHelperFunctions";
|
||||
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
import {removeElement} from "../utils/uiHelpers/removeElement";
|
||||
@ -242,9 +242,9 @@ function updateActiveScriptsItems(maxTasks=150) {
|
||||
}
|
||||
}
|
||||
|
||||
getElementById("active-scripts-total-production-active").innerText = numeral(total).format('$0.000a');
|
||||
getElementById("active-scripts-total-prod-aug-total").innerText = numeral(Player.scriptProdSinceLastAug).format('$0.000a');
|
||||
getElementById("active-scripts-total-prod-aug-avg").innerText = numeral(Player.scriptProdSinceLastAug / (Player.playtimeSinceLastAug/1000)).format('$0.000a');
|
||||
getElementById("active-scripts-total-production-active").innerText = numeralWrapper.format(total, '$0.000a');
|
||||
getElementById("active-scripts-total-prod-aug-total").innerText = numeralWrapper.format(Player.scriptProdSinceLastAug, '$0.000a');
|
||||
getElementById("active-scripts-total-prod-aug-avg").innerText = numeralWrapper.format(Player.scriptProdSinceLastAug / (Player.playtimeSinceLastAug/1000), '$0.000a');
|
||||
return total;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import {Faction, Factions, factionExists,
|
||||
import {Locations} from "./Locations";
|
||||
import {Player} from "./Player";
|
||||
import {hackWorldDaemon, redPillFlag} from "./RedPill";
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
import {KEY} from "../utils/helpers/keyCodes";
|
||||
|
||||
import {createProgressBarText} from "../utils/helpers/createProgressBarText";
|
||||
@ -14,7 +15,6 @@ import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver";
|
||||
import numeral from "numeral/min/numeral.min";
|
||||
import {addOffset} from "../utils/helpers/addOffset";
|
||||
import {appendLineBreaks} from "../utils/uiHelpers/appendLineBreaks";
|
||||
import {clearObject} from "../utils/helpers/clearObject";
|
||||
@ -44,9 +44,9 @@ var DifficultyToTimeFactor = 10; //Action Difficulty divided by this to ge
|
||||
var DiffMultExponentialFactor = 0.28;
|
||||
var DiffMultLinearFactor = 650;
|
||||
|
||||
var EffAgiLinearFactor = 90e3;
|
||||
var EffDexLinearFactor = 90e3;
|
||||
var EffAgiExponentialFactor = 0.031;
|
||||
var EffAgiLinearFactor = 40e3;
|
||||
var EffDexLinearFactor = 40e3;
|
||||
var EffAgiExponentialFactor = 0.032;
|
||||
var EffDexExponentialFactor = 0.03;
|
||||
|
||||
var BaseRecruitmentTimeNeeded = 300; //Base time needed (s) to complete a Recruitment action
|
||||
@ -659,7 +659,7 @@ function Bladeburner(params={}) {
|
||||
|
||||
this.storedCycles = 0;
|
||||
|
||||
this.randomEventCounter = getRandomInt(300, 600); //5-10 minutes
|
||||
this.randomEventCounter = getRandomInt(240, 600); //4-10 minutes
|
||||
|
||||
//These times are in seconds
|
||||
this.actionTimeToComplete = 0; //0 or -1 is an infinite running action (like training)
|
||||
@ -734,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(100, 500), countGrowth:getRandomInt(5, 75)/10,
|
||||
count:getRandomInt(25, 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
|
||||
@ -746,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(25, 750), countGrowth:getRandomInt(5, 75)/10,
|
||||
count:getRandomInt(5, 500), 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
|
||||
@ -758,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(50, 1000), countGrowth:getRandomInt(5,75)/10,
|
||||
count:getRandomInt(5, 500), 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
|
||||
@ -773,7 +773,7 @@ Bladeburner.prototype.create = function() {
|
||||
"You will NOT lose HP from failed Investigation ops.",
|
||||
baseDifficulty:400, difficultyFac:1.03,rewardFac:1.07,reqdRank:25,
|
||||
rankGain:2.2, rankLoss:0.2,
|
||||
count:getRandomInt(50, 200), countGrowth:getRandomInt(10, 40)/10,
|
||||
count:getRandomInt(1, 250), 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
|
||||
@ -786,7 +786,7 @@ Bladeburner.prototype.create = function() {
|
||||
"data.",
|
||||
baseDifficulty:500, difficultyFac:1.04, rewardFac:1.09, reqdRank:100,
|
||||
rankGain:4.4, rankLoss:0.4, hpLoss:2,
|
||||
count:getRandomInt(25, 300), countGrowth:getRandomInt(10, 40)/10,
|
||||
count:getRandomInt(1, 250), 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
|
||||
@ -797,7 +797,7 @@ Bladeburner.prototype.create = function() {
|
||||
"notorious Synthoid criminals.",
|
||||
baseDifficulty:650, difficultyFac:1.04, rewardFac:1.095, reqdRank:500,
|
||||
rankGain:5.5, rankLoss:0.5, hpLoss:2.5,
|
||||
count:getRandomInt(25,400), countGrowth:getRandomInt(3, 40)/10,
|
||||
count:getRandomInt(1, 300), 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
|
||||
@ -809,7 +809,7 @@ Bladeburner.prototype.create = function() {
|
||||
"in order for this Operation to be successful",
|
||||
baseDifficulty:800, difficultyFac:1.045, rewardFac:1.1, reqdRank:3000,
|
||||
rankGain:55,rankLoss:2.5,hpLoss:50,
|
||||
count:getRandomInt(25, 150), countGrowth:getRandomInt(2, 40)/10,
|
||||
count:getRandomInt(1, 200), 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
|
||||
@ -821,7 +821,7 @@ Bladeburner.prototype.create = function() {
|
||||
"drawing any attention. Stealth and discretion are key.",
|
||||
baseDifficulty:1000, difficultyFac:1.05, rewardFac:1.11, reqdRank:20e3,
|
||||
rankGain:22, rankLoss:2, hpLoss:10,
|
||||
count:getRandomInt(25, 250), countGrowth:getRandomInt(1, 20)/10,
|
||||
count:getRandomInt(1, 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
|
||||
@ -833,7 +833,7 @@ Bladeburner.prototype.create = function() {
|
||||
"in the Synthoid communities.",
|
||||
baseDifficulty:1500, difficultyFac:1.06, rewardFac:1.14, reqdRank:50e3,
|
||||
rankGain:44, rankLoss:4, hpLoss:5,
|
||||
count:getRandomInt(25, 200), countGrowth:getRandomInt(1, 20)/10,
|
||||
count:getRandomInt(1, 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
|
||||
@ -900,7 +900,7 @@ Bladeburner.prototype.process = function() {
|
||||
this.randomEventCounter -= seconds;
|
||||
if (this.randomEventCounter <= 0) {
|
||||
this.randomEvent();
|
||||
this.randomEventCounter = getRandomInt(300, 600);
|
||||
this.randomEventCounter = getRandomInt(240, 600);
|
||||
}
|
||||
|
||||
this.processAction(seconds);
|
||||
@ -1191,7 +1191,7 @@ Bladeburner.prototype.completeAction = function() {
|
||||
if (isOperation && this.logging.ops) {
|
||||
this.log(action.name + " successfully completed! Gained " + formatNumber(gain, 3) + " rank");
|
||||
} else if (!isOperation && this.logging.contracts) {
|
||||
this.log(action.name + " contract successfully completed! Gained " + formatNumber(gain, 3) + " rank and " + numeral(moneyGain).format("$0.000a"));
|
||||
this.log(action.name + " contract successfully completed! Gained " + formatNumber(gain, 3) + " rank and " + numeralWrapper.format(moneyGain, "$0.000a"));
|
||||
}
|
||||
}
|
||||
isOperation ? this.completeOperation(true) : this.completeContract(true);
|
||||
@ -2207,10 +2207,10 @@ Bladeburner.prototype.updateOverviewContent = function() {
|
||||
"Team Size: " + formatNumber(this.teamSize, 0) + "<br>" +
|
||||
"Team Members Lost: " + formatNumber(this.teamLost, 0) + "<br><br>" +
|
||||
"Num Times Hospitalized: " + this.numHosp + "<br>" +
|
||||
"Money Lost From Hospitalizations: " + numeral(this.moneyLost).format("$0.000a") + "<br><br>" +
|
||||
"Money Lost From Hospitalizations: " + numeralWrapper.format(this.moneyLost, "$0.000a") + "<br><br>" +
|
||||
"Current City: " + this.city + "<br>";
|
||||
|
||||
DomElems.overviewEstPop.childNodes[0].nodeValue = "Est. Synthoid Population: " + numeral(this.getCurrentCity().popEst).format("0.000a");
|
||||
DomElems.overviewEstPop.childNodes[0].nodeValue = "Est. Synthoid Population: " + numeralWrapper.format(this.getCurrentCity().popEst, "0.000a");
|
||||
DomElems.overviewEstComms.childNodes[0].nodeValue = "Est. Synthoid Communities: " + formatNumber(this.getCurrentCity().comms, 0);
|
||||
DomElems.overviewChaos.childNodes[0].nodeValue = "City Chaos: " + formatNumber(this.getCurrentCity().chaos);
|
||||
DomElems.overviewSkillPoints.innerText = "Skill Points: " + formatNumber(this.skillPoints, 0);
|
||||
@ -3703,7 +3703,7 @@ function initBladeburner() {
|
||||
name:SkillNames.Overclock,
|
||||
desc:"Each level of this skill decreases the time it takes " +
|
||||
"to attempt a Contract, Operation, and BlackOp by 1% (Max Level: 95)",
|
||||
baseCost:5, costInc:1, maxLvl:95,
|
||||
baseCost:5, costInc:1.1, maxLvl:95,
|
||||
actionTime:1
|
||||
});
|
||||
Skills[SkillNames.EvasiveSystem] = new Skill({
|
||||
|
@ -1,5 +1,6 @@
|
||||
import {Player} from "./Player";
|
||||
import numeral from "numeral/min/numeral.min";
|
||||
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
|
||||
function CharacterOverview() {
|
||||
this.hp = document.getElementById("character-hp-text");
|
||||
@ -33,7 +34,7 @@ CharacterOverview.prototype.update = function() {
|
||||
|
||||
let changed = false;
|
||||
changed = replaceAndChanged(this.hp, Player.hp + " / " + Player.max_hp) || changed;
|
||||
changed = replaceAndChanged(this.money, numeral(Player.money.toNumber()).format('($0.000a)')) || changed;
|
||||
changed = replaceAndChanged(this.money, numeralWrapper.format(Player.money.toNumber(), '($0.000a)')) || changed;
|
||||
changed = replaceAndChanged(this.hack, (Player.hacking_skill).toLocaleString()) || changed;
|
||||
changed = replaceAndChanged(this.str, (Player.strength).toLocaleString()) || changed;
|
||||
changed = replaceAndChanged(this.def, (Player.defense).toLocaleString()) || changed;
|
||||
|
@ -5,11 +5,12 @@ import {Locations} from "./Locations";
|
||||
import {Player} from "./Player";
|
||||
|
||||
import Decimal from "decimal.js";
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {clearSelector} from "../utils/uiHelpers/clearSelector";
|
||||
import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver";
|
||||
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";
|
||||
@ -453,46 +454,46 @@ var IndustryStartingCosts = {
|
||||
|
||||
var IndustryDescriptions = {
|
||||
Energy: "Engage in the production and distribution of energy.<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.Energy).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.Energy, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: NO",
|
||||
Utilities: "Distributes water and provides wastewater services.<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.Utilities).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.Utilities, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: NO",
|
||||
Agriculture: "Cultive crops and breed livestock to produce food.<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.Agriculture).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.Agriculture, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: YES",
|
||||
Fishing: "Produce food through the breeding and processing of fish and fish products<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.Fishing).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.Fishing, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: NO",
|
||||
Mining: "Extract and process metals from the earth.<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.Mining).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.Mining, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: NO",
|
||||
Food: "Create your own restaurants all around the world.<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.Food).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.Food, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: YES",
|
||||
Tobacco: "Create and distribute tobacco and tobacco-related products.<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.Tobacco).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.Tobacco, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: YES",
|
||||
Chemical: "Product industrial chemicals<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.Chemical).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.Chemical, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: NO",
|
||||
Pharmaceutical: "Discover, develop, and create new pharmaceutical drugs.<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.Pharmaceutical).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.Pharmaceutical, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: NO",
|
||||
Computer: "Develop and manufacture new computer hardware and networking infrastructures.<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.Computer).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.Computer, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: NO",
|
||||
Robotics: "Develop and create robots.<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.Robotics).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.Robotics, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: NO",
|
||||
Software: "Develop computer software and create AI Cores.<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.Software).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.Software, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: YES",
|
||||
Healthcare: "Create and manage hospitals.<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.Healthcare).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.Healthcare, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: NO",
|
||||
RealEstate: "Develop and manage real estate properties.<br><br>" +
|
||||
"Starting cost: " + numeral(IndustryStartingCosts.RealEstate).format("$0.000a") + "<br>" +
|
||||
"Starting cost: " + numeralWrapper.format(IndustryStartingCosts.RealEstate, "$0.000a") + "<br>" +
|
||||
"Recommended starting Industry: NO",
|
||||
}
|
||||
|
||||
@ -1776,7 +1777,7 @@ Employee.prototype.createUI = function(panel, corporation) {
|
||||
"Experience: " + formatNumber(this.exp, 3) + "<br>" +
|
||||
"Creativity: " + formatNumber(effCre, 3) + "<br>" +
|
||||
"Efficiency: " + formatNumber(effEff, 3) + "<br>" +
|
||||
"Salary: " + numeral(this.sal).format("$0.000a") + "/ s<br>",
|
||||
"Salary: " + numeralWrapper.format(this.sal, "$0.000a") + "/ s<br>",
|
||||
}));
|
||||
|
||||
//Selector for employee position
|
||||
@ -1826,7 +1827,7 @@ Employee.prototype.updateUI = function(panel, corporation) {
|
||||
"Experience: " + formatNumber(this.exp, 3) + "<br>" +
|
||||
"Creativity: " + formatNumber(effCre, 3) + "<br>" +
|
||||
"Efficiency: " + formatNumber(effEff, 3) + "<br>" +
|
||||
"Salary: " + numeral(this.sal).format("$0.000a") + "/ s<br>";
|
||||
"Salary: " + numeralWrapper.format(this.sal, "$0.000a") + "/ s<br>";
|
||||
}
|
||||
|
||||
Employee.prototype.toJSON = function() {
|
||||
@ -1963,7 +1964,7 @@ OfficeSpace.prototype.findEmployees = function(parentRefs) {
|
||||
"Experience: " + formatNumber(employee.exp, 1) + "<br>" +
|
||||
"Creativity: " + formatNumber(employee.cre, 1) + "<br>" +
|
||||
"Efficiency: " + formatNumber(employee.eff, 1) + "<br>" +
|
||||
"Salary: " + numeral(employee.sal).format('$0.000a') + " \ s<br>",
|
||||
"Salary: " + numeralWrapper.format(employee.sal, '$0.000a') + " \ s<br>",
|
||||
clickListener:()=>{
|
||||
office.hireEmployee(employee, parentRefs);
|
||||
removeElementById("cmpy-mgmt-hire-employee-popup");
|
||||
@ -2155,7 +2156,7 @@ Warehouse.prototype.createUI = function(parentRefs) {
|
||||
//Upgrade warehouse size button
|
||||
var upgradeCost = WarehouseUpgradeBaseCost * Math.pow(1.07, this.level+1);
|
||||
industryWarehouseUpgradeSizeButton = createElement("a", {
|
||||
innerText:"Upgrade Warehouse Size - " + numeral(upgradeCost).format('$0.000a'),
|
||||
innerText:"Upgrade Warehouse Size - " + numeralWrapper.format(upgradeCost, '$0.000a'),
|
||||
display:"inline-block",
|
||||
class: company.funds.lt(upgradeCost) ? "a-link-button-inactive" : "a-link-button",
|
||||
clickListener:()=>{
|
||||
@ -2721,9 +2722,9 @@ Warehouse.prototype.createProductUI = function(product, parentRefs) {
|
||||
"Aesthetics: " + formatNumber(product.aes, 3) + "<br>" +
|
||||
"Features: " + formatNumber(product.fea, 3) +
|
||||
cmpAndDmdText + "</span></p><br>" +
|
||||
"<p class='tooltip'>Est. Production Cost: " + numeral(product.pCost / ProductProductionCostRatio).format("$0.000a") +
|
||||
"<p class='tooltip'>Est. Production Cost: " + numeralWrapper.format(product.pCost / ProductProductionCostRatio, "$0.000a") +
|
||||
"<span class='tooltiptext'>An estimate of the material cost it takes to create this Product.</span></p><br>" +
|
||||
"<p class='tooltip'>Est. Market Price: " + numeral(product.pCost + product.rat / product.mku).format("$0.000a") +
|
||||
"<p class='tooltip'>Est. Market Price: " + numeralWrapper.format(product.pCost + product.rat / product.mku, "$0.000a") +
|
||||
"<span class='tooltiptext'>An estimate of how much consumers are willing to pay for this product. " +
|
||||
"Setting the sale price above this may result in less sales. Setting the sale price below this may result " +
|
||||
"in more sales.</span></p>"
|
||||
@ -2740,7 +2741,7 @@ Warehouse.prototype.createProductUI = function(product, parentRefs) {
|
||||
if (isString(product.sCost)) {
|
||||
sellInnerTextString += (" @ " + product.sCost);
|
||||
} else {
|
||||
sellInnerTextString += (" @ " + numeral(product.sCost).format("$0.000a"));
|
||||
sellInnerTextString += (" @ " + numeralWrapper.format(product.sCost, "$0.000a"));
|
||||
}
|
||||
}
|
||||
div.appendChild(createElement("a", {
|
||||
@ -3175,9 +3176,9 @@ Corporation.prototype.getInvestment = function() {
|
||||
noBtn.addEventListener("click", ()=>{
|
||||
return yesNoBoxClose();
|
||||
});
|
||||
yesNoBoxCreate("An investment firm has offered you " + numeral(funding).format('$0.000a') +
|
||||
" in funding in exchange for a " + numeral(percShares*100).format("0.000a") +
|
||||
"% stake in the company (" + numeral(investShares).format('0.000a') + " shares).<br><br>" +
|
||||
yesNoBoxCreate("An investment firm has offered you " + numeralWrapper.format(funding, '$0.000a') +
|
||||
" in funding in exchange for a " + numeralWrapper.format(percShares*100, "0.000a") +
|
||||
"% stake in the company (" + numeralWrapper.format(investShares, '0.000a') + " shares).<br><br>" +
|
||||
"Do you accept or reject this offer?");
|
||||
}
|
||||
|
||||
@ -3188,11 +3189,11 @@ Corporation.prototype.goPublic = function() {
|
||||
innerHTML: "Enter the number of shares you would like to issue " +
|
||||
"for your IPO. These shares will be publicly sold " +
|
||||
"and you will no longer own them. Your Corporation will receive " +
|
||||
numeral(initialSharePrice).format('$0.000a') + " per share " +
|
||||
numeralWrapper.format(initialSharePrice, '$0.000a') + " per share " +
|
||||
"(the IPO money will be deposited directly into your Corporation's funds).<br><br>" +
|
||||
"Furthermore, issuing more shares now will help drive up " +
|
||||
"your company's stock price in the future.<br><br>" +
|
||||
"You have a total of " + numeral(this.numShares).format("0.000a") + " of shares that you can issue.",
|
||||
"You have a total of " + numeralWrapper.format(this.numShares, "0.000a") + " of shares that you can issue.",
|
||||
});
|
||||
var yesBtn;
|
||||
var input = createElement("input", {
|
||||
@ -3635,7 +3636,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
innerHTML: "Enter the number of shares you would like to sell. The money from " +
|
||||
"selling your shares will go directly to you (NOT your Corporation). " +
|
||||
"The current price of your " +
|
||||
"company's stock is " + numeral(currentStockPrice).format("$0.000a"),
|
||||
"company's stock is " + numeralWrapper.format(currentStockPrice, "$0.000a"),
|
||||
});
|
||||
var profitIndicator = createElement("p", {});
|
||||
var input = createElement("input", {
|
||||
@ -3648,7 +3649,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
profitIndicator.innerText = "You don't have this many shares to sell!";
|
||||
} else {
|
||||
profitIndicator.innerText = "Sell " + numShares + " shares for a total of " +
|
||||
numeral(numShares * currentStockPrice).format('$0.000a');
|
||||
numeralWrapper.format(numShares * currentStockPrice, '$0.000a');
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -3702,7 +3703,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
innerHTML: "Enter the number of shares you would like to buy back at market price. To purchase " +
|
||||
"these shares, you must use your own money (NOT your Corporation's funds). " +
|
||||
"The current price of your " +
|
||||
"company's stock is " + numeral(currentStockPrice).format("$0.000a") +
|
||||
"company's stock is " + numeralWrapper.format(currentStockPrice, "$0.000a") +
|
||||
". Your company currently has " + formatNumber(this.issuedShares, 3) + " outstanding stock shares",
|
||||
});
|
||||
var costIndicator = createElement("p", {});
|
||||
@ -3719,7 +3720,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
} else {
|
||||
console.log("here");
|
||||
costIndicator.innerText = "Purchase " + numShares + " shares for a total of " +
|
||||
numeral(numShares * currentStockPrice).format('$0.000a');
|
||||
numeralWrapper.format(numShares * currentStockPrice, '$0.000a');
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -3734,7 +3735,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
dialogBoxCreate("ERROR: There are not this many oustanding shares to buy back");
|
||||
} else if (shares * tempStockPrice > Player.money) {
|
||||
dialogBoxCreate("ERROR: You do not have enough money to purchase this many shares (you need " +
|
||||
numeral(shares * tempStockPrice).format("$0.000a") + ")");
|
||||
numeralWrapper.format(shares * tempStockPrice, "$0.000a") + ")");
|
||||
} else {
|
||||
this.numShares += shares;
|
||||
if (isNaN(this.issuedShares)) {
|
||||
@ -3958,7 +3959,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
|
||||
upgradeContainer.appendChild(createElement("div", {
|
||||
class:"cmpy-mgmt-upgrade-div", width:"45%",
|
||||
innerHTML:upgrade[2] + " - " + numeral(upgrade[1]).format("$0.000a"),
|
||||
innerHTML:upgrade[2] + " - " + numeralWrapper.format(upgrade[1], "$0.000a"),
|
||||
tooltip: upgrade[3],
|
||||
clickListener:()=>{
|
||||
if (corp.funds.lt(upgrade[1])) {
|
||||
@ -3990,7 +3991,7 @@ Corporation.prototype.displayCorporationOverviewContent = function() {
|
||||
var cost = baseCost * Math.pow(priceMult, corp.upgrades[i]);
|
||||
upgradeContainer.appendChild(createElement("div", {
|
||||
class:"cmpy-mgmt-upgrade-div", width:"45%",
|
||||
innerHTML:upgrade[4] + " - " + numeral(cost).format("$0.000a"),
|
||||
innerHTML:upgrade[4] + " - " + numeralWrapper.format(cost, "$0.000a"),
|
||||
tooltip:upgrade[5],
|
||||
clickListener:()=>{
|
||||
if (corp.funds.lt(cost)) {
|
||||
@ -4018,14 +4019,14 @@ Corporation.prototype.updateCorporationOverviewContent = function() {
|
||||
totalExpenses = new Decimal(0);
|
||||
|
||||
var profit = this.revenue.minus(this.expenses).toNumber(),
|
||||
profitStr = profit >= 0 ? numeral(profit).format("$0.000a") : "-" + numeral(-1 * profit).format("$0.000a");
|
||||
profitStr = profit >= 0 ? numeralWrapper.format(profit, "$0.000a") : "-" + numeralWrapper.format(-1 * profit, "$0.000a");
|
||||
|
||||
var txt = "Total Funds: " + numeral(totalFunds.toNumber()).format('$0.000a') + "<br>" +
|
||||
"Total Revenue: " + numeral(this.revenue.toNumber()).format("$0.000a") + " / s<br>" +
|
||||
"Total Expenses: " + numeral(this.expenses.toNumber()).format("$0.000a") + "/ s<br>" +
|
||||
var txt = "Total Funds: " + numeralWrapper.format(totalFunds.toNumber(), '$0.000a') + "<br>" +
|
||||
"Total Revenue: " + numeralWrapper.format(this.revenue.toNumber(), "$0.000a") + " / s<br>" +
|
||||
"Total Expenses: " + numeralWrapper.format(this.expenses.toNumber(), "$0.000a") + "/ s<br>" +
|
||||
"Total Profits: " + profitStr + " / s<br>" +
|
||||
"Publicly Traded: " + (this.public ? "Yes" : "No") + "<br>" +
|
||||
"Owned Stock Shares: " + numeral(this.numShares).format('0.000a') + "<br>" +
|
||||
"Owned Stock Shares: " + numeralWrapper.format(this.numShares, '0.000a') + "<br>" +
|
||||
"Stock Price: " + (this.public ? "$" + formatNumber(this.sharePrice, 2) : "N/A") + "<br><br>";
|
||||
|
||||
var prodMult = this.getProductionMultiplier(),
|
||||
@ -4071,7 +4072,7 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
var popupId = "cmpy-mgmt-expand-city-popup";
|
||||
var text = createElement("p", {
|
||||
innerText: "Would you like to expand into a new city by opening an office? " +
|
||||
"This would cost " + numeral(OfficeInitialCost).format('$0.000a'),
|
||||
"This would cost " + numeralWrapper.format(OfficeInitialCost, '$0.000a'),
|
||||
});
|
||||
var citySelector = createElement("select", {class: "dropdown", margin:"5px"});
|
||||
for (var cityName in division.offices) {
|
||||
@ -4180,7 +4181,7 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
}
|
||||
industryOverviewUpgrades.appendChild(createElement("div", {
|
||||
class:"cmpy-mgmt-upgrade-div", display:"inline-block",
|
||||
innerHTML:upgrade[4] + ' - ' + numeral(cost).format("$0.000a"),
|
||||
innerHTML:upgrade[4] + ' - ' + numeralWrapper.format(cost, "$0.000a"),
|
||||
tooltip:upgrade[5],
|
||||
clickListener:()=>{
|
||||
if (corp.funds.lt(cost)) {
|
||||
@ -4428,7 +4429,7 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
var confirmBtn = createElement("a", {
|
||||
class: this.funds.lt(upgradeCost) ? "a-link-button-inactive" : "a-link-button",
|
||||
display:"inline-block", margin:"4px", innerText:"by 3",
|
||||
tooltip:numeral(upgradeCost).format("$0.000a"),
|
||||
tooltip:numeralWrapper.format(upgradeCost, "$0.000a"),
|
||||
clickListener:()=>{
|
||||
if (this.funds.lt(upgradeCost)) {
|
||||
dialogBoxCreate("You don't have enough company funds to purchase this upgrade!");
|
||||
@ -4445,7 +4446,7 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
var confirmBtn15 = createElement("a", {
|
||||
class: this.funds.lt(upgradeCost15) ? "a-link-button-inactive" : "a-link-button",
|
||||
display:"inline-block", margin:"4px", innerText:"by 15",
|
||||
tooltip:numeral(upgradeCost15).format("$0.000a"),
|
||||
tooltip:numeralWrapper.format(upgradeCost15, "$0.000a"),
|
||||
clickListener:()=>{
|
||||
if (this.funds.lt(upgradeCost15)) {
|
||||
dialogBoxCreate("You don't have enough company funds to purchase this upgrade!");
|
||||
@ -4462,7 +4463,7 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
var confirmBtnMax = createElement("a", {
|
||||
class:this.funds.lt(upgradeCostMax) ? "a-link-button-inactive" : "a-link-button",
|
||||
display:"inline-block", margin:"4px", innerText:"by MAX (" + maxNum*OfficeInitialSize + ")",
|
||||
tooltip:numeral(upgradeCostMax).format("$0.000a"),
|
||||
tooltip:numeralWrapper.format(upgradeCostMax, "$0.000a"),
|
||||
clickListener:()=>{
|
||||
if (this.funds.lt(upgradeCostMax)) {
|
||||
dialogBoxCreate("You don't have enough company funds to purchase this upgrade!");
|
||||
@ -4511,7 +4512,7 @@ Corporation.prototype.displayDivisionContent = function(division, city) {
|
||||
totalCostTxt.innerText = "Invalid value entered!"
|
||||
} else {
|
||||
var totalCost = input.value * office.employees.length;
|
||||
totalCostTxt.innerText = "Throwing this party will cost a total of " + numeral(totalCost).format('$0.000a');
|
||||
totalCostTxt.innerText = "Throwing this party will cost a total of " + numeralWrapper.format(totalCost, '$0.000a');
|
||||
}
|
||||
},
|
||||
onkeyup:(e)=>{
|
||||
@ -4726,7 +4727,7 @@ Corporation.prototype.updateDivisionContent = function(division) {
|
||||
var vechain = (this.unlockUpgrades[4] === 1);
|
||||
//Industry Overview Text
|
||||
var profit = division.lastCycleRevenue.minus(division.lastCycleExpenses).toNumber(),
|
||||
profitStr = profit >= 0 ? numeral(profit).format("$0.000a") : "-" + numeral(-1 * profit).format("$0.000a");
|
||||
profitStr = profit >= 0 ? numeralWrapper.format(profit, "$0.000a") : "-" + numeralWrapper.format(-1 * profit, "$0.000a");
|
||||
var advertisingInfo = "";
|
||||
if (vechain) {
|
||||
var advertisingFactors = division.getAdvertisingFactors();
|
||||
@ -4745,12 +4746,12 @@ Corporation.prototype.updateDivisionContent = function(division) {
|
||||
|
||||
removeChildrenFromElement(industryOverviewText);
|
||||
industryOverviewText.appendChild(createElement("p", {
|
||||
innerHTML:"Industry: " + division.type + " (Corp Funds: " + numeral(this.funds.toNumber()).format("$0.000a") + ")<br><br>" +
|
||||
innerHTML:"Industry: " + division.type + " (Corp Funds: " + numeralWrapper.format(this.funds.toNumber(), "$0.000a") + ")<br><br>" +
|
||||
"Awareness: " + formatNumber(division.awareness, 3) + "<br>" +
|
||||
"Popularity: " + formatNumber(division.popularity, 3) + "<br>" +
|
||||
advertisingInfo + "<br>" +
|
||||
"Revenue: " + numeral(division.lastCycleRevenue.toNumber()).format("$0.000a") + " / s<br>" +
|
||||
"Expenses: " + numeral(division.lastCycleExpenses.toNumber()).format("$0.000a") + " /s<br>" +
|
||||
"Revenue: " + numeralWrapper.format(division.lastCycleRevenue.toNumber(), "$0.000a") + " / s<br>" +
|
||||
"Expenses: " + numeralWrapper.format(division.lastCycleExpenses.toNumber(), "$0.000a") + " /s<br>" +
|
||||
"Profit: " + profitStr + " / s<br><br>"
|
||||
}));
|
||||
industryOverviewText.appendChild(createElement("p", {
|
||||
|
@ -1,11 +1,14 @@
|
||||
let CONSTANTS = {
|
||||
Version: "0.40.2",
|
||||
Version: "0.40.3",
|
||||
|
||||
//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
|
||||
//the player will have this level assuming no multipliers. Multipliers can cause skills to go above this.
|
||||
MaxSkillLevel: 975,
|
||||
|
||||
//Milliseconds per game cycle
|
||||
MilliPerCycle: 200,
|
||||
|
||||
//How much reputation is needed to join a megacorporation's faction
|
||||
CorpFactionRepRequirement: 200e3,
|
||||
|
||||
@ -32,6 +35,7 @@ let CONSTANTS = {
|
||||
|
||||
/* Faction and Company favor */
|
||||
BaseFavorToDonate: 150,
|
||||
DonateMoneyToRepDivisor: 1e6,
|
||||
FactionReputationToFavorBase: 500,
|
||||
FactionReputationToFavorMult: 1.02,
|
||||
CompanyReputationToFavorBase: 500,
|
||||
@ -493,33 +497,31 @@ let CONSTANTS = {
|
||||
"World Stock Exchange account and TIX API Access<br>",
|
||||
|
||||
LatestUpdate:
|
||||
"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>"
|
||||
|
||||
`v0.40.3<br>
|
||||
-----------------------------------------------<br>
|
||||
* Bladeburner Changes:<br>
|
||||
*** Increased the effect that agi and dexterity have on action time<br>
|
||||
*** Starting number of contracts/operations available will be slightly lower<br>
|
||||
*** Random events will now happen slightly more often<br>
|
||||
*** Slightly increased the rate at which the Overclock skill point cost increases<br>
|
||||
-----------------------------------------------<br>
|
||||
* The maximum volatility of stocks is now randomized (randomly generated within a certain range every time the game resets)<br>
|
||||
* Increased the range of possible values for initial stock prices<br>
|
||||
* b1t_flum3.exe program can now be created immediately at Hacking level 1 (rather than hacking level 5)<br>
|
||||
* UI improvements for the character overview panel and the left-hand menu (by mat-jaworski)<br>
|
||||
* General UI improvements for displays and Terminal (by mat-jaworski)<br>
|
||||
* Added optional parameters to the getHackTime(), getGrowTime(), and getWeakenTime() Netscript functions<br>
|
||||
* Added isLogEnabled() and getScriptLogs() Netscript functions<br>
|
||||
* Added donateToFaction() Singularity function<br>
|
||||
* Updated documentation to reflect the fact that Netscript port handles (getPortHandle()) only works in NetscriptJS (2.0), NOT Netscript 1.0<br>
|
||||
* Added tryWrite() Netscript function<br>
|
||||
* When working (for a company/faction), experience is gained immediately/continuously rather than all at once when the work is finished<br>
|
||||
* Added a setting in .fconf for enabling line-wrap in the Terminal input<br>
|
||||
* Adding a game option for changing the locale that most numbers are displayed in (this mostly applies for whenever money is displayed)<br>
|
||||
* The randomized parameters of many high-level servers can now take on a higher range of values<br>
|
||||
* Many 'foreign' servers (hackable servers that you don't own) now have a randomized amount of RAM<br>
|
||||
* Added 'wget' Terminal command<br>
|
||||
* Improved the introductory tutorial`
|
||||
}
|
||||
|
||||
export {CONSTANTS};
|
||||
|
@ -83,9 +83,9 @@ const Programs = {
|
||||
time: CONSTANTS.MillisecondsPerQuarterHour,
|
||||
}),
|
||||
BitFlume: new Program("b1t_flum3.exe", {
|
||||
level: 5,
|
||||
level: 1,
|
||||
tooltip:"This program creates a portal to the BitNode Nexus (allows you to restart and switch BitNodes)",
|
||||
req: function() {return Player.sourceFiles.length > 0 && Player.hacking_skill >= 5},
|
||||
req: function() {return Player.sourceFiles.length > 0 && Player.hacking_skill >= 1},
|
||||
time: CONSTANTS.MillisecondsPerFiveMinutes / 5,
|
||||
}),
|
||||
// special because you can't create it.
|
||||
|
@ -10,13 +10,13 @@ import {Player} from "./Player";
|
||||
import {Settings} from "./Settings";
|
||||
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {factionInvitationBoxCreate} from "../utils/FactionInvitationBox";
|
||||
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver";
|
||||
import numeral from "numeral/min/numeral.min";
|
||||
import {formatNumber} from "../utils/StringHelperFunctions";
|
||||
import {yesNoBoxCreate, yesNoBoxGetYesButton,
|
||||
yesNoBoxGetNoButton, yesNoBoxClose} from "../utils/YesNoBox";
|
||||
@ -319,7 +319,7 @@ function displayFactionContent(factionName) {
|
||||
if (isNaN(amt)) {
|
||||
donateRepGain.innerText = "Invalid donate amount entered!";
|
||||
} else {
|
||||
var repGain = amt / 1e6 * Player.faction_rep_mult;
|
||||
var repGain = amt / CONSTANTS.DonateMoneyToRepDivisor * Player.faction_rep_mult;
|
||||
donateRepGain.innerText = "This donation will result in " +
|
||||
formatNumber(repGain, 3) + " reputation gain";
|
||||
}
|
||||
@ -335,9 +335,9 @@ function displayFactionContent(factionName) {
|
||||
dialogBoxCreate("You cannot afford to donate this much money!");
|
||||
} else {
|
||||
Player.loseMoney(amt);
|
||||
var repGain = amt / 1e6 * Player.faction_rep_mult;
|
||||
var repGain = amt / CONSTANTS.DonateMoneyToRepDivisor * Player.faction_rep_mult;
|
||||
faction.playerReputation += repGain;
|
||||
dialogBoxCreate("You just donated " + numeral(amt).format("$0.000a") + " to " +
|
||||
dialogBoxCreate("You just donated " + numeralWrapper.format(amt, "$0.000a") + " to " +
|
||||
faction.name + " to gain " + formatNumber(repGain, 3) + " reputation");
|
||||
displayFactionContent(factionName);
|
||||
}
|
||||
@ -603,10 +603,10 @@ function createFactionAugmentationDisplayElements(augmentationsList, augs, facti
|
||||
pElem.innerHTML = "ALREADY OWNED";
|
||||
} else if (faction.playerReputation >= req) {
|
||||
aElem.setAttribute("class", "a-link-button");
|
||||
pElem.innerHTML = "UNLOCKED - " + numeral(aug.baseCost * factionInfo.augmentationPriceMult).format("$0.000a");
|
||||
pElem.innerHTML = "UNLOCKED - " + numeralWrapper.format(aug.baseCost * factionInfo.augmentationPriceMult, "$0.000a");
|
||||
} else {
|
||||
aElem.setAttribute("class", "a-link-button-inactive");
|
||||
pElem.innerHTML = "LOCKED (Requires " + formatNumber(req, 1) + " faction reputation) - " + numeral(aug.baseCost * factionInfo.augmentationPriceMult).format("$0.000a");
|
||||
pElem.innerHTML = "LOCKED (Requires " + formatNumber(req, 1) + " faction reputation) - " + numeralWrapper.format(aug.baseCost * factionInfo.augmentationPriceMult, "$0.000a");
|
||||
pElem.style.color = "red";
|
||||
}
|
||||
aDiv.appendChild(aElem);
|
||||
|
@ -66,26 +66,43 @@ class FactionInfo {
|
||||
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),
|
||||
"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),
|
||||
[],
|
||||
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),
|
||||
[],
|
||||
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),
|
||||
"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 " +
|
||||
@ -93,66 +110,110 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
"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),
|
||||
[],
|
||||
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),
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
"Blade Industries": new FactionInfo(
|
||||
"Augmentation is salvation",
|
||||
[], true, true, true, true),
|
||||
[],
|
||||
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 " +
|
||||
"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),
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
|
||||
"Clarke Incorporated": new FactionInfo(
|
||||
"Unlocking the power of the genome",
|
||||
[], true, true, true, true),
|
||||
[],
|
||||
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),
|
||||
[],
|
||||
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),
|
||||
"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),
|
||||
[],
|
||||
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),
|
||||
[],
|
||||
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 " +
|
||||
"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),
|
||||
[],
|
||||
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>" +
|
||||
"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),
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false),
|
||||
|
||||
NiteSec: new FactionInfo(
|
||||
" __..__ <br>" +
|
||||
@ -190,40 +251,108 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
" d .dNITESEC $ | <br>" +
|
||||
" :bp.__.gNITESEC$$ :$ ; <br>" +
|
||||
" NITESECNITESECNIT $$b : <br>",
|
||||
[], true, true, false, false),
|
||||
[],
|
||||
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 Tokyo",
|
||||
"Ishima",
|
||||
"Volhaven",
|
||||
],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
Chongqing: new FactionInfo(
|
||||
"Serve the people",
|
||||
["Sector-12", "Aevum", "Volhaven"], true, true, true, true),
|
||||
[
|
||||
"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),
|
||||
[
|
||||
"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",
|
||||
"Aevum",
|
||||
"Volhaven",
|
||||
],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true),
|
||||
"Sector-12": new FactionInfo(
|
||||
"The City of the Future",
|
||||
["Chongqing", "New Tokyo", "Ishima", "Volhaven"], true, true, true, true),
|
||||
[
|
||||
"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),
|
||||
[
|
||||
"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),
|
||||
[],
|
||||
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),
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false),
|
||||
|
||||
"The Syndicate": new FactionInfo(
|
||||
"Honor holds you back",
|
||||
[], true, true, true, true),
|
||||
[],
|
||||
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 " +
|
||||
@ -231,35 +360,64 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
"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),
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false),
|
||||
|
||||
Tetrads: new FactionInfo(
|
||||
"Following the Mandate of Heaven and Carrying out the Way",
|
||||
[], false, false, true, true),
|
||||
[],
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true),
|
||||
|
||||
"Slum Snakes": new FactionInfo(
|
||||
"Slum Snakes rule!",
|
||||
[], false, false, true, true),
|
||||
[],
|
||||
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),
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false),
|
||||
|
||||
"Tian Di Hui": new FactionInfo(
|
||||
"Obey Heaven and Work Righteousness",
|
||||
[], true, true, false, true),
|
||||
[],
|
||||
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),
|
||||
"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),
|
||||
"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),
|
||||
};
|
||||
|
@ -3,6 +3,7 @@ import {parse, Node} from "../utils/acorn";
|
||||
var FconfSettings = {
|
||||
ENABLE_BASH_HOTKEYS: false,
|
||||
ENABLE_TIMESTAMPS: false,
|
||||
WRAP_INPUT: false,
|
||||
}
|
||||
|
||||
var FconfComments = {
|
||||
@ -15,6 +16,11 @@ var FconfComments = {
|
||||
"http://bitburner.readthedocs.io/en/latest/shortcuts.html",
|
||||
ENABLE_TIMESTAMPS: "Terminal commands and log entries will be timestamped. The timestamp\n" +
|
||||
"will have the format: M/D h:m",
|
||||
WRAP_INPUT: "Wrap Terminal Input. If this is enabled, then when a Terminal command is\n" +
|
||||
"too long and overflows, then it will wrap to the next line instead of\n" +
|
||||
"side-scrolling\n\n" +
|
||||
"Note that after you enable/disable this, you'll have to run a command\n" +
|
||||
"before its effect takes place.",
|
||||
}
|
||||
|
||||
//Parse Fconf settings from the config text
|
||||
@ -74,6 +80,7 @@ function parseFconfSetting(setting, value) {
|
||||
switch(setting) {
|
||||
case "ENABLE_BASH_HOTKEYS":
|
||||
case "ENABLE_TIMESTAMPS":
|
||||
case "WRAP_INPUT":
|
||||
var value = value.toLowerCase();
|
||||
if (value === "1" || value === "true" || value === "y") {
|
||||
value = true;
|
||||
|
16
src/Gang.js
16
src/Gang.js
@ -3,6 +3,7 @@ import {Engine} from "./engine";
|
||||
import {Faction, Factions,
|
||||
displayFactionContent} from "./Faction";
|
||||
import {Player} from "./Player";
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver";
|
||||
@ -10,7 +11,6 @@ import {createAccordionElement} from "../utils/uiHelpers/createA
|
||||
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";
|
||||
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
@ -892,7 +892,7 @@ function createGangMemberUpgradePanel(memberObj) {
|
||||
var upg = upgradeArray[j];
|
||||
(function (upg, div, memberObj) {
|
||||
div.appendChild(createElement("a", {
|
||||
innerText:upg.name + " - " + numeral(upg.cost).format("$0.000a"),
|
||||
innerText:upg.name + " - " + numeralWrapper.format(upg.cost, "$0.000a"),
|
||||
class:"a-link-button", margin:"2px", padding:"2px", display:"block",
|
||||
fontSize:"12px",
|
||||
tooltip:upg.desc,
|
||||
@ -1411,12 +1411,12 @@ function updateGangMemberDisplayElement(memberObj) {
|
||||
var stats = document.getElementById(name + "gang-member-stats-text");
|
||||
if (stats) {
|
||||
stats.innerHTML =
|
||||
"Hacking: " + formatNumber(memberObj.hack, 0) + " (" + numeral(memberObj.hack_exp).format('(0.00a)') + " exp)<br>" +
|
||||
"Strength: " + formatNumber(memberObj.str, 0) + " (" + numeral(memberObj.str_exp).format('(0.00a)') + " exp)<br>" +
|
||||
"Defense: " + formatNumber(memberObj.def, 0) + " (" + numeral(memberObj.def_exp).format('(0.00a)') + " exp)<br>" +
|
||||
"Dexterity: " + formatNumber(memberObj.dex, 0) + " (" + numeral(memberObj.dex_exp).format('(0.00a)') + " exp)<br>" +
|
||||
"Agility: " + formatNumber(memberObj.agi, 0) + " (" + numeral(memberObj.agi_exp).format('(0.00a)') + " exp)<br>" +
|
||||
"Charisma: " + formatNumber(memberObj.cha, 0) + " (" + numeral(memberObj.cha_exp).format('(0.00a)') + " exp)<br>";
|
||||
"Hacking: " + formatNumber(memberObj.hack, 0) + " (" + numeralWrapper.format(memberObj.hack_exp, '(0.00a)') + " exp)<br>" +
|
||||
"Strength: " + formatNumber(memberObj.str, 0) + " (" + numeralWrapper.format(memberObj.str_exp, '(0.00a)') + " exp)<br>" +
|
||||
"Defense: " + formatNumber(memberObj.def, 0) + " (" + numeralWrapper.format(memberObj.def_exp, '(0.00a)') + " exp)<br>" +
|
||||
"Dexterity: " + formatNumber(memberObj.dex, 0) + " (" + numeralWrapper.format(memberObj.dex_exp, '(0.00a)') + " exp)<br>" +
|
||||
"Agility: " + formatNumber(memberObj.agi, 0) + " (" + numeralWrapper.format(memberObj.agi_exp, '(0.00a)') + " exp)<br>" +
|
||||
"Charisma: " + formatNumber(memberObj.cha, 0) + " (" + numeralWrapper.format(memberObj.cha_exp, '(0.00a)') + " exp)<br>";
|
||||
}
|
||||
|
||||
var gainInfo = document.getElementById(name + "gang-member-gain-info");
|
||||
|
92
src/Hacking.js
Normal file
92
src/Hacking.js
Normal file
@ -0,0 +1,92 @@
|
||||
import { BitNodeMultipliers } from "./BitNodeMultipliers";
|
||||
import { Player } from "./Player";
|
||||
import { Server } from "./Server";
|
||||
|
||||
/**
|
||||
* Returns the chance the player has to successfully hack a server
|
||||
*/
|
||||
export function calculateHackingChance(server) {
|
||||
const hackFactor = 1.75;
|
||||
const intFactor = 0.2;
|
||||
const difficultyMult = (100 - server.hackDifficulty) / 100;
|
||||
const skillMult = (hackFactor * Player.hacking_skill) + (intFactor * Player.intelligence);
|
||||
const skillChance = (skillMult - server.requiredHackingSkill) / skillMult;
|
||||
const chance = skillChance * difficultyMult * Player.hacking_chance_mult;
|
||||
if (chance > 1) { return 1; }
|
||||
if (chance < 0) { return 0; }
|
||||
|
||||
return chance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of hacking experience the player will gain upon
|
||||
* successfully hacking a server
|
||||
*/
|
||||
export function calculateHackingExpGain(server) {
|
||||
const baseExpGain = 3;
|
||||
const diffFactor = 0.3;
|
||||
if (server.baseDifficulty == null) {
|
||||
server.baseDifficulty = server.hackDifficulty;
|
||||
}
|
||||
var expGain = baseExpGain;
|
||||
expGain += (server.baseDifficulty * Player.hacking_exp_mult * diffFactor);
|
||||
|
||||
return expGain * BitNodeMultipliers.HackExpGain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the percentage of money that will be stolen from a server if
|
||||
* it is successfully hacked (returns the decimal form, not the actual percent value)
|
||||
*/
|
||||
export function calculatePercentMoneyHacked(server) {
|
||||
// Adjust if needed for balancing. This is the divisor for the final calculation
|
||||
const balanceFactor = 240;
|
||||
|
||||
const difficultyMult = (100 - server.hackDifficulty) / 100;
|
||||
const skillMult = (Player.hacking_skill - (server.requiredHackingSkill - 1)) / Player.hacking_skill;
|
||||
const percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / balanceFactor;
|
||||
if (percentMoneyHacked < 0) { return 0; }
|
||||
if (percentMoneyHacked > 1) { return 1; }
|
||||
|
||||
return percentMoneyHacked * BitNodeMultipliers.ScriptHackMoney;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns time it takes to complete a hack on a server, in seconds
|
||||
*/
|
||||
export function calculateHackingTime(server, hack, int) {
|
||||
const difficultyMult = server.requiredHackingSkill * server.hackDifficulty;
|
||||
|
||||
const baseDiff = 500;
|
||||
const baseSkill = 50;
|
||||
const diffFactor = 2.5;
|
||||
const intFactor = 0.1;
|
||||
if (hack == null) {hack = Player.hacking_skill;}
|
||||
if (int == null) {int = Player.intelligence;}
|
||||
var skillFactor = (diffFactor * difficultyMult + baseDiff);
|
||||
// tslint:disable-next-line
|
||||
skillFactor /= (hack + baseSkill + (intFactor * int));
|
||||
|
||||
const hackTimeMultiplier = 5;
|
||||
const hackingTime = hackTimeMultiplier * skillFactor / Player.hacking_speed_mult;
|
||||
|
||||
return hackingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns time it takes to complete a grow operation on a server, in seconds
|
||||
*/
|
||||
export function calculateGrowTime(server, hack, int) {
|
||||
const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2
|
||||
|
||||
return growTimeMultiplier * calculateHackingTime(server, hack, int);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns time it takes to complete a weaken operation on a server, in seconds
|
||||
*/
|
||||
export function calculateWeakenTime(server, hack, int) {
|
||||
const weakenTimeMultiplier = 4; // Relative to hacking time
|
||||
|
||||
return weakenTimeMultiplier * calculateHackingTime(server, hack, int);
|
||||
}
|
@ -2,7 +2,7 @@ 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";
|
||||
@ -245,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;
|
||||
@ -446,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) {
|
||||
@ -548,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);
|
||||
|
@ -32,7 +32,8 @@ export const TerminalHelpText: string =
|
||||
"tail [script] [args...] Displays dynamic logs for the specified script<br>" +
|
||||
"theme [preset] | bg txt hlgt Change the color scheme of the UI<br>" +
|
||||
"top Displays all running scripts and their RAM usage<br>" +
|
||||
'unalias "[alias name]" Deletes the specified alias<br>';
|
||||
'unalias "[alias name]" Deletes the specified alias<br>' +
|
||||
"wget [url] [target file] Retrieves code/text from a web server<br>";
|
||||
|
||||
interface IMap<T> {
|
||||
[key: string]: T;
|
||||
@ -214,5 +215,11 @@ export const HelpTexts: IMap<string> = {
|
||||
"Then it could be removed using:<br><br>" +
|
||||
'unalias "r"<br><br>' +
|
||||
"It is not necessary to differentiate between global and non-global aliases when using 'unalias'",
|
||||
|
||||
wget: "wget [url] [target file]<br>" +
|
||||
"Retrieves data from a URL and downloads it to a file on the current server. The data can only " +
|
||||
"be downloaded to a script (.script, .ns, .js) or a text file (.txt). If the file already exists, " +
|
||||
"it will be overwritten by this command.<br><br>" +
|
||||
"Note that it will not be possible to download data from many websites because they do not allow " +
|
||||
"cross-origin resource sharing (CORS). Example:<br><br>" +
|
||||
"wget https://raw.githubusercontent.com/danielyxie/bitburner/master/README.md game_readme.txt",
|
||||
};
|
||||
|
@ -162,7 +162,7 @@ function nextInfiltrationLevel(inst) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
var res = attemptInfiltrationKill(inst);
|
||||
if (res[0]) {
|
||||
writeInfiltrationStatusText("You SUCCESSFULLY killed the security bots! Unfortunately you alerted the " +
|
||||
writeInfiltrationStatusText("You <span class='success'>SUCCESSFULLY</span> killed the security bots! Unfortunately you alerted the " +
|
||||
"rest of the facility's security. The facility's security " +
|
||||
"level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
Player.karma -= 1;
|
||||
@ -170,7 +170,7 @@ function nextInfiltrationLevel(inst) {
|
||||
return false;
|
||||
} else {
|
||||
var dmgTaken = Math.max(1, Math.round(1.5 * inst.securityLevel / Player.defense));
|
||||
writeInfiltrationStatusText("You FAILED to kill the security bots. The bots fight back " +
|
||||
writeInfiltrationStatusText("You <span class='failure'>FAILED</span> to kill the security bots. The bots fight back " +
|
||||
"and raise the alarm! You take " + dmgTaken + " damage and " +
|
||||
"the facility's security level increases by " +
|
||||
formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
@ -186,12 +186,12 @@ function nextInfiltrationLevel(inst) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
var res = attemptInfiltrationAssassinate(inst);
|
||||
if (res[0]) {
|
||||
writeInfiltrationStatusText("You SUCCESSFULLY assassinated the security bots without being detected!");
|
||||
writeInfiltrationStatusText("You <span class='success'>SUCCESSFULLY</span> assassinated the security bots without being detected!");
|
||||
Player.karma -= 1;
|
||||
endInfiltrationLevel(inst);
|
||||
return false;
|
||||
} else {
|
||||
writeInfiltrationStatusText("You FAILED to assassinate the security bots. The bots have not detected " +
|
||||
writeInfiltrationStatusText("You <span class='failure'>FAILED</span> to assassinate the security bots. The bots have not detected " +
|
||||
"you but are now more alert for an intruder. The facility's security level " +
|
||||
"has increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
}
|
||||
@ -209,7 +209,7 @@ function nextInfiltrationLevel(inst) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
var res = attemptInfiltrationKill(inst);
|
||||
if (res[0]) {
|
||||
writeInfiltrationStatusText("You SUCCESSFULLY killed the security guard! Unfortunately you alerted the " +
|
||||
writeInfiltrationStatusText("You <span class='success'>SUCCESSFULLY</span> killed the security guard! Unfortunately you alerted the " +
|
||||
"rest of the facility's security. The facility's security " +
|
||||
"level has increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
Player.karma -= 3;
|
||||
@ -218,7 +218,7 @@ function nextInfiltrationLevel(inst) {
|
||||
return false;
|
||||
} else {
|
||||
var dmgTaken = Math.max(1, Math.round(inst.securityLevel / Player.defense));
|
||||
writeInfiltrationStatusText("You FAILED to kill the security guard. The guard fights back " +
|
||||
writeInfiltrationStatusText("You <span class='failure'>FAILED</span> to kill the security guard. The guard fights back " +
|
||||
"and raises the alarm! You take " + dmgTaken + " damage and " +
|
||||
"the facility's security level has increased by " +
|
||||
formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
@ -236,13 +236,13 @@ function nextInfiltrationLevel(inst) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
var res = attemptInfiltrationAssassinate(inst);
|
||||
if (res[0]) {
|
||||
writeInfiltrationStatusText("You SUCCESSFULLY assassinated the security guard without being detected!");
|
||||
writeInfiltrationStatusText("You <span class='success'>SUCCESSFULLY</span> assassinated the security guard without being detected!");
|
||||
Player.karma -= 3;
|
||||
++Player.numPeopleKilled;
|
||||
endInfiltrationLevel(inst);
|
||||
return false;
|
||||
} else {
|
||||
writeInfiltrationStatusText("You FAILED to assassinate the security guard. The guard has not detected " +
|
||||
writeInfiltrationStatusText("You <span class='failure'>FAILED</span> to assassinate the security guard. The guard has not detected " +
|
||||
"you but is now more alert for an intruder. The facility's security level " +
|
||||
"has increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
}
|
||||
@ -259,14 +259,14 @@ function nextInfiltrationLevel(inst) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
var res = attemptInfiltrationKnockout(inst);
|
||||
if (res[0]) {
|
||||
writeInfiltrationStatusText("You SUCCESSFULLY knocked out the security guard! " +
|
||||
writeInfiltrationStatusText("You <span class='success'>SUCCESSFULLY</span> knocked out the security guard! " +
|
||||
"Unfortunately you made a lot of noise and alerted other security.");
|
||||
writeInfiltrationStatusText("The facility's security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
endInfiltrationLevel(inst);
|
||||
return false;
|
||||
} else {
|
||||
var dmgTaken = Math.max(1, Math.round(inst.securityLevel / Player.defense));
|
||||
writeInfiltrationStatusText("You FAILED to knockout the security guard. The guard " +
|
||||
writeInfiltrationStatusText("You <span class='failure'>FAILED</span> to knockout the security guard. The guard " +
|
||||
"raises the alarm and fights back! You take " + dmgTaken + " damage and " +
|
||||
"the facility's security level increases by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
if (Player.takeDamage(dmgTaken)) {
|
||||
@ -282,13 +282,13 @@ function nextInfiltrationLevel(inst) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
var res = attemptInfiltrationStealthKnockout(inst);
|
||||
if (res[0]) {
|
||||
writeInfiltrationStatusText("You SUCCESSFULLY knocked out the security guard without making " +
|
||||
writeInfiltrationStatusText("You <span class='success'>SUCCESSFULLY</span> knocked out the security guard without making " +
|
||||
"any noise!");
|
||||
endInfiltrationLevel(inst);
|
||||
return false;
|
||||
} else {
|
||||
var dmgTaken = Math.max(1, Math.round(inst.securityLevel / Player.defense));
|
||||
writeInfiltrationStatusText("You FAILED to stealthily knockout the security guard. The guard " +
|
||||
writeInfiltrationStatusText("You <span class='failure'>FAILED</span> to stealthily knockout the security guard. The guard " +
|
||||
"raises the alarm and fights back! You take " + dmgTaken + " damage and " +
|
||||
"the facility's security level increases by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
if (Player.takeDamage(dmgTaken)) {
|
||||
@ -304,12 +304,12 @@ function nextInfiltrationLevel(inst) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
var res = attemptInfiltrationHack(inst);
|
||||
if (res[0]) {
|
||||
writeInfiltrationStatusText("You SUCCESSFULLY hacked and disabled the security system!");
|
||||
writeInfiltrationStatusText("You <span class='success'>SUCCESSFULLY</span> hacked and disabled the security system!");
|
||||
writeInfiltrationStatusText("The facility's security level increased by " + ((res[1]*100) - 100).toString() + "%");
|
||||
endInfiltrationLevel(inst);
|
||||
return false;
|
||||
} else {
|
||||
writeInfiltrationStatusText("You FAILED to hack the security system. The facility's " +
|
||||
writeInfiltrationStatusText("You <span class='failure'>FAILED</span> to hack the security system. The facility's " +
|
||||
"security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
}
|
||||
updateInfiltrationButtons(inst, scenario);
|
||||
@ -321,12 +321,12 @@ function nextInfiltrationLevel(inst) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
var res = attemptInfiltrationDestroySecurity(inst);
|
||||
if (res[0]) {
|
||||
writeInfiltrationStatusText("You SUCCESSFULLY and violently destroy the security system!");
|
||||
writeInfiltrationStatusText("You <span class='success'>SUCCESSFULLY</span> and violently destroy the security system!");
|
||||
writeInfiltrationStatusText("The facility's security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
endInfiltrationLevel(inst);
|
||||
return false;
|
||||
} else {
|
||||
writeInfiltrationStatusText("You FAILED to destroy the security system. The facility's " +
|
||||
writeInfiltrationStatusText("You <span class='failure'>FAILED</span> to destroy the security system. The facility's " +
|
||||
"security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
}
|
||||
updateInfiltrationButtons(inst, scenario);
|
||||
@ -338,11 +338,11 @@ function nextInfiltrationLevel(inst) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
var res = attemptInfiltrationSneak(inst);
|
||||
if (res[0]) {
|
||||
writeInfiltrationStatusText("You SUCCESSFULLY sneak past the security undetected!");
|
||||
writeInfiltrationStatusText("You <span class='success'>SUCCESSFULLY</span> sneak past the security undetected!");
|
||||
endInfiltrationLevel(inst);
|
||||
return false;
|
||||
} else {
|
||||
writeInfiltrationStatusText("You FAILED and were detected while trying to sneak past security! The facility's " +
|
||||
writeInfiltrationStatusText("You <span class='failure'>FAILED</span> and were detected while trying to sneak past security! The facility's " +
|
||||
"security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
}
|
||||
updateInfiltrationButtons(inst, scenario);
|
||||
@ -354,12 +354,12 @@ function nextInfiltrationLevel(inst) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
var res = attemptInfiltrationPickLockedDoor(inst);
|
||||
if (res[0]) {
|
||||
writeInfiltrationStatusText("You SUCCESSFULLY pick the locked door!");
|
||||
writeInfiltrationStatusText("You <span class='success'>SUCCESSFULLY</span> pick the locked door!");
|
||||
writeInfiltrationStatusText("The facility's security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
endInfiltrationLevel(inst);
|
||||
return false;
|
||||
} else {
|
||||
writeInfiltrationStatusText("You FAILED to pick the locked door. The facility's security level " +
|
||||
writeInfiltrationStatusText("You <span class='failure'>FAILED</span> to pick the locked door. The facility's security level " +
|
||||
"increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
}
|
||||
updateInfiltrationButtons(inst, scenario);
|
||||
@ -377,13 +377,13 @@ function nextInfiltrationLevel(inst) {
|
||||
}
|
||||
var res = attemptInfiltrationBribe(inst);
|
||||
if (res[0]) {
|
||||
writeInfiltrationStatusText("You SUCCESSFULLY bribed a guard to let you through " +
|
||||
writeInfiltrationStatusText("You <span class='success'>SUCCESSFULLY</span> bribed a guard to let you through " +
|
||||
"to the next clearance level for $" + bribeAmt);
|
||||
Player.loseMoney(bribeAmt);
|
||||
endInfiltrationLevel(inst);
|
||||
return false;
|
||||
} else {
|
||||
writeInfiltrationStatusText("You FAILED to bribe a guard! The guard is alerting " +
|
||||
writeInfiltrationStatusText("You <span class='failure'>FAILED</span> to bribe a guard! The guard is alerting " +
|
||||
"other security guards about your presence! The facility's " +
|
||||
"security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
}
|
||||
@ -396,12 +396,12 @@ function nextInfiltrationLevel(inst) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
var res = attemptInfiltrationEscape(inst);
|
||||
if (res[0]) {
|
||||
writeInfiltrationStatusText("You SUCCESSFULLY escape from the facility with the stolen classified " +
|
||||
writeInfiltrationStatusText("You <span class='success'>SUCCESSFULLY</span> escape from the facility with the stolen classified " +
|
||||
"documents and company secrets!");
|
||||
endInfiltration(inst, true);
|
||||
return false;
|
||||
} else {
|
||||
writeInfiltrationStatusText("You FAILED to escape from the facility. You took 1 damage. The facility's " +
|
||||
writeInfiltrationStatusText("You <span class='failure'>FAILED</span> to escape from the facility. You took 1 damage. The facility's " +
|
||||
"security level increased by " + formatNumber((res[1]*100)-100, 2).toString() + "%");
|
||||
if (Player.takeDamage(1)) {
|
||||
endInfiltration(inst, false);
|
||||
@ -429,9 +429,9 @@ function endInfiltrationLevel(inst) {
|
||||
BitNodeMultipliers.InfiltrationMoney;
|
||||
inst.secretsStolen.push(baseSecretValue);
|
||||
dialogBoxCreate("You found and stole a set of classified documents from the company. " +
|
||||
"These classified secrets could probably be sold for money ($" +
|
||||
formatNumber(secretMoneyValue, 2) + "), or they " +
|
||||
"could be given to factions for reputation (" + formatNumber(secretValue, 3) + " rep)");
|
||||
"These classified secrets could probably be sold for money (<span class='money-gold'>$" +
|
||||
formatNumber(secretMoneyValue, 2) + "</span>), or they " +
|
||||
"could be given to factions for reputation (<span class='light-yellow'>" + formatNumber(secretValue, 3) + " rep</span>)");
|
||||
}
|
||||
|
||||
//Increase security level based on difficulty
|
||||
@ -468,18 +468,22 @@ function updateInfiltrationLevelText(inst) {
|
||||
}
|
||||
|
||||
var expMultiplier = 2 * inst.clearanceLevel / inst.maxClearanceLevel;
|
||||
// TODO: fix this to not rely on <pre> and whitespace for formatting...
|
||||
/* eslint-disable no-irregular-whitespace */
|
||||
document.getElementById("infiltration-level-text").innerHTML =
|
||||
"Facility name: " + inst.companyName + "<br>" +
|
||||
"Clearance Level: " + inst.clearanceLevel + "<br>" +
|
||||
"Security Level: " + formatNumber(inst.securityLevel, 3) + "<br><br>" +
|
||||
"Total reputation value of secrets stolen: " + formatNumber(totalValue, 3) + "<br>" +
|
||||
"Total monetary value of secrets stolen: $" + formatNumber(totalMoneyValue, 2) + "<br><br>" +
|
||||
"Hack exp gained: " + formatNumber(inst.hackingExpGained * expMultiplier, 3) + "<br>" +
|
||||
"Str exp gained: " + formatNumber(inst.strExpGained * expMultiplier, 3) + "<br>" +
|
||||
"Def exp gained: " + formatNumber(inst.defExpGained * expMultiplier, 3) + "<br>" +
|
||||
"Dex exp gained: " + formatNumber(inst.dexExpGained * expMultiplier, 3) + "<br>" +
|
||||
"Agi exp gained: " + formatNumber(inst.agiExpGained * expMultiplier, 3) + "<br>" +
|
||||
"Cha exp gained: " + formatNumber(inst.chaExpGained * expMultiplier, 3);
|
||||
"Facility name: " + inst.companyName + "<br>" +
|
||||
"Clearance Level: " + inst.clearanceLevel + "<br>" +
|
||||
"Security Level: " + formatNumber(inst.securityLevel, 3) + "<br><br>" +
|
||||
"Total value of stolen secrets<br>" +
|
||||
"Reputation: <span class='light-yellow'>" + formatNumber(totalValue, 3) + "</span><br>" +
|
||||
"Money: <span class='money-gold'>$" + formatNumber(totalMoneyValue, 2) + "</span><br><br>" +
|
||||
"Hack exp gained: " + formatNumber(inst.hackingExpGained * expMultiplier, 3) + "<br>" +
|
||||
"Str exp gained: " + formatNumber(inst.strExpGained * expMultiplier, 3) + "<br>" +
|
||||
"Def exp gained: " + formatNumber(inst.defExpGained * expMultiplier, 3) + "<br>" +
|
||||
"Dex exp gained: " + formatNumber(inst.dexExpGained * expMultiplier, 3) + "<br>" +
|
||||
"Agi exp gained: " + formatNumber(inst.agiExpGained * expMultiplier, 3) + "<br>" +
|
||||
"Cha exp gained: " + formatNumber(inst.chaExpGained * expMultiplier, 3);
|
||||
/* eslint-enable no-irregular-whitespace */
|
||||
}
|
||||
|
||||
function updateInfiltrationButtons(inst, scenario) {
|
||||
|
@ -1,55 +1,75 @@
|
||||
import {Engine} from "./engine";
|
||||
import {Player} from "./Player";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {Settings} from "./Settings";
|
||||
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();
|
||||
|
||||
//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 +79,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
|
||||
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 +231,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 +250,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 +276,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 +302,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 +417,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>" +
|
||||
|
||||
//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><br><br>" +
|
||||
"<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");
|
||||
"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 +506,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>" +
|
||||
|
@ -15,10 +15,11 @@ import {purchaseServer,
|
||||
import {Settings} from "./Settings";
|
||||
import {SpecialServerNames, SpecialServerIps} from "./SpecialServerIps";
|
||||
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";
|
||||
import {createRandomIp} from "../utils/IPAddress";
|
||||
import numeral from "numeral/min/numeral.min";
|
||||
import {formatNumber} from "../utils/StringHelperFunctions";
|
||||
import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
|
||||
yesNoBoxGetYesButton, yesNoBoxGetNoButton,
|
||||
@ -1788,7 +1789,7 @@ function initLocationButtons() {
|
||||
});
|
||||
yesNoBoxCreate("Would you like to purchase additional RAM for your home computer? <br><br>" +
|
||||
"This will upgrade your RAM from " + ram + "GB to " + ram*2 + "GB. <br><br>" +
|
||||
"This will cost " + numeral(cost).format('$0.000a'));
|
||||
"This will cost " + numeralWrapper.format(cost, '$0.000a'));
|
||||
});
|
||||
|
||||
purchaseHomeCores.addEventListener("click", function(e) {
|
||||
@ -1825,7 +1826,7 @@ function initLocationButtons() {
|
||||
yesNoBoxCreate("Would you like to purchase an additional CPU Core for your home computer? Each CPU Core " +
|
||||
"lets you start with an additional Core Node in Hacking Missions.<br><br>" +
|
||||
"Purchasing an additional core (for a total of " + (Player.getHomeComputer().cpuCores + 1) + ") will " +
|
||||
"cost " + numeral(cost).format('$0.000a'));
|
||||
"cost " + numeralWrapper.format(cost, '$0.000a'));
|
||||
});
|
||||
|
||||
travelToAevum.addEventListener("click", function(e) {
|
||||
|
@ -911,61 +911,5 @@ function isScriptErrorMessage(msg) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//The same as Player's calculateHackingChance() function but takes in the server as an argument
|
||||
function scriptCalculateHackingChance(server) {
|
||||
var difficultyMult = (100 - server.hackDifficulty) / 100;
|
||||
var skillMult = (1.75 * Player.hacking_skill) + (0.2 * Player.intelligence);
|
||||
var skillChance = (skillMult - server.requiredHackingSkill) / skillMult;
|
||||
var chance = skillChance * difficultyMult * Player.hacking_chance_mult;
|
||||
if (chance > 1) {return 1;}
|
||||
if (chance < 0) {return 0;}
|
||||
else {return chance;}
|
||||
}
|
||||
|
||||
//The same as Player's calculateHackingTime() function but takes in the server as an argument
|
||||
function scriptCalculateHackingTime(server) {
|
||||
var difficultyMult = server.requiredHackingSkill * server.hackDifficulty;
|
||||
var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50 + (0.1 * Player.intelligence));
|
||||
var hackingTime = 5 * skillFactor / Player.hacking_speed_mult; //This is in seconds
|
||||
return hackingTime;
|
||||
}
|
||||
|
||||
//The same as Player's calculateExpGain() function but takes in the server as an argument
|
||||
function scriptCalculateExpGain(server) {
|
||||
if (server.baseDifficulty == null) {
|
||||
server.baseDifficulty = server.hackDifficulty;
|
||||
}
|
||||
return (server.baseDifficulty * Player.hacking_exp_mult * 0.3 + 3) * BitNodeMultipliers.HackExpGain;
|
||||
}
|
||||
|
||||
//The same as Player's calculatePercentMoneyHacked() function but takes in the server as an argument
|
||||
function scriptCalculatePercentMoneyHacked(server) {
|
||||
var difficultyMult = (100 - server.hackDifficulty) / 100;
|
||||
var skillMult = (Player.hacking_skill - (server.requiredHackingSkill - 1)) / Player.hacking_skill;
|
||||
var percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / 240;
|
||||
if (percentMoneyHacked < 0) {return 0;}
|
||||
if (percentMoneyHacked > 1) {return 1;}
|
||||
return percentMoneyHacked * BitNodeMultipliers.ScriptHackMoney;
|
||||
}
|
||||
|
||||
//Amount of time to execute grow() in milliseconds
|
||||
function scriptCalculateGrowTime(server) {
|
||||
var difficultyMult = server.requiredHackingSkill * server.hackDifficulty;
|
||||
var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50 + (0.1 * Player.intelligence));
|
||||
var growTime = 16 * skillFactor / Player.hacking_speed_mult; //This is in seconds
|
||||
return growTime * 1000;
|
||||
}
|
||||
|
||||
//Amount of time to execute weaken() in milliseconds
|
||||
function scriptCalculateWeakenTime(server) {
|
||||
var difficultyMult = server.requiredHackingSkill * server.hackDifficulty;
|
||||
var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50 + (0.1 * Player.intelligence));
|
||||
var weakenTime = 20 * skillFactor / Player.hacking_speed_mult; //This is in seconds
|
||||
return weakenTime * 1000;
|
||||
}
|
||||
|
||||
export {makeRuntimeRejectMsg, netscriptDelay, runScriptFromScript,
|
||||
scriptCalculateHackingChance, scriptCalculateHackingTime,
|
||||
scriptCalculateExpGain, scriptCalculatePercentMoneyHacked,
|
||||
scriptCalculateGrowTime, scriptCalculateWeakenTime, evaluate,
|
||||
export {makeRuntimeRejectMsg, netscriptDelay, runScriptFromScript, evaluate,
|
||||
isScriptErrorMessage, killNetscriptDelay, evaluateImport};
|
||||
|
@ -13,6 +13,12 @@ import {Companies, Company, CompanyPosition,
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Programs} from "./CreateProgram";
|
||||
import {DarkWebItems} from "./DarkWeb";
|
||||
import {calculateHackingChance,
|
||||
calculateHackingExpGain,
|
||||
calculatePercentMoneyHacked,
|
||||
calculateHackingTime,
|
||||
calculateGrowTime,
|
||||
calculateWeakenTime} from "./Hacking";
|
||||
import {AllGangs} from "./Gang";
|
||||
import {Factions, Faction, joinFaction,
|
||||
factionExists, purchaseAugmentation} from "./Faction";
|
||||
@ -28,11 +34,12 @@ import {Server, getServer, AddToAllServers,
|
||||
GetServerByHostname} from "./Server";
|
||||
import {Settings} from "./Settings";
|
||||
import {SpecialServerIps} from "./SpecialServerIps";
|
||||
import {Stock} from "./Stock";
|
||||
import {StockMarket, StockSymbols, SymbolToStockMap, initStockSymbols,
|
||||
initStockMarket, initSymbolToStockMap, stockMarketCycle, buyStock,
|
||||
sellStock, updateStockPrices, displayStockMarketContent,
|
||||
updateStockTicker, updateStockPlayerPosition,
|
||||
Stock, shortStock, sellShort, OrderTypes,
|
||||
shortStock, sellShort, OrderTypes,
|
||||
PositionTypes, placeOrder, cancelOrder} from "./StockMarket";
|
||||
import {post} from "./ui/postToTerminal";
|
||||
import {TextFile, getTextFile, createTextFile} from "./TextFile";
|
||||
@ -42,10 +49,8 @@ import {unknownBladeburnerActionErrorMessage,
|
||||
checkBladeburnerAccess} from "./NetscriptBladeburner.js";
|
||||
import {WorkerScript, workerScripts,
|
||||
killWorkerScript, NetscriptPorts} from "./NetscriptWorker";
|
||||
import {makeRuntimeRejectMsg, netscriptDelay, runScriptFromScript,
|
||||
scriptCalculateHackingChance, scriptCalculateHackingTime,
|
||||
scriptCalculateExpGain, scriptCalculatePercentMoneyHacked,
|
||||
scriptCalculateGrowTime, scriptCalculateWeakenTime} from "./NetscriptEvaluator";
|
||||
import {makeRuntimeRejectMsg, netscriptDelay,
|
||||
runScriptFromScript} from "./NetscriptEvaluator";
|
||||
import {NetscriptPort} from "./NetscriptPort";
|
||||
|
||||
import Decimal from "decimal.js";
|
||||
@ -116,6 +121,7 @@ var possibleLogs = {
|
||||
applyToCompany: true,
|
||||
joinFaction: true,
|
||||
workForFaction: true,
|
||||
donateToFaction: true,
|
||||
createProgram: true,
|
||||
commitCrime: true,
|
||||
shortStock: true,
|
||||
@ -292,7 +298,7 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
|
||||
//Calculate the hacking time
|
||||
var hackingTime = scriptCalculateHackingTime(server); //This is in seconds
|
||||
var hackingTime = calculateHackingTime(server); //This is in seconds
|
||||
|
||||
//No root access or skill level too low
|
||||
if (server.hasAdminRights == false) {
|
||||
@ -310,12 +316,12 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
return netscriptDelay(hackingTime * 1000, workerScript).then(function() {
|
||||
if (workerScript.env.stopFlag) {return Promise.reject(workerScript);}
|
||||
var hackChance = scriptCalculateHackingChance(server);
|
||||
var hackChance = calculateHackingChance(server);
|
||||
var rand = Math.random();
|
||||
var expGainedOnSuccess = scriptCalculateExpGain(server) * threads;
|
||||
var expGainedOnSuccess = calculateHackingExpGain(server) * threads;
|
||||
var expGainedOnFailure = (expGainedOnSuccess / 4);
|
||||
if (rand < hackChance) { //Success!
|
||||
const percentHacked = scriptCalculatePercentMoneyHacked(server);
|
||||
const percentHacked = calculatePercentMoneyHacked(server);
|
||||
let maxThreadNeeded = Math.ceil(1/percentHacked*(server.moneyAvailable/server.moneyMax));
|
||||
if (isNaN(maxThreadNeeded)) {
|
||||
//Server has a 'max money' of 0 (probably).
|
||||
@ -390,18 +396,18 @@ function NetscriptFunctions(workerScript) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Cannot grow this server (" + server.hostname + ") because user does not have root access");
|
||||
}
|
||||
|
||||
var growTime = scriptCalculateGrowTime(server);
|
||||
var growTime = calculateGrowTime(server);
|
||||
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.grow == null) {
|
||||
workerScript.scriptRef.log("Executing grow() on server " + server.hostname + " in " + formatNumber(growTime/1000, 3) + " seconds (t=" + threads + ")");
|
||||
workerScript.scriptRef.log("Executing grow() on server " + server.hostname + " in " + formatNumber(growTime, 3) + " seconds (t=" + threads + ")");
|
||||
}
|
||||
return netscriptDelay(growTime, workerScript).then(function() {
|
||||
return netscriptDelay(growTime * 1000, workerScript).then(function() {
|
||||
if (workerScript.env.stopFlag) {return Promise.reject(workerScript);}
|
||||
const moneyBefore = server.moneyAvailable;
|
||||
server.moneyAvailable += (1 * threads); //It can be grown even if it has no money
|
||||
var growthPercentage = processSingleServerGrowth(server, 450 * threads);
|
||||
const moneyAfter = server.moneyAvailable;
|
||||
workerScript.scriptRef.recordGrow(server.ip, threads);
|
||||
var expGain = scriptCalculateExpGain(server) * threads;
|
||||
var expGain = calculateHackingExpGain(server) * threads;
|
||||
if (growthPercentage == 1) {
|
||||
expGain = 0;
|
||||
}
|
||||
@ -437,16 +443,16 @@ function NetscriptFunctions(workerScript) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Cannot weaken this server (" + server.hostname + ") because user does not have root access");
|
||||
}
|
||||
|
||||
var weakenTime = scriptCalculateWeakenTime(server);
|
||||
var weakenTime = calculateWeakenTime(server);
|
||||
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.weaken == null) {
|
||||
workerScript.scriptRef.log("Executing weaken() on server " + server.hostname + " in " +
|
||||
formatNumber(weakenTime/1000, 3) + " seconds (t=" + threads + ")");
|
||||
formatNumber(weakenTime, 3) + " seconds (t=" + threads + ")");
|
||||
}
|
||||
return netscriptDelay(weakenTime, workerScript).then(function() {
|
||||
return netscriptDelay(weakenTime * 1000, workerScript).then(function() {
|
||||
if (workerScript.env.stopFlag) {return Promise.reject(workerScript);}
|
||||
server.weaken(CONSTANTS.ServerWeakenAmount * threads);
|
||||
workerScript.scriptRef.recordWeaken(server.ip, threads);
|
||||
var expGain = scriptCalculateExpGain(server) * threads;
|
||||
var expGain = calculateHackingExpGain(server) * threads;
|
||||
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.weaken == null) {
|
||||
workerScript.scriptRef.log("Server security level on " + server.hostname + " weakened to " + server.hackDifficulty +
|
||||
". Gained " + formatNumber(expGain, 4) + " hacking exp (t=" + threads + ")");
|
||||
@ -502,6 +508,17 @@ function NetscriptFunctions(workerScript) {
|
||||
workerScript.scriptRef.log("Enabled logging for " + fn);
|
||||
}
|
||||
},
|
||||
isLogEnabled : function(fn) {
|
||||
if (workerScript.checkingRam) {return 0;}
|
||||
if (possibleLogs[fn] === undefined) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Invalid argument to isLogEnabled: " + fn);
|
||||
}
|
||||
return workerScript.disableLogs[fn] ? false : true;
|
||||
},
|
||||
getScriptLogs : function() {
|
||||
if (workerScript.checkingRam) {return 0;}
|
||||
return workerScript.scriptRef.logs.slice();
|
||||
},
|
||||
nuke : function(ip){
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("nuke", CONSTANTS.ScriptPortProgramRamCost);
|
||||
@ -1843,6 +1860,25 @@ function NetscriptFunctions(workerScript) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for write: " + port);
|
||||
}
|
||||
},
|
||||
tryWrite : function(port, data="") {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("tryWrite", CONSTANTS.ScriptReadWriteRamCost);
|
||||
}
|
||||
updateDynamicRam("tryWrite", CONSTANTS.ScriptReadWriteRamCost);
|
||||
if (!isNaN(port)) {
|
||||
port = Math.round(port);
|
||||
if (port < 1 || port > CONSTANTS.NumNetscriptPorts) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "ERROR: tryWrite() called on invalid port: " + port + ". Only ports 1-" + CONSTANTS.NumNetscriptPorts + " are valid.");
|
||||
}
|
||||
var port = NetscriptPorts[port-1];
|
||||
if (port == null || !(port instanceof NetscriptPort)) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Could not find port: " + port + ". This is a bug contact the game developer");
|
||||
}
|
||||
return port.tryWrite(data);
|
||||
} else {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for tryWrite: " + port);
|
||||
}
|
||||
},
|
||||
read : function(port) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("read", CONSTANTS.ScriptReadWriteRamCost);
|
||||
@ -2047,7 +2083,7 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
getHackTime : function(ip) {
|
||||
getHackTime : function(ip, hack, int) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("getHackTime", CONSTANTS.ScriptGetHackTimeRamCost);
|
||||
}
|
||||
@ -2057,9 +2093,9 @@ function NetscriptFunctions(workerScript) {
|
||||
workerScript.scriptRef.log("getHackTime() failed. Invalid IP or hostname passed in: " + ip);
|
||||
throw makeRuntimeRejectMsg(workerScript, "getHackTime() failed. Invalid IP or hostname passed in: " + ip);
|
||||
}
|
||||
return scriptCalculateHackingTime(server); //Returns seconds
|
||||
return calculateHackingTime(server, hack, int); //Returns seconds
|
||||
},
|
||||
getGrowTime : function(ip) {
|
||||
getGrowTime : function(ip, hack, int) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("getGrowTime", CONSTANTS.ScriptGetHackTimeRamCost);
|
||||
}
|
||||
@ -2069,9 +2105,9 @@ function NetscriptFunctions(workerScript) {
|
||||
workerScript.scriptRef.log("getGrowTime() failed. Invalid IP or hostname passed in: " + ip);
|
||||
throw makeRuntimeRejectMsg(workerScript, "getGrowTime() failed. Invalid IP or hostname passed in: " + ip);
|
||||
}
|
||||
return scriptCalculateGrowTime(server) / 1000; //Returns seconds
|
||||
return calculateGrowTime(server, hack, int); //Returns seconds
|
||||
},
|
||||
getWeakenTime : function(ip) {
|
||||
getWeakenTime : function(ip, hack, int) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("getWeakenTime", CONSTANTS.ScriptGetHackTimeRamCost);
|
||||
}
|
||||
@ -2081,7 +2117,7 @@ function NetscriptFunctions(workerScript) {
|
||||
workerScript.scriptRef.log("getWeakenTime() failed. Invalid IP or hostname passed in: " + ip);
|
||||
throw makeRuntimeRejectMsg(workerScript, "getWeakenTime() failed. Invalid IP or hostname passed in: " + ip);
|
||||
}
|
||||
return scriptCalculateWeakenTime(server) / 1000; //Returns seconds
|
||||
return calculateWeakenTime(server, hack, int); //Returns seconds
|
||||
},
|
||||
getScriptIncome : function(scriptname, ip) {
|
||||
if (workerScript.checkingRam) {
|
||||
@ -3053,6 +3089,45 @@ function NetscriptFunctions(workerScript) {
|
||||
|
||||
return Factions[name].getFavorGain()[0];
|
||||
},
|
||||
donateToFaction : function(name, amt) {
|
||||
var ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
|
||||
if (Player.bitNodeN !== 4) {ramCost *= 8;}
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("donateToFaction", ramCost);
|
||||
}
|
||||
updateDynamicRam("donateToFaction", ramCost);
|
||||
if (Player.bitNodeN != 4) {
|
||||
if (!(hasSingularitySF && singularitySFLvl >= 3)) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Cannot run donateToFaction(). It is a Singularity Function and requires SourceFile-4 (level 3) to run.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!factionExists(name)) {
|
||||
workerScript.log(`ERROR: Faction specified in donateToFaction() does not exist: ${name}`);
|
||||
return false;
|
||||
}
|
||||
if (typeof amt !== 'number' || amt <= 0) {
|
||||
workerScript.log(`ERROR: Invalid donation amount specified in donateToFaction(): ${amt}. Must be numeric and positive`);
|
||||
return false;
|
||||
}
|
||||
if (Player.money.lt(amt)) {
|
||||
workerScript.log(`ERROR: You do not have enough money to donate $${amt} to ${name}`);
|
||||
return false;
|
||||
}
|
||||
var repNeededToDonate = Math.round(CONSTANTS.BaseFavorToDonate * BitNodeMultipliers.RepToDonateToFaction);
|
||||
if (Factions[name].favor < repNeededToDonate) {
|
||||
workerScript.log(`ERROR: You do not have enough favor to donate to this faction. Have ${Factions[name].favor}, need ${repNeededToDonate}`);
|
||||
return false;
|
||||
}
|
||||
var repGain = amt / CONSTANTS.DonateMoneyToRepDivisor * Player.faction_rep_mult;
|
||||
Factions[name].playerReputation += repGain;
|
||||
Player.loseMoney(amt);
|
||||
if (workerScript.shouldLog("donateToFaction")) {
|
||||
workerScript.log(`$${amt} donated to ${name} for ${repGain} reputation`);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
createProgram : function(name) {
|
||||
var ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
|
||||
if (Player.bitNodeN !== 4) {ramCost *= 8;}
|
||||
|
514
src/Player.js
514
src/Player.js
@ -21,15 +21,18 @@ import {SpecialServerIps, SpecialServerNames} from "./SpecialServerIps";
|
||||
import {SourceFiles, applySourceFile} from "./SourceFile";
|
||||
|
||||
import Decimal from "decimal.js";
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";
|
||||
import {createRandomIp} from "../utils/IPAddress";
|
||||
import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver";
|
||||
import numeral from "numeral/min/numeral.min";
|
||||
import {formatNumber,
|
||||
convertTimeMsToTimeElapsedString} from "../utils/StringHelperFunctions";
|
||||
|
||||
const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle;
|
||||
|
||||
function PlayerObject() {
|
||||
//Skills and stats
|
||||
this.hacking_skill = 1;
|
||||
@ -119,11 +122,6 @@ function PlayerObject() {
|
||||
this.crime_money_mult = 1;
|
||||
this.crime_success_mult = 1;
|
||||
|
||||
//Flag to let the engine know the player is starting an action
|
||||
// Current actions: hack, analyze
|
||||
this.startAction = false;
|
||||
this.actionTime = 0;
|
||||
|
||||
//Flags/variables for working (Company, Faction, Creating Program, Taking Class)
|
||||
this.isWorking = false;
|
||||
this.workType = "";
|
||||
@ -265,9 +263,6 @@ PlayerObject.prototype.prestigeAugmentation = function() {
|
||||
|
||||
this.queuedAugmentations = [];
|
||||
|
||||
this.startAction = false;
|
||||
this.actionTime = 0;
|
||||
|
||||
this.isWorking = false;
|
||||
this.currentWorkFactionName = "";
|
||||
this.currentWorkFactionDescription = "";
|
||||
@ -349,9 +344,6 @@ PlayerObject.prototype.prestigeSourceFile = function() {
|
||||
this.queuedAugmentations = [];
|
||||
this.augmentations = [];
|
||||
|
||||
this.startAction = false;
|
||||
this.actionTime = 0;
|
||||
|
||||
this.isWorking = false;
|
||||
this.currentWorkFactionName = "";
|
||||
this.currentWorkFactionDescription = "";
|
||||
@ -498,74 +490,10 @@ PlayerObject.prototype.resetMultipliers = function() {
|
||||
this.bladeburner_success_chance_mult = 1;
|
||||
}
|
||||
|
||||
//Calculates the chance of hacking a server
|
||||
//The formula is:
|
||||
// (2 * hacking_chance_multiplier * hacking_skill - requiredLevel) 100 - difficulty
|
||||
// ----------------------------------------------------------- * -----------------
|
||||
// (2 * hacking_chance_multiplier * hacking_skill) 100
|
||||
PlayerObject.prototype.calculateHackingChance = function() {
|
||||
var difficultyMult = (100 - this.getCurrentServer().hackDifficulty) / 100;
|
||||
var skillMult = (1.75 * this.hacking_skill) + (0.2 * this.intelligence);
|
||||
var skillChance = (skillMult - this.getCurrentServer().requiredHackingSkill) / skillMult;
|
||||
var chance = skillChance * difficultyMult * this.hacking_chance_mult;
|
||||
if (chance > 1) {return 1;}
|
||||
if (chance < 0) {return 0;}
|
||||
return chance;
|
||||
}
|
||||
|
||||
//Calculate the time it takes to hack a server in seconds. Returns the time
|
||||
//The formula is:
|
||||
// (2.5 * requiredLevel * difficulty + 200)
|
||||
// ----------------------------------- * hacking_speed_multiplier
|
||||
// hacking_skill + 100
|
||||
PlayerObject.prototype.calculateHackingTime = function() {
|
||||
var difficultyMult = this.getCurrentServer().requiredHackingSkill * this.getCurrentServer().hackDifficulty;
|
||||
var skillFactor = (2.5 * difficultyMult + 200) / (this.hacking_skill + 100 + (0.1 * this.intelligence));
|
||||
return 5 * skillFactor / this.hacking_speed_mult;
|
||||
}
|
||||
|
||||
//Calculates the PERCENTAGE of a server's money that the player will hack from the server if successful
|
||||
//The formula is:
|
||||
// (hacking_skill - (requiredLevel-1)) 100 - difficulty
|
||||
// --------------------------------------* ----------------------- * hacking_money_multiplier
|
||||
// hacking_skill 100
|
||||
PlayerObject.prototype.calculatePercentMoneyHacked = function() {
|
||||
var difficultyMult = (100 - this.getCurrentServer().hackDifficulty) / 100;
|
||||
var skillMult = (this.hacking_skill - (this.getCurrentServer().requiredHackingSkill - 1)) / this.hacking_skill;
|
||||
var percentMoneyHacked = difficultyMult * skillMult * this.hacking_money_mult / 240;
|
||||
console.log("Percent money hacked calculated to be: " + percentMoneyHacked);
|
||||
if (percentMoneyHacked < 0) {return 0;}
|
||||
if (percentMoneyHacked > 1) {return 1;}
|
||||
return percentMoneyHacked * BitNodeMultipliers.ManualHackMoney;
|
||||
}
|
||||
|
||||
//Returns how much EXP the player gains on a successful hack
|
||||
//The formula is:
|
||||
// difficulty * requiredLevel * hacking_multiplier
|
||||
PlayerObject.prototype.calculateExpGain = function() {
|
||||
var s = this.getCurrentServer();
|
||||
if (s.baseDifficulty == null) {
|
||||
s.baseDifficulty = s.hackDifficulty;
|
||||
}
|
||||
return (s.baseDifficulty * this.hacking_exp_mult * 0.3 + 3) * BitNodeMultipliers.HackExpGain;
|
||||
}
|
||||
|
||||
//Hack/Analyze a server. Return the amount of time the hack will take. This lets the Terminal object know how long to disable itself for
|
||||
//This assumes that the server being hacked is not purchased by the player, that the player's hacking skill is greater than the
|
||||
//required hacking skill and that the player has admin rights.
|
||||
PlayerObject.prototype.hack = function() {
|
||||
this.actionTime = this.calculateHackingTime();
|
||||
console.log("Hacking time: " + this.actionTime);
|
||||
this.startAction = true; //Set the startAction flag so the engine starts the hacking process
|
||||
}
|
||||
|
||||
PlayerObject.prototype.analyze = function() {
|
||||
this.actionTime = 1;
|
||||
this.startAction = true;
|
||||
}
|
||||
|
||||
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;}
|
||||
}
|
||||
@ -688,6 +616,7 @@ PlayerObject.prototype.resetWorkStatus = function() {
|
||||
this.workChaExpGainRate = 0;
|
||||
this.workRepGainRate = 0;
|
||||
this.workMoneyGainRate = 0;
|
||||
this.workMoneyLossRate = 0;
|
||||
|
||||
this.workHackExpGained = 0;
|
||||
this.workStrExpGained = 0;
|
||||
@ -709,24 +638,109 @@ PlayerObject.prototype.resetWorkStatus = function() {
|
||||
document.getElementById("work-in-progress-text").innerHTML = "";
|
||||
}
|
||||
|
||||
PlayerObject.prototype.gainWorkExp = function() {
|
||||
this.gainHackingExp(this.workHackExpGained);
|
||||
this.gainStrengthExp(this.workStrExpGained);
|
||||
this.gainDefenseExp(this.workDefExpGained);
|
||||
this.gainDexterityExp(this.workDexExpGained);
|
||||
this.gainAgilityExp(this.workAgiExpGained);
|
||||
this.gainCharismaExp(this.workChaExpGained);
|
||||
PlayerObject.prototype.processWorkEarnings = function(numCycles=1) {
|
||||
var hackExpGain = this.workHackExpGainRate * numCycles;
|
||||
var strExpGain = this.workStrExpGainRate * numCycles;
|
||||
var defExpGain = this.workDefExpGainRate * numCycles;
|
||||
var dexExpGain = this.workDexExpGainRate * numCycles;
|
||||
var agiExpGain = this.workAgiExpGainRate * numCycles;
|
||||
var chaExpGain = this.workChaExpGainRate * numCycles;
|
||||
|
||||
this.gainHackingExp(hackExpGain);
|
||||
this.gainStrengthExp(strExpGain);
|
||||
this.gainDefenseExp(defExpGain);
|
||||
this.gainDexterityExp(dexExpGain);
|
||||
this.gainAgilityExp(agiExpGain);
|
||||
this.gainCharismaExp(chaExpGain);
|
||||
this.workHackExpGained += hackExpGain;
|
||||
this.workStrExpGained += strExpGain;
|
||||
this.workDefExpGained += defExpGain;
|
||||
this.workDexExpGained += dexExpGain;
|
||||
this.workAgiExpGained += agiExpGain;
|
||||
this.workChaExpGained += chaExpGain;
|
||||
this.workRepGained += this.workRepGainRate * numCycles;
|
||||
this.workMoneyGained += this.workMoneyGainRate * numCycles;
|
||||
this.workMoneyGained -= this.workMoneyLossRate * numCycles;
|
||||
}
|
||||
|
||||
/* Working for Company */
|
||||
PlayerObject.prototype.startWork = function() {
|
||||
this.resetWorkStatus();
|
||||
this.isWorking = true;
|
||||
this.workType = CONSTANTS.WorkTypeCompany;
|
||||
|
||||
this.workHackExpGainRate = this.getWorkHackExpGain();
|
||||
this.workStrExpGainRate = this.getWorkStrExpGain();
|
||||
this.workDefExpGainRate = this.getWorkDefExpGain();
|
||||
this.workDexExpGainRate = this.getWorkDexExpGain();
|
||||
this.workAgiExpGainRate = this.getWorkAgiExpGain();
|
||||
this.workChaExpGainRate = this.getWorkChaExpGain();
|
||||
this.workRepGainRate = this.getWorkRepGain();
|
||||
this.workMoneyGainRate = this.getWorkMoneyGain();
|
||||
|
||||
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours;
|
||||
|
||||
//Remove all old event listeners from Cancel button
|
||||
var newCancelButton = clearEventListeners("work-in-progress-cancel-button");
|
||||
newCancelButton.innerHTML = "Cancel Work";
|
||||
newCancelButton.addEventListener("click", function() {
|
||||
Player.finishWork(true);
|
||||
return false;
|
||||
});
|
||||
|
||||
//Display Work In Progress Screen
|
||||
Engine.loadWorkInProgressContent();
|
||||
}
|
||||
|
||||
PlayerObject.prototype.work = function(numCycles) {
|
||||
//Cap the number of cycles being processed to whatever would put you at
|
||||
//the work time limit (8 hours)
|
||||
var overMax = false;
|
||||
if (this.timeWorked + (Engine._idleSpeed * numCycles) >= CONSTANTS.MillisecondsPer8Hours) {
|
||||
overMax = true;
|
||||
numCycles = Math.round((CONSTANTS.MillisecondsPer8Hours - this.timeWorked) / Engine._idleSpeed);
|
||||
}
|
||||
this.timeWorked += Engine._idleSpeed * numCycles;
|
||||
|
||||
this.workRepGainRate = this.getWorkRepGain();
|
||||
this.processWorkEarnings(numCycles);
|
||||
|
||||
//If timeWorked == 8 hours, then finish. You can only gain 8 hours worth of exp and money
|
||||
if (overMax || this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) {
|
||||
return this.finishWork(false);
|
||||
}
|
||||
|
||||
var comp = Companies[this.companyName], companyRep = "0";
|
||||
if (comp == null || !(comp instanceof Company)) {
|
||||
console.log("ERROR: Could not find Company: " + this.companyName);
|
||||
} else {
|
||||
companyRep = comp.playerReputation;
|
||||
}
|
||||
|
||||
var txt = document.getElementById("work-in-progress-text");
|
||||
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
|
||||
" at " + this.companyName + " (Current Company Reputation: " +
|
||||
formatNumber(companyRep, 0) + ")<br><br>" +
|
||||
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
|
||||
"You have earned: <br><br>" +
|
||||
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * CYCLES_PER_SEC, 2) + " / sec) <br><br>" +
|
||||
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * CYCLES_PER_SEC, 4) + " / sec) reputation for this company <br><br>" +
|
||||
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * CYCLES_PER_SEC, 4) + " / sec) hacking exp <br><br>" +
|
||||
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * CYCLES_PER_SEC, 4) + " / sec) strength exp <br>" +
|
||||
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * CYCLES_PER_SEC, 4) + " / sec) defense exp <br>" +
|
||||
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * CYCLES_PER_SEC, 4) + " / sec) dexterity exp <br>" +
|
||||
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * CYCLES_PER_SEC, 4) + " / sec) agility exp <br><br> " +
|
||||
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * CYCLES_PER_SEC, 4) + " / sec) charisma exp <br><br>" +
|
||||
"You will automatically finish after working for 8 hours. You can cancel earlier if you wish, " +
|
||||
"but you will only gain half of the reputation you've earned so far."
|
||||
}
|
||||
|
||||
PlayerObject.prototype.finishWork = function(cancelled, sing=false) {
|
||||
//Since the work was cancelled early, player only gains half of what they've earned so far
|
||||
if (cancelled) {
|
||||
this.workRepGained /= 2;
|
||||
}
|
||||
|
||||
this.gainWorkExp();
|
||||
|
||||
var company = Companies[this.companyName];
|
||||
company.playerReputation += (this.workRepGained);
|
||||
|
||||
@ -773,91 +787,6 @@ PlayerObject.prototype.finishWork = function(cancelled, sing=false) {
|
||||
this.resetWorkStatus();
|
||||
}
|
||||
|
||||
PlayerObject.prototype.startWork = function() {
|
||||
this.resetWorkStatus();
|
||||
this.isWorking = true;
|
||||
this.workType = CONSTANTS.WorkTypeCompany;
|
||||
|
||||
this.workHackExpGainRate = this.getWorkHackExpGain();
|
||||
this.workStrExpGainRate = this.getWorkStrExpGain();
|
||||
this.workDefExpGainRate = this.getWorkDefExpGain();
|
||||
this.workDexExpGainRate = this.getWorkDexExpGain();
|
||||
this.workAgiExpGainRate = this.getWorkAgiExpGain();
|
||||
this.workChaExpGainRate = this.getWorkChaExpGain();
|
||||
this.workRepGainRate = this.getWorkRepGain();
|
||||
this.workMoneyGainRate = this.getWorkMoneyGain();
|
||||
|
||||
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours;
|
||||
|
||||
//Remove all old event listeners from Cancel button
|
||||
var newCancelButton = clearEventListeners("work-in-progress-cancel-button");
|
||||
newCancelButton.innerHTML = "Cancel Work";
|
||||
newCancelButton.addEventListener("click", function() {
|
||||
Player.finishWork(true);
|
||||
return false;
|
||||
});
|
||||
|
||||
//Display Work In Progress Screen
|
||||
Engine.loadWorkInProgressContent();
|
||||
}
|
||||
|
||||
PlayerObject.prototype.work = function(numCycles) {
|
||||
this.workRepGainRate = this.getWorkRepGain();
|
||||
|
||||
this.workHackExpGained += this.workHackExpGainRate * numCycles;
|
||||
this.workStrExpGained += this.workStrExpGainRate * numCycles;
|
||||
this.workDefExpGained += this.workDefExpGainRate * numCycles;
|
||||
this.workDexExpGained += this.workDexExpGainRate * numCycles;
|
||||
this.workAgiExpGained += this.workAgiExpGainRate * numCycles;
|
||||
this.workChaExpGained += this.workChaExpGainRate * numCycles;
|
||||
this.workRepGained += this.workRepGainRate * numCycles;
|
||||
this.workMoneyGained += this.workMoneyGainRate * numCycles;
|
||||
|
||||
var cyclesPerSec = 1000 / Engine._idleSpeed;
|
||||
|
||||
this.timeWorked += Engine._idleSpeed * numCycles;
|
||||
|
||||
//If timeWorked == 8 hours, then finish. You can only gain 8 hours worth of exp and money
|
||||
if (this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) {
|
||||
var maxCycles = CONSTANTS.GameCyclesPer8Hours;
|
||||
this.workHackExpGained = this.workHackExpGainRate * maxCycles;
|
||||
this.workStrExpGained = this.workStrExpGainRate * maxCycles;
|
||||
this.workDefExpGained = this.workDefExpGainRate * maxCycles;
|
||||
this.workDexExpGained = this.workDexExpGainRate * maxCycles;
|
||||
this.workAgiExpGained = this.workAgiExpGainRate * maxCycles;
|
||||
this.workChaExpGained = this.workChaExpGainRate * maxCycles;
|
||||
this.workRepGained = this.workRepGainRate * maxCycles;
|
||||
this.workMoneyGained = this.workMoneyGainRate * maxCycles;
|
||||
this.finishWork(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var comp = Companies[this.companyName], companyRep = "0";
|
||||
if (comp == null || !(comp instanceof Company)) {
|
||||
console.log("ERROR: Could not find Company: " + this.companyName);
|
||||
} else {
|
||||
companyRep = comp.playerReputation;
|
||||
}
|
||||
|
||||
var txt = document.getElementById("work-in-progress-text");
|
||||
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
|
||||
" at " + this.companyName + " (Current Company Reputation: " +
|
||||
formatNumber(companyRep, 0) + ")<br><br>" +
|
||||
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
|
||||
"You have earned: <br><br>" +
|
||||
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec) <br><br>" +
|
||||
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this company <br><br>" +
|
||||
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp <br><br>" +
|
||||
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp <br>" +
|
||||
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp <br>" +
|
||||
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp <br>" +
|
||||
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp <br><br> " +
|
||||
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp <br><br>" +
|
||||
"You will automatically finish after working for 8 hours. You can cancel earlier if you wish, " +
|
||||
"but you will only gain half of the reputation you've earned so far."
|
||||
|
||||
}
|
||||
|
||||
PlayerObject.prototype.startWorkPartTime = function() {
|
||||
this.resetWorkStatus();
|
||||
this.isWorking = true;
|
||||
@ -886,57 +815,50 @@ PlayerObject.prototype.startWorkPartTime = function() {
|
||||
}
|
||||
|
||||
PlayerObject.prototype.workPartTime = function(numCycles) {
|
||||
this.workRepGainRate = this.getWorkRepGain();
|
||||
|
||||
this.workHackExpGained += this.workHackExpGainRate * numCycles;
|
||||
this.workStrExpGained += this.workStrExpGainRate * numCycles;
|
||||
this.workDefExpGained += this.workDefExpGainRate * numCycles;
|
||||
this.workDexExpGained += this.workDexExpGainRate * numCycles;
|
||||
this.workAgiExpGained += this.workAgiExpGainRate * numCycles;
|
||||
this.workChaExpGained += this.workChaExpGainRate * numCycles;
|
||||
this.workRepGained += this.workRepGainRate * numCycles;
|
||||
this.workMoneyGained += this.workMoneyGainRate * numCycles;
|
||||
|
||||
var cyclesPerSec = 1000 / Engine._idleSpeed;
|
||||
|
||||
//Cap the number of cycles being processed to whatever would put you at the
|
||||
//work time limit (8 hours)
|
||||
var overMax = false;
|
||||
if (this.timeWorked + (Engine._idleSpeed * numCycles) >= CONSTANTS.MillisecondsPer8Hours) {
|
||||
overMax = true;
|
||||
numCycles = Math.round((CONSTANTS.MillisecondsPer8Hours - this.timeWorked) / Engine._idleSpeed);
|
||||
}
|
||||
this.timeWorked += Engine._idleSpeed * numCycles;
|
||||
|
||||
this.workRepGainRate = this.getWorkRepGain();
|
||||
this.processWorkEarnings(numCycles);
|
||||
|
||||
//If timeWorked == 8 hours, then finish. You can only gain 8 hours worth of exp and money
|
||||
if (this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) {
|
||||
var maxCycles = CONSTANTS.GameCyclesPer8Hours;
|
||||
this.workHackExpGained = this.workHackExpGainRate * maxCycles;
|
||||
this.workStrExpGained = this.workStrExpGainRate * maxCycles;
|
||||
this.workDefExpGained = this.workDefExpGainRate * maxCycles;
|
||||
this.workDexExpGained = this.workDexExpGainRate * maxCycles;
|
||||
this.workAgiExpGained = this.workAgiExpGainRate * maxCycles;
|
||||
this.workChaExpGained = this.workChaExpGainRate * maxCycles;
|
||||
this.workRepGained = this.workRepGainRate * maxCycles;
|
||||
this.workMoneyGained = this.workMoneyGainRate * maxCycles;
|
||||
this.finishWorkPartTime();
|
||||
return;
|
||||
if (overMax || this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) {
|
||||
return this.finishWorkPartTime();
|
||||
}
|
||||
|
||||
var comp = Companies[this.companyName], companyRep = "0";
|
||||
if (comp == null || !(comp instanceof Company)) {
|
||||
console.log("ERROR: Could not find Company: " + this.companyName);
|
||||
} else {
|
||||
companyRep = comp.playerReputation;
|
||||
}
|
||||
|
||||
var txt = document.getElementById("work-in-progress-text");
|
||||
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
|
||||
" at " + Player.companyName + "<br><br>" +
|
||||
" at " + Player.companyName + " (Current Company Reputation: " +
|
||||
formatNumber(companyRep, 0) + ")<br><br>" +
|
||||
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
|
||||
"You have earned: <br><br>" +
|
||||
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec) <br><br>" +
|
||||
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this company <br><br>" +
|
||||
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp <br><br>" +
|
||||
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp <br>" +
|
||||
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp <br>" +
|
||||
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp <br>" +
|
||||
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp <br><br> " +
|
||||
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp <br><br>" +
|
||||
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * CYCLES_PER_SEC, 2) + " / sec) <br><br>" +
|
||||
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * CYCLES_PER_SEC, 4) + " / sec) reputation for this company <br><br>" +
|
||||
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * CYCLES_PER_SEC, 4) + " / sec) hacking exp <br><br>" +
|
||||
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * CYCLES_PER_SEC, 4) + " / sec) strength exp <br>" +
|
||||
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * CYCLES_PER_SEC, 4) + " / sec) defense exp <br>" +
|
||||
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * CYCLES_PER_SEC, 4) + " / sec) dexterity exp <br>" +
|
||||
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * CYCLES_PER_SEC, 4) + " / sec) agility exp <br><br> " +
|
||||
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * CYCLES_PER_SEC, 4) + " / sec) charisma exp <br><br>" +
|
||||
"You will automatically finish after working for 8 hours. You can cancel earlier if you wish, <br>" +
|
||||
"and there will be no penalty because this is a part-time job.";
|
||||
|
||||
}
|
||||
|
||||
PlayerObject.prototype.finishWorkPartTime = function(sing=false) {
|
||||
this.gainWorkExp();
|
||||
|
||||
var company = Companies[this.companyName];
|
||||
company.playerReputation += (this.workRepGained);
|
||||
|
||||
@ -978,51 +900,6 @@ PlayerObject.prototype.finishWorkPartTime = function(sing=false) {
|
||||
}
|
||||
|
||||
/* Working for Faction */
|
||||
PlayerObject.prototype.finishFactionWork = function(cancelled, sing=false) {
|
||||
this.gainWorkExp();
|
||||
|
||||
var faction = Factions[this.currentWorkFactionName];
|
||||
faction.playerReputation += (this.workRepGained);
|
||||
|
||||
this.gainMoney(this.workMoneyGained);
|
||||
|
||||
this.updateSkillLevels();
|
||||
|
||||
var txt = "You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " <br><br> " +
|
||||
"You earned a total of: <br>" +
|
||||
"$" + formatNumber(this.workMoneyGained, 2) + "<br>" +
|
||||
formatNumber(this.workRepGained, 4) + " reputation for the faction <br>" +
|
||||
formatNumber(this.workHackExpGained, 4) + " hacking exp <br>" +
|
||||
formatNumber(this.workStrExpGained, 4) + " strength exp <br>" +
|
||||
formatNumber(this.workDefExpGained, 4) + " defense exp <br>" +
|
||||
formatNumber(this.workDexExpGained, 4) + " dexterity exp <br>" +
|
||||
formatNumber(this.workAgiExpGained, 4) + " agility exp <br>" +
|
||||
formatNumber(this.workChaExpGained, 4) + " charisma exp<br>";
|
||||
if (!sing) {dialogBoxCreate(txt);}
|
||||
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "visible";
|
||||
|
||||
this.isWorking = false;
|
||||
|
||||
Engine.loadFactionContent();
|
||||
displayFactionContent(faction.name);
|
||||
if (sing) {
|
||||
var res="You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + ". " +
|
||||
"You earned " +
|
||||
formatNumber(this.workRepGained, 4) + " rep, " +
|
||||
formatNumber(this.workHackExpGained, 4) + " hacking exp, " +
|
||||
formatNumber(this.workStrExpGained, 4) + " str exp, " +
|
||||
formatNumber(this.workDefExpGained, 4) + " def exp, " +
|
||||
formatNumber(this.workDexExpGained, 4) + " dex exp, " +
|
||||
formatNumber(this.workAgiExpGained, 4) + " agi exp, and " +
|
||||
formatNumber(this.workChaExpGained, 4) + " cha exp.";
|
||||
this.resetWorkStatus();
|
||||
return res;
|
||||
}
|
||||
this.resetWorkStatus();
|
||||
}
|
||||
|
||||
PlayerObject.prototype.startFactionWork = function(faction) {
|
||||
//Update reputation gain rate to account for faction favor
|
||||
var favorMult = 1 + (faction.favor / 100);
|
||||
@ -1117,52 +994,81 @@ PlayerObject.prototype.workForFaction = function(numCycles) {
|
||||
this.workRepGainRate *= favorMult;
|
||||
this.workRepGainRate *= BitNodeMultipliers.FactionWorkRepGain;
|
||||
|
||||
this.workHackExpGained += this.workHackExpGainRate * numCycles;
|
||||
this.workStrExpGained += this.workStrExpGainRate * numCycles;
|
||||
this.workDefExpGained += this.workDefExpGainRate * numCycles;
|
||||
this.workDexExpGained += this.workDexExpGainRate * numCycles;
|
||||
this.workAgiExpGained += this.workAgiExpGainRate * numCycles;
|
||||
this.workChaExpGained += this.workChaExpGainRate * numCycles;
|
||||
this.workRepGained += this.workRepGainRate * numCycles;
|
||||
this.workMoneyGained += this.workMoneyGainRate * numCycles;
|
||||
|
||||
var cyclesPerSec = 1000 / Engine._idleSpeed;
|
||||
|
||||
//Cap the number of cycles being processed to whatever would put you at limit (20 hours)
|
||||
var overMax = false;
|
||||
if (this.timeWorked + (Engine._idleSpeed * numCycles) >= CONSTANTS.MillisecondsPer20Hours) {
|
||||
overMax = true;
|
||||
numCycles = Math.round((CONSTANTS.MillisecondsPer20Hours - this.timeWorked) / Engine._idleSpeed);
|
||||
}
|
||||
this.timeWorked += Engine._idleSpeed * numCycles;
|
||||
|
||||
this.processWorkEarnings(numCycles);
|
||||
|
||||
//If timeWorked == 20 hours, then finish. You can only work for the faction for 20 hours
|
||||
if (this.timeWorked >= CONSTANTS.MillisecondsPer20Hours) {
|
||||
var maxCycles = CONSTANTS.GameCyclesPer20Hours;
|
||||
this.timeWorked = CONSTANTS.MillisecondsPer20Hours;
|
||||
this.workHackExpGained = this.workHackExpGainRate * maxCycles;
|
||||
this.workStrExpGained = this.workStrExpGainRate * maxCycles;
|
||||
this.workDefExpGained = this.workDefExpGainRate * maxCycles;
|
||||
this.workDexExpGained = this.workDexExpGainRate * maxCycles;
|
||||
this.workAgiExpGained = this.workAgiExpGainRate * maxCycles;
|
||||
this.workChaExpGained = this.workChaExpGainRate * maxCycles;
|
||||
this.workRepGained = this.workRepGainRate * maxCycles;
|
||||
this.workMoneyGained = this.workMoneyGainRate * maxCycles;
|
||||
this.finishFactionWork(false);
|
||||
if (overMax || this.timeWorked >= CONSTANTS.MillisecondsPer20Hours) {
|
||||
return this.finishWork(false);
|
||||
}
|
||||
|
||||
var txt = document.getElementById("work-in-progress-text");
|
||||
txt.innerHTML = "You are currently " + this.currentWorkFactionDescription + " for your faction " + faction.name +
|
||||
" (Current Faction Reputation: " + formatNumber(faction.playerReputation, 0) + "). " +
|
||||
" (Current Faction Reputation: " + formatNumber(faction.playerReputation, 0) + "). <br>" +
|
||||
"You have been doing this for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
|
||||
"You have earned: <br><br>" +
|
||||
"$" + formatNumber(this.workMoneyGained, 2) + " (" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec) <br><br>" +
|
||||
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this faction <br><br>" +
|
||||
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp <br><br>" +
|
||||
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp <br>" +
|
||||
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp <br>" +
|
||||
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp <br>" +
|
||||
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp <br><br> " +
|
||||
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp <br><br>" +
|
||||
"$" + formatNumber(this.workMoneyGained, 2) + " (" + formatNumber(this.workMoneyGainRate * CYCLES_PER_SEC, 2) + " / sec) <br><br>" +
|
||||
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * CYCLES_PER_SEC, 4) + " / sec) reputation for this faction <br><br>" +
|
||||
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * CYCLES_PER_SEC, 4) + " / sec) hacking exp <br><br>" +
|
||||
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * CYCLES_PER_SEC, 4) + " / sec) strength exp <br>" +
|
||||
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * CYCLES_PER_SEC, 4) + " / sec) defense exp <br>" +
|
||||
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * CYCLES_PER_SEC, 4) + " / sec) dexterity exp <br>" +
|
||||
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * CYCLES_PER_SEC, 4) + " / sec) agility exp <br><br> " +
|
||||
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * CYCLES_PER_SEC, 4) + " / sec) charisma exp <br><br>" +
|
||||
|
||||
"You will automatically finish after working for 20 hours. You can cancel earlier if you wish.<br>" +
|
||||
"There is no penalty for cancelling earlier.";
|
||||
}
|
||||
|
||||
PlayerObject.prototype.finishFactionWork = function(cancelled, sing=false) {
|
||||
var faction = Factions[this.currentWorkFactionName];
|
||||
faction.playerReputation += (this.workRepGained);
|
||||
|
||||
this.gainMoney(this.workMoneyGained);
|
||||
|
||||
this.updateSkillLevels();
|
||||
|
||||
var txt = "You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " <br><br> " +
|
||||
"You earned a total of: <br>" +
|
||||
"$" + formatNumber(this.workMoneyGained, 2) + "<br>" +
|
||||
formatNumber(this.workRepGained, 4) + " reputation for the faction <br>" +
|
||||
formatNumber(this.workHackExpGained, 4) + " hacking exp <br>" +
|
||||
formatNumber(this.workStrExpGained, 4) + " strength exp <br>" +
|
||||
formatNumber(this.workDefExpGained, 4) + " defense exp <br>" +
|
||||
formatNumber(this.workDexExpGained, 4) + " dexterity exp <br>" +
|
||||
formatNumber(this.workAgiExpGained, 4) + " agility exp <br>" +
|
||||
formatNumber(this.workChaExpGained, 4) + " charisma exp<br>";
|
||||
if (!sing) {dialogBoxCreate(txt);}
|
||||
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "visible";
|
||||
|
||||
this.isWorking = false;
|
||||
|
||||
Engine.loadFactionContent();
|
||||
displayFactionContent(faction.name);
|
||||
if (sing) {
|
||||
var res="You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + ". " +
|
||||
"You earned " +
|
||||
formatNumber(this.workRepGained, 4) + " rep, " +
|
||||
formatNumber(this.workHackExpGained, 4) + " hacking exp, " +
|
||||
formatNumber(this.workStrExpGained, 4) + " str exp, " +
|
||||
formatNumber(this.workDefExpGained, 4) + " def exp, " +
|
||||
formatNumber(this.workDexExpGained, 4) + " dex exp, " +
|
||||
formatNumber(this.workAgiExpGained, 4) + " agi exp, and " +
|
||||
formatNumber(this.workChaExpGained, 4) + " cha exp.";
|
||||
this.resetWorkStatus();
|
||||
return res;
|
||||
}
|
||||
this.resetWorkStatus();
|
||||
}
|
||||
|
||||
//Money gained per game cycle
|
||||
PlayerObject.prototype.getWorkMoneyGain = function() {
|
||||
@ -1438,36 +1344,25 @@ PlayerObject.prototype.takeClass = function(numCycles) {
|
||||
this.timeWorked += Engine._idleSpeed * numCycles;
|
||||
var className = this.className;
|
||||
|
||||
this.workHackExpGained += this.workHackExpGainRate * numCycles;
|
||||
this.workStrExpGained += this.workStrExpGainRate * numCycles;
|
||||
this.workDefExpGained += this.workDefExpGainRate * numCycles;
|
||||
this.workDexExpGained += this.workDexExpGainRate * numCycles;
|
||||
this.workAgiExpGained += this.workAgiExpGainRate * numCycles;
|
||||
this.workChaExpGained += this.workChaExpGainRate * numCycles;
|
||||
this.workRepGained += this.workRepGainRate * numCycles;
|
||||
this.workMoneyGained += this.workMoneyGainRate * numCycles;
|
||||
this.workMoneyGained -= this.workMoneyLossRate * numCycles;
|
||||
|
||||
var cyclesPerSec = 1000 / Engine._idleSpeed;
|
||||
this.processWorkEarnings(numCycles);
|
||||
|
||||
var txt = document.getElementById("work-in-progress-text");
|
||||
txt.innerHTML = "You have been " + className + " for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
|
||||
"This has cost you: <br>" +
|
||||
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyLossRate * cyclesPerSec, 2) + " / sec) <br><br>" +
|
||||
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyLossRate * CYCLES_PER_SEC, 2) + " / sec) <br><br>" +
|
||||
"You have gained: <br>" +
|
||||
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp <br>" +
|
||||
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp <br>" +
|
||||
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp <br>" +
|
||||
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp <br>" +
|
||||
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp <br>" +
|
||||
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp <br>" +
|
||||
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * CYCLES_PER_SEC, 4) + " / sec) hacking exp <br>" +
|
||||
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * CYCLES_PER_SEC, 4) + " / sec) strength exp <br>" +
|
||||
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * CYCLES_PER_SEC, 4) + " / sec) defense exp <br>" +
|
||||
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * CYCLES_PER_SEC, 4) + " / sec) dexterity exp <br>" +
|
||||
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * CYCLES_PER_SEC, 4) + " / sec) agility exp <br>" +
|
||||
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * CYCLES_PER_SEC, 4) + " / sec) charisma exp <br>" +
|
||||
"You may cancel at any time";
|
||||
}
|
||||
|
||||
//The 'sing' argument defines whether or not this function was called
|
||||
//through a Singularity Netscript function
|
||||
PlayerObject.prototype.finishClass = function(sing=false) {
|
||||
this.gainWorkExp();
|
||||
this.gainIntelligenceExp(CONSTANTS.IntelligenceClassBaseExpGain * Math.round(this.timeWorked / 1000));
|
||||
|
||||
if (this.workMoneyGained > 0) {
|
||||
@ -1592,7 +1487,7 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
|
||||
if (this.committingCrimeThruSingFn) {
|
||||
if(this.singFnCrimeWorkerScript.disableLogs.ALL == null && this.singFnCrimeWorkerScript.disableLogs.commitCrime == null) {
|
||||
this.singFnCrimeWorkerScript.scriptRef.log("Crime successful! Gained " +
|
||||
numeral(this.workMoneyGained).format("$0.000a") + ", " +
|
||||
numeralWrapper.format(this.workMoneyGained, "$0.000a") + ", " +
|
||||
formatNumber(this.workHackExpGained, 3) + " hack exp, " +
|
||||
formatNumber(this.workStrExpGained, 3) + " str exp, " +
|
||||
formatNumber(this.workDefExpGained, 3) + " def exp, " +
|
||||
@ -1642,7 +1537,12 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
|
||||
}
|
||||
}
|
||||
|
||||
this.gainWorkExp();
|
||||
this.gainHackingExp(this.workHackExpGained);
|
||||
this.gainStrengthExp(this.workStrExpGained);
|
||||
this.gainDefenseExp(this.workDefExpGained);
|
||||
this.gainDexterityExp(this.workDexExpGained);
|
||||
this.gainAgilityExp(this.workAgiExpGained);
|
||||
this.gainCharismaExp(this.workChaExpGained);
|
||||
}
|
||||
this.committingCrimeThruSingFn = false;
|
||||
this.singFnCrimeWorkerScript = null;
|
||||
@ -1701,7 +1601,7 @@ 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 " +
|
||||
numeral(this.max_hp * CONSTANTS.HospitalCostPerHp).format('$0.000a')
|
||||
numeralWrapper.format(this.max_hp * CONSTANTS.HospitalCostPerHp, '$0.000a')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -451,7 +451,7 @@ function loadImportedGame(saveObj, saveString) {
|
||||
|
||||
var popupId = "import-game-restart-game-notice";
|
||||
var txt = createElement("p", {
|
||||
innerText:"Imported game! I would suggest saving the game and then reloading the page " +
|
||||
innerText:"Imported game! You need to SAVE the game and then RELOAD the page " +
|
||||
"to make sure everything runs smoothly"
|
||||
});
|
||||
var gotitBtn = createElement("a", {
|
||||
@ -516,9 +516,9 @@ function loadImportedGame(saveObj, saveString) {
|
||||
|
||||
Player.lastUpdate = Engine._lastUpdate;
|
||||
Engine.start(); //Run main game loop and Scripts loop
|
||||
dialogBoxCreate("While you were offline, your scripts generated $" +
|
||||
formatNumber(offlineProductionFromScripts, 2) + " and your Hacknet Nodes generated $" +
|
||||
formatNumber(offlineProductionFromHacknetNodes, 2));
|
||||
dialogBoxCreate("While you were offline, your scripts generated <span class='money-gold'>$" +
|
||||
formatNumber(offlineProductionFromScripts, 2) + "</span> and your Hacknet Nodes generated <span class='money-gold'>$" +
|
||||
formatNumber(offlineProductionFromHacknetNodes, 2) + "</span>");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
32
src/Script.js
Normal file → Executable file
32
src/Script.js
Normal file → Executable file
@ -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,
|
||||
@ -31,15 +31,14 @@ import {AllServers, processSingleServerGrowth} from "./Server";
|
||||
import {Settings} from "./Settings";
|
||||
import {post} from "./ui/postToTerminal";
|
||||
import {TextFile} from "./TextFile";
|
||||
|
||||
import {parse, Node} from "../utils/acorn";
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver";
|
||||
import {compareArrays} from "../utils/helpers/compareArrays";
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {formatNumber} from "../utils/StringHelperFunctions";
|
||||
import {getTimestamp} from "../utils/helpers/getTimestamp";
|
||||
import {roundToTwo} from "../utils/helpers/roundToTwo";
|
||||
|
||||
@ -252,7 +251,7 @@ function updateScriptEditorContent() {
|
||||
var codeCopy = code.repeat(1);
|
||||
var ramUsage = calculateRamUsage(codeCopy);
|
||||
if (ramUsage !== -1) {
|
||||
scriptEditorRamText.innerText = "RAM: " + formatNumber(ramUsage, 2).toString() + "GB";
|
||||
scriptEditorRamText.innerText = "RAM: " + numeralWrapper.format(ramUsage, '0.00') + " GB";
|
||||
} else {
|
||||
scriptEditorRamText.innerText = "RAM: Syntax Error";
|
||||
}
|
||||
@ -281,8 +280,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;
|
||||
}
|
||||
@ -291,7 +291,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 == "") {
|
||||
@ -858,7 +874,7 @@ function scriptCalculateOfflineProduction(runningScriptObj) {
|
||||
console.log(runningScriptObj.filename + " called grow() on " + serv.hostname + " " + timesGrown + " times while offline");
|
||||
runningScriptObj.log("Called grow() on " + serv.hostname + " " + timesGrown + " times while offline");
|
||||
var growth = processSingleServerGrowth(serv, timesGrown * 450);
|
||||
runningScriptObj.log(serv.hostname + " grown by " + formatNumber(growth * 100 - 100, 6) + "% from grow() calls made while offline");
|
||||
runningScriptObj.log(serv.hostname + " grown by " + numeralWrapper.format(growth * 100 - 100, '0.000000%') + " from grow() calls made while offline");
|
||||
}
|
||||
}
|
||||
|
||||
|
685
src/Server.js
685
src/Server.js
@ -2,10 +2,10 @@ import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Programs} from "./CreateProgram";
|
||||
import {Player} from "./Player";
|
||||
import {RunningScript, Script} from "./Script";
|
||||
import {SpecialServerNames, SpecialServerIps} from "./SpecialServerIps";
|
||||
import {SpecialServerIps} from "./SpecialServerIps";
|
||||
import {getRandomInt} from "../utils/helpers/getRandomInt";
|
||||
import {createRandomIp, ipExists} from "../utils/IPAddress";
|
||||
import {serverMetadata} from "./data/servers";
|
||||
import {Reviver, Generic_toJSON,
|
||||
Generic_fromJSON} from "../utils/JSONReviver";
|
||||
import {isValidIPAddress} from "../utils/helpers/isValidIPAddress";
|
||||
@ -125,652 +125,83 @@ Server.fromJSON = function(value) {
|
||||
Reviver.constructors.Server = Server;
|
||||
|
||||
function initForeignServers() {
|
||||
//MegaCorporations
|
||||
var ECorpServer = new Server({
|
||||
ip:createRandomIp(), hostname:"ecorp", organizationName:"ECorp",
|
||||
requiredHackingSkill:getRandomInt(1150, 1300), moneyAvailable:getRandomInt(30e9, 70e9),
|
||||
hackDifficulty:99,serverGrowth:99, numOpenPortsRequired: 5,
|
||||
});
|
||||
AddToAllServers(ECorpServer);
|
||||
|
||||
var MegaCorpServer = new Server({
|
||||
ip:createRandomIp(), hostname:"megacorp", organizationName:"MegaCorp",
|
||||
requiredHackingSkill:getRandomInt(1150, 1300), moneyAvailable:getRandomInt(40e9, 60e9),
|
||||
hackDifficulty:99, serverGrowth:99, numOpenPortsRequired:5
|
||||
});
|
||||
AddToAllServers(MegaCorpServer);
|
||||
|
||||
var BachmanAndAssociatesServer = new Server({
|
||||
ip:createRandomIp(), hostname:"b-and-a", organizationName:"Bachman & Associates",
|
||||
requiredHackingSkill:getRandomInt(1000, 1050), moneyAvailable:getRandomInt(20e9, 25e9),
|
||||
hackDifficulty:getRandomInt(75, 85), serverGrowth:getRandomInt(65, 75), numOpenPortsRequired:5
|
||||
});
|
||||
AddToAllServers(BachmanAndAssociatesServer);
|
||||
|
||||
var BladeIndustriesServer = new Server({
|
||||
ip:createRandomIp(), hostname:"blade", organizationName:"Blade Industries", maxRam:128,
|
||||
requiredHackingSkill:getRandomInt(1000, 1100), moneyAvailable:getRandomInt(12e9, 20e9),
|
||||
hackDifficulty:getRandomInt(90, 95), serverGrowth:getRandomInt(60, 75), numOpenPortsRequired:5
|
||||
});
|
||||
BladeIndustriesServer.messages.push("beyond-man.lit");
|
||||
AddToAllServers(BladeIndustriesServer);
|
||||
|
||||
var NWOServer = new Server({
|
||||
ip:createRandomIp(), hostname:"nwo", organizationName:"New World Order",
|
||||
requiredHackingSkill:getRandomInt(1000, 1200), moneyAvailable:getRandomInt(25e9, 35e9),
|
||||
hackDifficulty:99, serverGrowth:getRandomInt(75, 85), numOpenPortsRequired:5
|
||||
});
|
||||
NWOServer.messages.push("the-hidden-world.lit");
|
||||
AddToAllServers(NWOServer);
|
||||
|
||||
var ClarkeIncorporatedServer = new Server({
|
||||
ip:createRandomIp(), hostname:"clarkeinc", organizationName:"Clarke Incorporated",
|
||||
requiredHackingSkill:getRandomInt(1000, 1200), moneyAvailable:getRandomInt(15e9, 25e9),
|
||||
hackDifficulty:getRandomInt(50, 60), serverGrowth:getRandomInt(50, 70), numOpenPortsRequired:5
|
||||
});
|
||||
ClarkeIncorporatedServer.messages.push("beyond-man.lit");
|
||||
ClarkeIncorporatedServer.messages.push("cost-of-immortality.lit");
|
||||
AddToAllServers(ClarkeIncorporatedServer);
|
||||
|
||||
var OmniTekIncorporatedServer = new Server({
|
||||
ip:createRandomIp(), hostname:"omnitek", organizationName:"OmniTek Incorporated", maxRam:256,
|
||||
requiredHackingSkill:getRandomInt(900, 1100), moneyAvailable:getRandomInt(15e9, 20e9),
|
||||
hackDifficulty:getRandomInt(90, 99), serverGrowth:getRandomInt(95, 99), numOpenPortsRequired:5
|
||||
});
|
||||
OmniTekIncorporatedServer.messages.push("coded-intelligence.lit");
|
||||
OmniTekIncorporatedServer.messages.push("history-of-synthoids.lit");
|
||||
AddToAllServers(OmniTekIncorporatedServer);
|
||||
|
||||
var FourSigmaServer = new Server({
|
||||
ip:createRandomIp(), hostname:"4sigma", organizationName:"FourSigma",
|
||||
requiredHackingSkill:getRandomInt(950, 1200), moneyAvailable:getRandomInt(15e9, 25e9),
|
||||
hackDifficulty:getRandomInt(60, 70), serverGrowth:getRandomInt(75, 99), numOpenPortsRequired:5
|
||||
});
|
||||
AddToAllServers(FourSigmaServer);
|
||||
|
||||
var KuaiGongInternationalServer = new Server({
|
||||
ip:createRandomIp(), hostname:"kuai-gong", organizationName:"KuaiGong International",
|
||||
requiredHackingSkill:getRandomInt(1000, 1250), moneyAvailable:getRandomInt(20e9, 30e9),
|
||||
hackDifficulty:getRandomInt(95, 99), serverGrowth:getRandomInt(90, 99), numOpenPortsRequired:5,
|
||||
});
|
||||
AddToAllServers(KuaiGongInternationalServer);
|
||||
|
||||
//Technology and communications companies (large targets)
|
||||
var FulcrumTechnologiesServer = new Server({
|
||||
ip:createRandomIp(), hostname:"fulcrumtech", organizationName:"Fulcrum Technologies", maxRam:512,
|
||||
requiredHackingSkill:getRandomInt(1000, 1200), moneyAvailable:getRandomInt(1.4e9, 1.8e9),
|
||||
hackDifficulty:getRandomInt(85, 95), serverGrowth:getRandomInt(80, 99), numOpenPortsRequired:5
|
||||
});
|
||||
FulcrumTechnologiesServer.messages.push("simulated-reality.lit");
|
||||
AddToAllServers(FulcrumTechnologiesServer);
|
||||
|
||||
var FulcrumSecretTechnologiesServer = new Server({
|
||||
ip:createRandomIp(), hostname:"fulcrumassets", organizationName:"Fulcrum Technologies Assets",
|
||||
requiredHackingSkill:getRandomInt(1200, 1500), moneyAvailable:1e6,
|
||||
hackDifficulty:99, serverGrowth:1, numOpenPortsRequired:5
|
||||
});
|
||||
AddToAllServers(FulcrumSecretTechnologiesServer);
|
||||
SpecialServerIps.addIp(SpecialServerNames.FulcrumSecretTechnologies, FulcrumSecretTechnologiesServer.ip);
|
||||
|
||||
var StormTechnologiesServer = new Server({
|
||||
ip:createRandomIp(), hostname:"stormtech", organizationName:"Storm Technologies",
|
||||
requiredHackingSkill:getRandomInt(900, 1050), moneyAvailable:getRandomInt(1e9, 1.2e9),
|
||||
hackDifficulty:getRandomInt(80, 90), serverGrowth:getRandomInt(70, 90), numOpenPortsRequired:5
|
||||
});
|
||||
AddToAllServers(StormTechnologiesServer);
|
||||
|
||||
var DefCommServer = new Server({
|
||||
ip:createRandomIp(), hostname:"defcomm", organizationName:"DefComm",
|
||||
requiredHackingSkill:getRandomInt(900, 1000), moneyAvailable:getRandomInt(800e6, 950e6),
|
||||
hackDifficulty:getRandomInt(85, 95), serverGrowth:getRandomInt(50, 70), numOpenPortsRequired:5
|
||||
});
|
||||
AddToAllServers(DefCommServer);
|
||||
|
||||
var InfoCommServer = new Server({
|
||||
ip:createRandomIp(), hostname:"infocomm", organizationName:"InfoComm",
|
||||
requiredHackingSkill:getRandomInt(875, 950), moneyAvailable:getRandomInt(600e6, 900e6),
|
||||
hackDifficulty:getRandomInt(70, 90), serverGrowth:getRandomInt(35, 75), numOpenPortsRequired:5
|
||||
});
|
||||
AddToAllServers(InfoCommServer);
|
||||
|
||||
var HeliosLabsServer = new Server({
|
||||
ip:createRandomIp(), hostname:"helios", organizationName:"Helios Labs", maxRam:128,
|
||||
requiredHackingSkill:getRandomInt(800, 900), moneyAvailable:getRandomInt(550e6, 750e6),
|
||||
hackDifficulty:getRandomInt(85, 95), serverGrowth:getRandomInt(70, 80), numOpenPortsRequired:5
|
||||
});
|
||||
HeliosLabsServer.messages.push("beyond-man.lit");
|
||||
AddToAllServers(HeliosLabsServer);
|
||||
|
||||
var VitaLifeServer = new Server({
|
||||
ip:createRandomIp(), hostname:"vitalife", organizationName:"VitaLife", maxRam:64,
|
||||
requiredHackingSkill:getRandomInt(775, 900), moneyAvailable:getRandomInt(700e6, 800e6),
|
||||
hackDifficulty:getRandomInt(80, 90), serverGrowth:getRandomInt(60, 80), numOpenPortsRequired:5
|
||||
});
|
||||
VitaLifeServer.messages.push("A-Green-Tomorrow.lit");
|
||||
AddToAllServers(VitaLifeServer);
|
||||
|
||||
var IcarusMicrosystemsServer = new Server({
|
||||
ip:createRandomIp(), hostname:"icarus", organizationName:"Icarus Microsystems",
|
||||
requiredHackingSkill:getRandomInt(850, 925), moneyAvailable:getRandomInt(900e6, 1000e6),
|
||||
hackDifficulty:getRandomInt(85, 95), serverGrowth:getRandomInt(85, 95), numOpenPortsRequired:5
|
||||
});
|
||||
AddToAllServers(IcarusMicrosystemsServer);
|
||||
|
||||
var UniversalEnergyServer = new Server({
|
||||
ip:createRandomIp(), hostname:"univ-energy", organizationName:"Universal Energy", maxRam:64,
|
||||
requiredHackingSkill:getRandomInt(800, 900), moneyAvailable:getRandomInt(1.1e9, 1.2e9),
|
||||
hackDifficulty:getRandomInt(80, 90), serverGrowth:getRandomInt(80, 90), numOpenPortsRequired:4
|
||||
});
|
||||
AddToAllServers(UniversalEnergyServer);
|
||||
|
||||
var TitanLabsServer = new Server({
|
||||
ip:createRandomIp(), hostname:"titan-labs", organizationName:"Titan Laboratories", maxRam:64,
|
||||
requiredHackingSkill:getRandomInt(800, 875), moneyAvailable:getRandomInt(750e6, 900e6),
|
||||
hackDifficulty:getRandomInt(70, 80), serverGrowth:getRandomInt(60, 80), numOpenPortsRequired:5
|
||||
});
|
||||
TitanLabsServer.messages.push("coded-intelligence.lit");
|
||||
AddToAllServers(TitanLabsServer);
|
||||
|
||||
var MicrodyneTechnologiesServer = new Server({
|
||||
ip:createRandomIp(), hostname:"microdyne", organizationName:"Microdyne Technologies", maxRam:32,
|
||||
requiredHackingSkill:getRandomInt(800, 875), moneyAvailable:getRandomInt(500e6, 700e6),
|
||||
hackDifficulty:getRandomInt(65, 75), serverGrowth:getRandomInt(70, 90), numOpenPortsRequired:5
|
||||
});
|
||||
MicrodyneTechnologiesServer.messages.push("synthetic-muscles.lit");
|
||||
AddToAllServers(MicrodyneTechnologiesServer);
|
||||
|
||||
var TaiYangDigitalServer = new Server({
|
||||
ip:createRandomIp(), hostname:"taiyang-digital", organizationName:"Taiyang Digital",
|
||||
requiredHackingSkill:getRandomInt(850, 950), moneyAvailable:getRandomInt(800e6, 900e6),
|
||||
hackDifficulty:getRandomInt(70, 80), serverGrowth:getRandomInt(70, 80), numOpenPortsRequired:5
|
||||
});
|
||||
TaiYangDigitalServer.messages.push("A-Green-Tomorrow.lit");
|
||||
TaiYangDigitalServer.messages.push("brighter-than-the-sun.lit");
|
||||
AddToAllServers(TaiYangDigitalServer);
|
||||
|
||||
var GalacticCyberSystemsServer = new Server({
|
||||
ip:createRandomIp(), hostname:"galactic-cyber", organizationName:"Galactic Cybersystems",
|
||||
requiredHackingSkill:getRandomInt(825, 875), moneyAvailable:getRandomInt(750e6, 850e6),
|
||||
hackDifficulty:getRandomInt(55, 65), serverGrowth:getRandomInt(70, 90), numOpenPortsRequired:5
|
||||
});
|
||||
AddToAllServers(GalacticCyberSystemsServer);
|
||||
|
||||
//Defense Companies ("Large" Companies)
|
||||
var AeroCorpServer = new Server({
|
||||
ip:createRandomIp(), hostname:"aerocorp", organizationName:"AeroCorp",
|
||||
requiredHackingSkill:getRandomInt(850, 925), moneyAvailable:getRandomInt(1e9, 1.2e9),
|
||||
hackDifficulty:getRandomInt(80, 90), serverGrowth:getRandomInt(55, 65), numOpenPortsRequired:5
|
||||
});
|
||||
AeroCorpServer.messages.push("man-and-machine.lit");
|
||||
AddToAllServers(AeroCorpServer);
|
||||
|
||||
var OmniaCybersystemsServer = new Server({
|
||||
ip:createRandomIp(), hostname:"omnia", organizationName:"Omnia Cybersystems", maxRam:64,
|
||||
requiredHackingSkill:getRandomInt(850, 950), moneyAvailable:getRandomInt(900e6, 1e9),
|
||||
hackDifficulty:getRandomInt(85, 95), serverGrowth:getRandomInt(60, 70), numOpenPortsRequired:5
|
||||
});
|
||||
OmniaCybersystemsServer.messages.push("history-of-synthoids.lit");
|
||||
AddToAllServers(OmniaCybersystemsServer);
|
||||
|
||||
var ZBDefenseServer = new Server({
|
||||
ip:createRandomIp(), hostname:"zb-def", organizationName:"ZB Defense Industries",
|
||||
requiredHackingSkill:getRandomInt(775, 825), moneyAvailable:getRandomInt(900e6, 1.1e9),
|
||||
hackDifficulty:getRandomInt(55, 65), serverGrowth:getRandomInt(65, 75), numOpenPortsRequired:4
|
||||
});
|
||||
ZBDefenseServer.messages.push("synthetic-muscles.lit");
|
||||
AddToAllServers(ZBDefenseServer);
|
||||
|
||||
var AppliedEnergeticsServer = new Server({
|
||||
ip:createRandomIp(), hostname:"applied-energetics", organizationName:"Applied Energetics",
|
||||
requiredHackingSkill:getRandomInt(775, 850), moneyAvailable:getRandomInt(700e6, 1e9),
|
||||
hackDifficulty:getRandomInt(60, 80), serverGrowth:getRandomInt(70, 75), numOpenPortsRequired:4
|
||||
});
|
||||
AddToAllServers(AppliedEnergeticsServer);
|
||||
|
||||
var SolarisSpaceSystemsServer = new Server({
|
||||
ip:createRandomIp(), hostname:"solaris", organizationName:"Solaris Space Systems", maxRam:64,
|
||||
requiredHackingSkill:getRandomInt(750, 850), moneyAvailable:getRandomInt(700e6, 900e6),
|
||||
hackDifficulty:getRandomInt(70, 80), serverGrowth:getRandomInt(70, 80), numOpenPortsRequired:5
|
||||
});
|
||||
SolarisSpaceSystemsServer.messages.push("A-Green-Tomorrow.lit");
|
||||
SolarisSpaceSystemsServer.messages.push("the-failed-frontier.lit");
|
||||
AddToAllServers(SolarisSpaceSystemsServer);
|
||||
|
||||
var DeltaOneServer = new Server({
|
||||
ip:createRandomIp(), hostname:"deltaone", organizationName:"Delta One",
|
||||
requiredHackingSkill:getRandomInt(800, 900), moneyAvailable:getRandomInt(1.3e9, 1.7e9),
|
||||
hackDifficulty:getRandomInt(75, 85), serverGrowth:getRandomInt(50, 70), numOpenPortsRequired:5
|
||||
});
|
||||
AddToAllServers(DeltaOneServer);
|
||||
|
||||
//Health, medicine, pharmaceutical companies ("Large" targets)
|
||||
var GlobalPharmaceuticalsServer = new Server({
|
||||
ip:createRandomIp(), hostname:"global-pharm", organizationName:"Global Pharmaceuticals", maxRam:32,
|
||||
requiredHackingSkill:getRandomInt(750, 850), moneyAvailable:getRandomInt(1.5e9, 1.75e9),
|
||||
hackDifficulty:getRandomInt(75, 85), serverGrowth:getRandomInt(80, 90), numOpenPortsRequired:4
|
||||
});
|
||||
GlobalPharmaceuticalsServer.messages.push("A-Green-Tomorrow.lit");
|
||||
AddToAllServers(GlobalPharmaceuticalsServer);
|
||||
|
||||
var NovaMedicalServer = new Server({
|
||||
ip:createRandomIp(), hostname:"nova-med", organizationName:"Nova Medical",
|
||||
requiredHackingSkill:getRandomInt(775, 850), moneyAvailable:getRandomInt(1.1e9, 1.25e9),
|
||||
hackDifficulty:getRandomInt(60, 80), serverGrowth:getRandomInt(65, 85), numOpenPortsRequired:4
|
||||
});
|
||||
AddToAllServers(NovaMedicalServer);
|
||||
|
||||
var ZeusMedicalServer = new Server({
|
||||
ip:createRandomIp(), hostname:"zeus-med", organizationName:"Zeus Medical",
|
||||
requiredHackingSkill:getRandomInt(800, 850), moneyAvailable:getRandomInt(1.3e9, 1.5e9),
|
||||
hackDifficulty:getRandomInt(70, 90), serverGrowth:getRandomInt(70, 80), numOpenPortsRequired:5
|
||||
});
|
||||
AddToAllServers(ZeusMedicalServer);
|
||||
|
||||
var UnitaLifeGroupServer = new Server({
|
||||
ip:createRandomIp(), hostname:"unitalife", organizationName:"UnitaLife Group", maxRam:32,
|
||||
requiredHackingSkill:getRandomInt(775, 825), moneyAvailable:getRandomInt(1e9, 1.1e9),
|
||||
hackDifficulty:getRandomInt(70, 80), serverGrowth:getRandomInt(70, 80), numOpenPortsRequired:4
|
||||
});
|
||||
AddToAllServers(UnitaLifeGroupServer);
|
||||
|
||||
//"Medium level" targets
|
||||
var LexoCorpServer = new Server({
|
||||
ip:createRandomIp(), hostname:"lexo-corp", organizationName:"Lexo Corporation", maxRam:32,
|
||||
requiredHackingSkill:getRandomInt(650, 750), moneyAvailable:getRandomInt(700e6, 800e6),
|
||||
hackDifficulty:getRandomInt(60, 80), serverGrowth:getRandomInt(55, 65), numOpenPortsRequired:4
|
||||
});
|
||||
AddToAllServers(LexoCorpServer);
|
||||
|
||||
var RhoConstructionServer = new Server({
|
||||
ip:createRandomIp(), hostname:"rho-construction", organizationName:"Rho Construction",
|
||||
requiredHackingSkill:getRandomInt(475, 525), moneyAvailable:getRandomInt(500e6, 700e6),
|
||||
hackDifficulty:getRandomInt(40, 60), serverGrowth:getRandomInt(40, 60), numOpenPortsRequired:3
|
||||
});
|
||||
AddToAllServers(RhoConstructionServer);
|
||||
|
||||
var AlphaEnterprisesServer = new Server({
|
||||
ip:createRandomIp(), hostname:"alpha-ent", organizationName:"Alpha Enterprises", maxRam:32,
|
||||
requiredHackingSkill:getRandomInt(500, 600), moneyAvailable:getRandomInt(600e6, 750e6),
|
||||
hackDifficulty:getRandomInt(50, 70), serverGrowth:getRandomInt(50, 60),numOpenPortsRequired:4
|
||||
});
|
||||
AlphaEnterprisesServer.messages.push("sector-12-crime.lit");
|
||||
AddToAllServers(AlphaEnterprisesServer);
|
||||
|
||||
var AevumPoliceServer = new Server({
|
||||
ip:createRandomIp(), hostname:"aevum-police", organizationName:"Aevum Police Network", maxRam:32,
|
||||
requiredHackingSkill:getRandomInt(400, 450), moneyAvailable:getRandomInt(200e6, 400e6),
|
||||
hackDifficulty:getRandomInt(70, 80), serverGrowth:getRandomInt(30, 50), numOpenPortsRequired:4
|
||||
});
|
||||
AddToAllServers(AevumPoliceServer);
|
||||
|
||||
var RothmanUniversityServer = new Server({
|
||||
ip:createRandomIp(), hostname:"rothman-uni", organizationName:"Rothman University Network", maxRam:64,
|
||||
requiredHackingSkill:getRandomInt(370, 430), moneyAvailable:getRandomInt(175e6, 250e6),
|
||||
hackDifficulty:getRandomInt(45, 55), serverGrowth:getRandomInt(35, 45), numOpenPortsRequired:3
|
||||
});
|
||||
RothmanUniversityServer.messages.push("secret-societies.lit");
|
||||
RothmanUniversityServer.messages.push("the-failed-frontier.lit");
|
||||
RothmanUniversityServer.messages.push("tensions-in-tech-race.lit");
|
||||
AddToAllServers(RothmanUniversityServer);
|
||||
|
||||
var ZBInstituteOfTechnologyServer = new Server({
|
||||
ip:createRandomIp(), hostname:"zb-institute", organizationName:"ZB Institute of Technology Network", maxRam:64,
|
||||
requiredHackingSkill:getRandomInt(725, 775), moneyAvailable:getRandomInt(800e6, 1.1e9),
|
||||
hackDifficulty:getRandomInt(65, 85), serverGrowth:getRandomInt(75, 85), numOpenPortsRequired:5
|
||||
});
|
||||
AddToAllServers(ZBInstituteOfTechnologyServer);
|
||||
|
||||
var SummitUniversityServer = new Server({
|
||||
ip:createRandomIp(), hostname:"summit-uni", organizationName:"Summit University Network", maxRam:32,
|
||||
requiredHackingSkill:getRandomInt(425, 475), moneyAvailable:getRandomInt(200e6, 350e6),
|
||||
hackDifficulty:getRandomInt(45, 65), serverGrowth:getRandomInt(40, 60), numOpenPortsRequired:3
|
||||
});
|
||||
SummitUniversityServer.messages.push("secret-societies.lit");
|
||||
SummitUniversityServer.messages.push("the-failed-frontier.lit");
|
||||
SummitUniversityServer.messages.push("synthetic-muscles.lit");
|
||||
AddToAllServers(SummitUniversityServer);
|
||||
|
||||
var SysCoreSecuritiesServer = new Server({
|
||||
ip:createRandomIp(), hostname:"syscore", organizationName:"SysCore Securities",
|
||||
requiredHackingSkill:getRandomInt(550, 650), moneyAvailable:getRandomInt(400e6, 600e6),
|
||||
hackDifficulty:getRandomInt(60, 80), serverGrowth:getRandomInt(60, 70), numOpenPortsRequired:4
|
||||
});
|
||||
AddToAllServers(SysCoreSecuritiesServer);
|
||||
|
||||
var CatalystVenturesServer = new Server({
|
||||
ip:createRandomIp(), hostname:"catalyst", organizationName:"Catalyst Ventures",
|
||||
requiredHackingSkill:getRandomInt(400, 450), moneyAvailable:getRandomInt(300e6, 550e6),
|
||||
hackDifficulty:getRandomInt(60, 70), serverGrowth:getRandomInt(25, 55), numOpenPortsRequired:3,
|
||||
});
|
||||
CatalystVenturesServer.messages.push("tensions-in-tech-race.lit");
|
||||
AddToAllServers(CatalystVenturesServer);
|
||||
|
||||
var TheHubServer = new Server({
|
||||
ip:createRandomIp(), hostname:"the-hub", organizationName:"The Hub",
|
||||
requiredHackingSkill:getRandomInt(275, 325), moneyAvailable:getRandomInt(150e6, 200e6),
|
||||
hackDifficulty:getRandomInt(35, 45), serverGrowth:getRandomInt(45, 55), numOpenPortsRequired:2
|
||||
});
|
||||
AddToAllServers(TheHubServer);
|
||||
|
||||
var CompuTekServer = new Server({
|
||||
ip:createRandomIp(), hostname:"comptek", organizationName:"CompuTek",
|
||||
requiredHackingSkill:getRandomInt(300, 400), moneyAvailable:getRandomInt(220e6, 250e6),
|
||||
hackDifficulty:getRandomInt(55, 65), serverGrowth:getRandomInt(45, 65), numOpenPortsRequired:3
|
||||
});
|
||||
CompuTekServer.messages.push("man-and-machine.lit");
|
||||
AddToAllServers(CompuTekServer);
|
||||
|
||||
var NetLinkTechnologiesServer = new Server({
|
||||
ip:createRandomIp(), hostname:"netlink", organizationName:"NetLink Technologies", maxRam:64,
|
||||
requiredHackingSkill:getRandomInt(375, 425), moneyAvailable:275e6,
|
||||
hackDifficulty:getRandomInt(60, 80), serverGrowth:getRandomInt(45, 75), numOpenPortsRequired:3
|
||||
});
|
||||
NetLinkTechnologiesServer.messages.push("simulated-reality.lit");
|
||||
AddToAllServers(NetLinkTechnologiesServer);
|
||||
|
||||
var JohnsonOrthopedicsServer = new Server({
|
||||
ip:createRandomIp(), hostname:"johnson-ortho", organizationName:"Johnson Orthopedics",
|
||||
requiredHackingSkill:getRandomInt(250, 300), moneyAvailable:getRandomInt(70e6, 85e6),
|
||||
hackDifficulty:getRandomInt(35, 65), serverGrowth:getRandomInt(35, 65), numOpenPortsRequired:2
|
||||
});
|
||||
AddToAllServers(JohnsonOrthopedicsServer);
|
||||
|
||||
//"Low level" targets
|
||||
var FoodNStuffServer = new Server({
|
||||
ip:createRandomIp(), hostname:"foodnstuff", organizationName:"Food N Stuff Supermarket", maxRam:16,
|
||||
requiredHackingSkill:1, moneyAvailable:2e6,
|
||||
hackDifficulty:10, serverGrowth:5, numOpenPortsRequired:0
|
||||
});
|
||||
FoodNStuffServer.messages.push("sector-12-crime.lit");
|
||||
AddToAllServers(FoodNStuffServer);
|
||||
|
||||
var SigmaCosmeticsServer = new Server({
|
||||
ip:createRandomIp(), hostname:"sigma-cosmetics", organizationName:"Sigma Cosmetics", maxRam:16,
|
||||
requiredHackingSkill:5, moneyAvailable:2.3e6,
|
||||
hackDifficulty:10, serverGrowth:10, numOpenPortsRequired:0
|
||||
});
|
||||
AddToAllServers(SigmaCosmeticsServer);
|
||||
|
||||
var JoesGunsServer = new Server({
|
||||
ip:createRandomIp(), hostname:"joesguns", organizationName:"Joe's Guns", maxRam:16,
|
||||
requiredHackingSkill:10, moneyAvailable:2.5e6,
|
||||
hackDifficulty:15, serverGrowth:20, numOpenPortsRequired:0
|
||||
});
|
||||
AddToAllServers(JoesGunsServer);
|
||||
|
||||
var Zer0NightclubServer = new Server({
|
||||
ip:createRandomIp(), hostname:"zer0", organizationName:"ZER0 Nightclub", maxRam:32,
|
||||
requiredHackingSkill:75, moneyAvailable:7.5e6,
|
||||
hackDifficulty:25, serverGrowth:40, numOpenPortsRequired:1
|
||||
});
|
||||
AddToAllServers(Zer0NightclubServer);
|
||||
|
||||
var NectarNightclubServer = new Server({
|
||||
ip:createRandomIp(), hostname:"nectar-net", organizationName:"Nectar Nightclub Network", maxRam:16,
|
||||
requiredHackingSkill:20, moneyAvailable:2.75e6,
|
||||
hackDifficulty:20, serverGrowth:25, numOpenPortsRequired:0
|
||||
});
|
||||
AddToAllServers(NectarNightclubServer);
|
||||
|
||||
var NeoNightclubServer = new Server({
|
||||
ip:createRandomIp(), hostname:"neo-net", organizationName:"Neo Nightclub Network", maxRam:32,
|
||||
requiredHackingSkill:50, moneyAvailable:5e6,
|
||||
hackDifficulty:25, serverGrowth:25, numOpenPortsRequired:1
|
||||
});
|
||||
NeoNightclubServer.messages.push("the-hidden-world.lit");
|
||||
AddToAllServers(NeoNightclubServer);
|
||||
|
||||
var SilverHelixServer = new Server({
|
||||
ip:createRandomIp(), hostname:"silver-helix", organizationName:"Silver Helix", maxRam:64,
|
||||
requiredHackingSkill:150, moneyAvailable:45e6,
|
||||
hackDifficulty:30, serverGrowth:30, numOpenPortsRequired:2
|
||||
});
|
||||
SilverHelixServer.messages.push("new-triads.lit");
|
||||
AddToAllServers(SilverHelixServer);
|
||||
|
||||
var HongFangTeaHouseServer = new Server({
|
||||
ip:createRandomIp(), hostname:"hong-fang-tea", organizationName:"HongFang Teahouse", maxRam:16,
|
||||
requiredHackingSkill:30, moneyAvailable:3e6,
|
||||
hackDifficulty:15, serverGrowth:20, numOpenPortsRequired:0
|
||||
});
|
||||
HongFangTeaHouseServer.messages.push("brighter-than-the-sun.lit");
|
||||
AddToAllServers(HongFangTeaHouseServer);
|
||||
|
||||
var HaraKiriSushiBarServer = new Server({
|
||||
ip:createRandomIp(), hostname:"harakiri-sushi", organizationName:"HaraKiri Sushi Bar Network",maxRam:16,
|
||||
requiredHackingSkill:40, moneyAvailable:4e6,
|
||||
hackDifficulty:15, serverGrowth:40, numOpenPortsRequired:0
|
||||
});
|
||||
AddToAllServers(HaraKiriSushiBarServer);
|
||||
|
||||
var PhantasyServer = new Server({
|
||||
ip:createRandomIp(), hostname:"phantasy", organizationName:"Phantasy Club", maxRam:32,
|
||||
requiredHackingSkill:100, moneyAvailable:24e6,
|
||||
hackDifficulty:20, serverGrowth:35, numOpenPortsRequired:2
|
||||
});
|
||||
AddToAllServers(PhantasyServer);
|
||||
|
||||
var MaxHardwareServer = new Server({
|
||||
ip:createRandomIp(), hostname:"max-hardware", organizationName:"Max Hardware Store", maxRam:32,
|
||||
requiredHackingSkill:80, moneyAvailable:10e6,
|
||||
hackDifficulty:15, serverGrowth:30, numOpenPortsRequired:1,
|
||||
});
|
||||
AddToAllServers(MaxHardwareServer);
|
||||
|
||||
var OmegaSoftwareServer = new Server({
|
||||
ip:createRandomIp(), hostname:"omega-net", organizationName:"Omega Software", maxRam:32,
|
||||
requiredHackingSkill:getRandomInt(180, 220), moneyAvailable:getRandomInt(60e6, 70e6),
|
||||
hackDifficulty:getRandomInt(25, 35), serverGrowth:getRandomInt(30, 40), numOpenPortsRequired:2
|
||||
});
|
||||
OmegaSoftwareServer.messages.push("the-new-god.lit");
|
||||
AddToAllServers(OmegaSoftwareServer);
|
||||
|
||||
//Gyms
|
||||
var CrushFitnessGymServer = new Server({
|
||||
ip:createRandomIp(), hostname:"crush-fitness", organizationName:"Crush Fitness",
|
||||
requiredHackingSkill:getRandomInt(225, 275), moneyAvailable:getRandomInt(40e6, 60e6),
|
||||
hackDifficulty:getRandomInt(35, 45), serverGrowth:getRandomInt(27, 33), numOpenPortsRequired:2
|
||||
});
|
||||
AddToAllServers(CrushFitnessGymServer);
|
||||
|
||||
var IronGymServer = new Server({
|
||||
ip:createRandomIp(), hostname:"iron-gym", organizationName:"Iron Gym Network", maxRam:32,
|
||||
requiredHackingSkill:100, moneyAvailable:20e6,
|
||||
hackDifficulty:30, serverGrowth:20, numOpenPortsRequired:1
|
||||
});
|
||||
AddToAllServers(IronGymServer);
|
||||
|
||||
var MilleniumFitnessGymServer = new Server({
|
||||
ip:createRandomIp(), hostname:"millenium-fitness", organizationName:"Millenium Fitness Network",
|
||||
requiredHackingSkill:getRandomInt(475, 525), moneyAvailable:250e6,
|
||||
hackDifficulty:getRandomInt(45, 55), serverGrowth:getRandomInt(25, 45), numOpenPortsRequired:3,
|
||||
});
|
||||
AddToAllServers(MilleniumFitnessGymServer);
|
||||
|
||||
var PowerhouseGymServer = new Server({
|
||||
ip:createRandomIp(), hostname:"powerhouse-fitness", organizationName:"Powerhouse Fitness",
|
||||
requiredHackingSkill:getRandomInt(950, 1100), moneyAvailable:900e6,
|
||||
hackDifficulty:getRandomInt(55, 65), serverGrowth:getRandomInt(50, 60), numOpenPortsRequired:5,
|
||||
});
|
||||
AddToAllServers(PowerhouseGymServer);
|
||||
|
||||
var SnapFitnessGymServer = new Server({
|
||||
ip:createRandomIp(), hostname:"snap-fitness", organizationName:"Snap Fitness",
|
||||
requiredHackingSkill:getRandomInt(675, 800), moneyAvailable:450e6,
|
||||
hackDifficulty:getRandomInt(40, 60), serverGrowth:getRandomInt(40, 60), numOpenPortsRequired:4
|
||||
});
|
||||
AddToAllServers(SnapFitnessGymServer);
|
||||
|
||||
//Faction servers, cannot hack money from these
|
||||
var BitRunnersServer = new Server({
|
||||
ip:createRandomIp(), hostname:"run4theh111z", organizationName:"The Runners", maxRam:128,
|
||||
requiredHackingSkill:getRandomInt(505, 550), moneyAvailable:0,
|
||||
hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:4
|
||||
});
|
||||
BitRunnersServer.messages.push("simulated-reality.lit");
|
||||
BitRunnersServer.messages.push("the-new-god.lit");
|
||||
AddToAllServers(BitRunnersServer);
|
||||
SpecialServerIps.addIp(SpecialServerNames.BitRunnersServer, BitRunnersServer.ip);
|
||||
|
||||
var TheBlackHandServer = new Server({
|
||||
ip:createRandomIp(), hostname:"I.I.I.I", organizationName:"I.I.I.I", maxRam:64,
|
||||
requiredHackingSkill:getRandomInt(340, 365), moneyAvailable:0,
|
||||
hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:3,
|
||||
});
|
||||
TheBlackHandServer.messages.push("democracy-is-dead.lit");
|
||||
AddToAllServers(TheBlackHandServer);
|
||||
SpecialServerIps.addIp(SpecialServerNames.TheBlackHandServer, TheBlackHandServer.ip);
|
||||
|
||||
var NiteSecServer = new Server({
|
||||
ip:createRandomIp(), hostname:"avmnite-02h", organizationName:"NiteSec", maxRam:32,
|
||||
requiredHackingSkill:getRandomInt(202, 220), moneyAvailable:0,
|
||||
hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:2
|
||||
});
|
||||
NiteSecServer.messages.push("democracy-is-dead.lit");
|
||||
AddToAllServers(NiteSecServer);
|
||||
SpecialServerIps.addIp(SpecialServerNames.NiteSecServer, NiteSecServer.ip);
|
||||
|
||||
var DarkArmyServer = new Server({
|
||||
ip:createRandomIp(), hostname:".", organizationName:".", maxRam:16,
|
||||
requiredHackingSkill:getRandomInt(505, 550), moneyAvailable:0,
|
||||
hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:4
|
||||
});
|
||||
AddToAllServers(DarkArmyServer);
|
||||
SpecialServerIps.addIp(SpecialServerNames.TheDarkArmyServer, DarkArmyServer.ip);
|
||||
|
||||
var CyberSecServer = new Server({
|
||||
ip:createRandomIp(), hostname:"CSEC", organizationName:"CyberSec", maxRam:8,
|
||||
requiredHackingSkill:getRandomInt(51, 60), moneyAvailable:0,
|
||||
hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:1
|
||||
});
|
||||
CyberSecServer.messages.push("democracy-is-dead.lit");
|
||||
AddToAllServers(CyberSecServer);
|
||||
SpecialServerIps.addIp(SpecialServerNames.CyberSecServer, CyberSecServer.ip);
|
||||
|
||||
var DaedalusServer = new Server({
|
||||
ip:createRandomIp(), hostname:"The-Cave", organizationName:"Helios",
|
||||
requiredHackingSkill:925, moneyAvailable:0,
|
||||
hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:5
|
||||
});
|
||||
DaedalusServer.messages.push("alpha-omega.lit");
|
||||
AddToAllServers(DaedalusServer);
|
||||
SpecialServerIps.addIp(SpecialServerNames.DaedalusServer, DaedalusServer.ip);
|
||||
|
||||
//Super special Servers
|
||||
var WorldDaemon = new Server({
|
||||
ip:createRandomIp(), hostname:SpecialServerNames.WorldDaemon, organizationName:SpecialServerNames.WorldDaemon,
|
||||
requiredHackingSkill:3000, moneyAvailable:0,
|
||||
hackDifficulty:0, serverGrowth:0, numOpenPortsRequired:5
|
||||
});
|
||||
AddToAllServers(WorldDaemon);
|
||||
SpecialServerIps.addIp(SpecialServerNames.WorldDaemon, WorldDaemon.ip);
|
||||
|
||||
/* Create a randomized network for all the foreign servers */
|
||||
//Groupings for creating a randomized network
|
||||
var NetworkGroup1 = [IronGymServer, FoodNStuffServer, SigmaCosmeticsServer, JoesGunsServer, HongFangTeaHouseServer, HaraKiriSushiBarServer];
|
||||
var NetworkGroup2 = [MaxHardwareServer, NectarNightclubServer, Zer0NightclubServer, CyberSecServer];
|
||||
var NetworkGroup3 = [OmegaSoftwareServer, PhantasyServer, SilverHelixServer, NeoNightclubServer];
|
||||
var NetworkGroup4 = [CrushFitnessGymServer, NetLinkTechnologiesServer, CompuTekServer, TheHubServer, JohnsonOrthopedicsServer, NiteSecServer];
|
||||
var NetworkGroup5 = [CatalystVenturesServer, SysCoreSecuritiesServer, SummitUniversityServer, ZBInstituteOfTechnologyServer, RothmanUniversityServer, TheBlackHandServer];
|
||||
var NetworkGroup6 = [LexoCorpServer, RhoConstructionServer, AlphaEnterprisesServer, AevumPoliceServer, MilleniumFitnessGymServer];
|
||||
var NetworkGroup7 = [GlobalPharmaceuticalsServer, AeroCorpServer, GalacticCyberSystemsServer, SnapFitnessGymServer];
|
||||
var NetworkGroup8 = [DeltaOneServer, UnitaLifeGroupServer, OmniaCybersystemsServer];
|
||||
var NetworkGroup9 = [ZeusMedicalServer, SolarisSpaceSystemsServer, UniversalEnergyServer, IcarusMicrosystemsServer, DefCommServer];
|
||||
var NetworkGroup10 = [NovaMedicalServer, ZBDefenseServer, TaiYangDigitalServer, InfoCommServer];
|
||||
var NetworkGroup11 = [AppliedEnergeticsServer, MicrodyneTechnologiesServer, TitanLabsServer, BitRunnersServer];
|
||||
var NetworkGroup12 = [VitaLifeServer, HeliosLabsServer, StormTechnologiesServer, FulcrumTechnologiesServer];
|
||||
var NetworkGroup13 = [KuaiGongInternationalServer, FourSigmaServer, OmniTekIncorporatedServer, DarkArmyServer];
|
||||
var NetworkGroup14 = [PowerhouseGymServer, ClarkeIncorporatedServer, NWOServer, BladeIndustriesServer, BachmanAndAssociatesServer];
|
||||
var NetworkGroup15 = [FulcrumSecretTechnologiesServer, MegaCorpServer, ECorpServer, DaedalusServer];
|
||||
|
||||
for (var i = 0; i < NetworkGroup2.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup1[Math.floor(Math.random() * NetworkGroup1.length)];
|
||||
NetworkGroup2[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup2[i].ip);
|
||||
const networkLayers = [];
|
||||
for (let i = 0; i < 15; i++) {
|
||||
networkLayers.push([]);
|
||||
}
|
||||
|
||||
for (var i = 0; i < NetworkGroup3.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup2[Math.floor(Math.random() * NetworkGroup2.length)];
|
||||
NetworkGroup3[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup3[i].ip);
|
||||
// Essentially any property that is of type 'number | IMinMaxRange'
|
||||
const propertiesToPatternMatch = [
|
||||
"hackDifficulty",
|
||||
"moneyAvailable",
|
||||
"requiredHackingSkill",
|
||||
"serverGrowth"
|
||||
];
|
||||
|
||||
const toNumber = (value) => {
|
||||
switch (typeof value) {
|
||||
case 'number':
|
||||
return value;
|
||||
case 'object':
|
||||
return getRandomInt(value.min, value.max);
|
||||
default:
|
||||
throw Error(`Do not know how to convert the type '${typeof value}' to a number`);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < NetworkGroup4.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup3[Math.floor(Math.random() * NetworkGroup3.length)];
|
||||
NetworkGroup4[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup4[i].ip);
|
||||
for (const metadata of serverMetadata) {
|
||||
const serverParams = {
|
||||
hostname: metadata.hostname,
|
||||
ip: createRandomIp(),
|
||||
numOpenPortsRequired: metadata.numOpenPortsRequired,
|
||||
organizationName: metadata.organizationName
|
||||
};
|
||||
|
||||
if (metadata.maxRamExponent !== undefined) {
|
||||
serverParams.maxRam = Math.pow(2, toNumber(metadata.maxRamExponent));
|
||||
}
|
||||
|
||||
for (var i = 0; i < NetworkGroup5.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup4[Math.floor(Math.random() * NetworkGroup4.length)];
|
||||
NetworkGroup5[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup5[i].ip);
|
||||
for (const prop of propertiesToPatternMatch) {
|
||||
if (metadata[prop] !== undefined) {
|
||||
serverParams[prop] = toNumber(metadata[prop]);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < NetworkGroup6.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup5[Math.floor(Math.random() * NetworkGroup5.length)];
|
||||
NetworkGroup6[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup6[i].ip);
|
||||
const server = new Server(serverParams);
|
||||
for (const filename of (metadata.literature || [])) {
|
||||
server.messages.push(filename);
|
||||
}
|
||||
|
||||
for (var i = 0; i < NetworkGroup7.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup6[Math.floor(Math.random() * NetworkGroup6.length)];
|
||||
NetworkGroup7[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup7[i].ip);
|
||||
if (metadata.specialName !== undefined) {
|
||||
SpecialServerIps.addIp(metadata.specialName, server.ip);
|
||||
}
|
||||
|
||||
for (var i = 0; i < NetworkGroup8.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup7[Math.floor(Math.random() * NetworkGroup7.length)];
|
||||
NetworkGroup8[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup8[i].ip);
|
||||
AddToAllServers(server);
|
||||
if (metadata.networkLayer !== undefined) {
|
||||
networkLayers[toNumber(metadata.networkLayer) - 1].push(server);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < NetworkGroup9.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup8[Math.floor(Math.random() * NetworkGroup8.length)];
|
||||
NetworkGroup9[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup9[i].ip);
|
||||
}
|
||||
/* Create a randomized network for all the foreign servers */
|
||||
const linkComputers = (server1, server2) => {
|
||||
server1.serversOnNetwork.push(server2.ip);
|
||||
server2.serversOnNetwork.push(server1.ip);
|
||||
};
|
||||
|
||||
for (var i = 0; i < NetworkGroup10.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup9[Math.floor(Math.random() * NetworkGroup9.length)];
|
||||
NetworkGroup10[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup10[i].ip);
|
||||
}
|
||||
const getRandomArrayItem = (arr) => arr[Math.floor(Math.random() * arr.length)];
|
||||
|
||||
for (var i = 0; i < NetworkGroup11.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup10[Math.floor(Math.random() * NetworkGroup10.length)];
|
||||
NetworkGroup11[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup11[i].ip);
|
||||
}
|
||||
|
||||
for (var i = 0; i < NetworkGroup12.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup11[Math.floor(Math.random() * NetworkGroup11.length)];
|
||||
NetworkGroup12[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup12[i].ip);
|
||||
}
|
||||
|
||||
for (var i = 0; i < NetworkGroup13.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup12[Math.floor(Math.random() * NetworkGroup12.length)];
|
||||
NetworkGroup13[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup13[i].ip);
|
||||
}
|
||||
|
||||
for (var i = 0; i < NetworkGroup14.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup13[Math.floor(Math.random() * NetworkGroup13.length)];
|
||||
NetworkGroup14[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup14[i].ip);
|
||||
}
|
||||
|
||||
for (var i = 0; i < NetworkGroup15.length; i++) {
|
||||
var randomServerFromPrevGroup = NetworkGroup14[Math.floor(Math.random() * NetworkGroup14.length)];
|
||||
NetworkGroup15[i].serversOnNetwork.push(randomServerFromPrevGroup.ip);
|
||||
randomServerFromPrevGroup.serversOnNetwork.push(NetworkGroup15[i].ip);
|
||||
const linkNetworkLayers = (network1, selectServer) => {
|
||||
for (const server of network1) {
|
||||
linkComputers(server, selectServer());
|
||||
}
|
||||
};
|
||||
|
||||
// Connect the first tier of servers to the player's home computer
|
||||
for (var i = 0; i < NetworkGroup1.length; i++) {
|
||||
Player.getHomeComputer().serversOnNetwork.push(NetworkGroup1[i].ip);
|
||||
NetworkGroup1[i].serversOnNetwork.push(Player.homeComputer);
|
||||
linkNetworkLayers(networkLayers[0], () => Player.getHomeComputer());
|
||||
for (let i = 1; i < networkLayers.length; i++) {
|
||||
linkNetworkLayers(networkLayers[i], () => getRandomArrayItem(networkLayers[i - 1]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,11 @@ interface IDefaultSettings {
|
||||
*/
|
||||
DisableHotkeys: boolean;
|
||||
|
||||
/**
|
||||
* Locale used for display numbers
|
||||
*/
|
||||
Locale: string;
|
||||
|
||||
/**
|
||||
* Limit the number of log entries for each script being executed on each server.
|
||||
*/
|
||||
@ -39,6 +44,11 @@ interface IDefaultSettings {
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
@ -48,11 +58,6 @@ interface IDefaultSettings {
|
||||
* Whether the user should be asked to confirm travelling between cities.
|
||||
*/
|
||||
SuppressTravelConfirmation: boolean;
|
||||
|
||||
/**
|
||||
* Whether to show a popup message when player is hospitalized from taking too much damage
|
||||
*/
|
||||
SuppressHospitalizationPopup: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,13 +96,14 @@ const defaultSettings: IDefaultSettings = {
|
||||
AutosaveInterval: 60,
|
||||
CodeInstructionRunTime: 50,
|
||||
DisableHotkeys: false,
|
||||
Locale: "en",
|
||||
MaxLogCapacity: 50,
|
||||
MaxPortCapacity: 50,
|
||||
SuppressBuyAugmentationConfirmation: false,
|
||||
SuppressFactionInvites: false,
|
||||
SuppressHospitalizationPopup: false,
|
||||
SuppressMessages: false,
|
||||
SuppressTravelConfirmation: false,
|
||||
SuppressHospitalizationPopup: false,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -110,13 +116,14 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
||||
DisableHotkeys: defaultSettings.DisableHotkeys,
|
||||
EditorKeybinding: "ace",
|
||||
EditorTheme: "Monokai",
|
||||
Locale: "en",
|
||||
MaxLogCapacity: defaultSettings.MaxLogCapacity,
|
||||
MaxPortCapacity: defaultSettings.MaxPortCapacity,
|
||||
SuppressBuyAugmentationConfirmation: defaultSettings.SuppressBuyAugmentationConfirmation,
|
||||
SuppressFactionInvites: defaultSettings.SuppressFactionInvites,
|
||||
SuppressHospitalizationPopup: defaultSettings.SuppressHospitalizationPopup,
|
||||
SuppressMessages: defaultSettings.SuppressMessages,
|
||||
SuppressTravelConfirmation: defaultSettings.SuppressTravelConfirmation,
|
||||
SuppressHospitalizationPopup: defaultSettings.SuppressHospitalizationPopup,
|
||||
ThemeBackgroundColor: "#000000",
|
||||
ThemeFontColor: "#66ff33",
|
||||
ThemeHighlightColor: "#ffffff",
|
||||
|
98
src/Stock.ts
Normal file
98
src/Stock.ts
Normal file
@ -0,0 +1,98 @@
|
||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
||||
|
||||
/**
|
||||
* Represents the valuation of a company in the World Stock Exchange.
|
||||
*/
|
||||
export class Stock {
|
||||
/**
|
||||
* Initializes a Stock from a JSON save state
|
||||
*/
|
||||
static fromJSON(value: any): Stock {
|
||||
return Generic_fromJSON(Stock, value.data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bear or bull (more likely to go up or down, based on otlkMag)
|
||||
*/
|
||||
b: boolean;
|
||||
|
||||
/**
|
||||
* Maximum volatility
|
||||
*/
|
||||
readonly mv: number;
|
||||
|
||||
/**
|
||||
* Name of the company that the stock is for
|
||||
*/
|
||||
readonly name: string;
|
||||
|
||||
/**
|
||||
* Outlook magnitude. Represents the stock's forecast and likelihood
|
||||
* of increasing/decreasing (based on whether its in bear or bull mode)
|
||||
*/
|
||||
otlkMag: number;
|
||||
|
||||
/**
|
||||
* Average price of stocks that the player owns in the LONG position
|
||||
*/
|
||||
playerAvgPx: number;
|
||||
|
||||
/**
|
||||
* Average price of stocks that the player owns in the SHORT position
|
||||
*/
|
||||
playerAvgShortPx: number;
|
||||
|
||||
/**
|
||||
* Number of shares the player owns in the LONG position
|
||||
*/
|
||||
playerShares: number;
|
||||
|
||||
/**
|
||||
* Number of shares the player owns in the SHORT position
|
||||
*/
|
||||
playerShortShares: number;
|
||||
|
||||
/**
|
||||
* The HTML element that displays the stock's info in the UI
|
||||
*/
|
||||
posTxtEl: HTMLElement | null;
|
||||
|
||||
/**
|
||||
* Stock's share price
|
||||
*/
|
||||
price: number;
|
||||
|
||||
/**
|
||||
* The stock's ticker symbol
|
||||
*/
|
||||
readonly symbol: string;
|
||||
|
||||
constructor(name: string = "",
|
||||
symbol: string = "",
|
||||
mv: number = 1,
|
||||
b: boolean = true,
|
||||
otlkMag: number = 0,
|
||||
initPrice: number = 10e3) {
|
||||
this.name = name;
|
||||
this.symbol = symbol;
|
||||
this.price = initPrice;
|
||||
this.playerShares = 0;
|
||||
this.playerAvgPx = 0;
|
||||
this.playerShortShares = 0;
|
||||
this.playerAvgShortPx = 0;
|
||||
this.mv = mv;
|
||||
this.b = b;
|
||||
this.otlkMag = otlkMag;
|
||||
|
||||
this.posTxtEl = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the Stock to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
return Generic_toJSON("Stock", this);
|
||||
}
|
||||
}
|
||||
|
||||
Reviver.constructors.Stock = Stock;
|
@ -3,13 +3,14 @@ import {Locations} from "./Locations";
|
||||
import {hasWallStreetSF, wallStreetSFLvl} from "./NetscriptFunctions";
|
||||
import {WorkerScript} from "./NetscriptWorker";
|
||||
import {Player} from "./Player";
|
||||
import {Stock} from "./Stock";
|
||||
|
||||
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 {numeralWrapper} from "./ui/numeralFormat";
|
||||
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
|
||||
import {getRandomInt} from "../utils/helpers/getRandomInt";
|
||||
import {KEY} from "../utils/helpers/keyCodes";
|
||||
@ -24,32 +25,6 @@ import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
|
||||
|
||||
let StockPriceCap = 1e9; //Put a limit on how high a price can go
|
||||
|
||||
function Stock(name, symbol, mv, b, otlkMag, initPrice=10000) {
|
||||
this.symbol = symbol;
|
||||
this.name = name;
|
||||
this.price = initPrice;
|
||||
|
||||
this.playerShares = 0;
|
||||
this.playerAvgPx = 0;
|
||||
this.playerShortShares = 0;
|
||||
this.playerAvgShortPx = 0;
|
||||
this.mv = mv;
|
||||
this.b = b;
|
||||
this.otlkMag = otlkMag;
|
||||
|
||||
this.posTxtEl = null;
|
||||
}
|
||||
|
||||
Stock.prototype.toJSON = function() {
|
||||
return Generic_toJSON("Stock", this);
|
||||
}
|
||||
|
||||
Stock.fromJSON = function(value) {
|
||||
return Generic_fromJSON(Stock, value.data);
|
||||
}
|
||||
|
||||
Reviver.constructors.Stock = Stock;
|
||||
|
||||
var OrderTypes = {
|
||||
LimitBuy: "Limit Buy Order",
|
||||
LimitSell: "Limit Sell Order",
|
||||
@ -112,7 +87,7 @@ function cancelOrder(params, workerScript=null) {
|
||||
//Order properties are passed in. Need to look for the order
|
||||
var stockOrders = StockMarket["Orders"][params.stock.symbol];
|
||||
var orderTxt = params.stock.symbol + " - " + params.shares + " @ " +
|
||||
numeral(params.price).format('$0.000a');
|
||||
numeralWrapper.format(params.price, '$0.000a');
|
||||
for (var i = 0; i < stockOrders.length; ++i) {
|
||||
var order = stockOrders[i];
|
||||
if (params.shares === order.shares &&
|
||||
@ -253,135 +228,135 @@ function initStockMarket() {
|
||||
}
|
||||
|
||||
var ecorp = Locations.AevumECorp;
|
||||
var ecorpStk = new Stock(ecorp, StockSymbols[ecorp], 0.45, true, 19, getRandomInt(20000, 25000));
|
||||
var ecorpStk = new Stock(ecorp, StockSymbols[ecorp], getRandomInt(40, 50)/100, true, 19, getRandomInt(17e3, 28e3));
|
||||
StockMarket[ecorp] = ecorpStk;
|
||||
|
||||
var megacorp = Locations.Sector12MegaCorp;
|
||||
var megacorpStk = new Stock(megacorp, StockSymbols[megacorp], 0.45, true, 19, getRandomInt(25000, 33000));
|
||||
var megacorpStk = new Stock(megacorp, StockSymbols[megacorp], getRandomInt(40,50)/100, true, 19, getRandomInt(24e3, 34e3));
|
||||
StockMarket[megacorp] = megacorpStk;
|
||||
|
||||
var blade = Locations.Sector12BladeIndustries;
|
||||
var bladeStk = new Stock(blade, StockSymbols[blade], 0.75, true, 13, getRandomInt(15000, 22000));
|
||||
var bladeStk = new Stock(blade, StockSymbols[blade], getRandomInt(70, 80)/100, true, 13, getRandomInt(12e3, 25e3));
|
||||
StockMarket[blade] = bladeStk;
|
||||
|
||||
var clarke = Locations.AevumClarkeIncorporated;
|
||||
var clarkeStk = new Stock(clarke, StockSymbols[clarke], 0.7, true, 12, getRandomInt(15000, 20000));
|
||||
var clarkeStk = new Stock(clarke, StockSymbols[clarke], getRandomInt(65, 75)/100, true, 12, getRandomInt(10e3, 25e3));
|
||||
StockMarket[clarke] = clarkeStk;
|
||||
|
||||
var omnitek = Locations.VolhavenOmniTekIncorporated;
|
||||
var omnitekStk = new Stock(omnitek, StockSymbols[omnitek], 0.65, true, 12, getRandomInt(35000, 40000));
|
||||
var omnitekStk = new Stock(omnitek, StockSymbols[omnitek], getRandomInt(60, 70)/100, true, 12, getRandomInt(32e3, 43e3));
|
||||
StockMarket[omnitek] = omnitekStk;
|
||||
|
||||
var foursigma = Locations.Sector12FourSigma;
|
||||
var foursigmaStk = new Stock(foursigma, StockSymbols[foursigma], 1.05, true, 17, getRandomInt(60000, 70000));
|
||||
var foursigmaStk = new Stock(foursigma, StockSymbols[foursigma], getRandomInt(100, 110)/100, true, 17, getRandomInt(50e3, 80e3));
|
||||
StockMarket[foursigma] = foursigmaStk;
|
||||
|
||||
var kuaigong = Locations.ChongqingKuaiGongInternational;
|
||||
var kuaigongStk = new Stock(kuaigong, StockSymbols[kuaigong], 0.8, true, 10, getRandomInt(20000, 24000));
|
||||
var kuaigongStk = new Stock(kuaigong, StockSymbols[kuaigong], getRandomInt(75, 85)/100, true, 10, getRandomInt(16e3, 28e3));
|
||||
StockMarket[kuaigong] = kuaigongStk;
|
||||
|
||||
var fulcrum = Locations.AevumFulcrumTechnologies;
|
||||
var fulcrumStk = new Stock(fulcrum, StockSymbols[fulcrum], 1.25, true, 16, getRandomInt(30000, 35000));
|
||||
var fulcrumStk = new Stock(fulcrum, StockSymbols[fulcrum], getRandomInt(120, 130)/100, true, 16, getRandomInt(29e3, 36e3));
|
||||
StockMarket[fulcrum] = fulcrumStk;
|
||||
|
||||
var storm = Locations.IshimaStormTechnologies;
|
||||
var stormStk = new Stock(storm, StockSymbols[storm], 0.85, true, 7, getRandomInt(21000, 24000));
|
||||
var stormStk = new Stock(storm, StockSymbols[storm], getRandomInt(80, 90)/100, true, 7, getRandomInt(20e3, 25e3));
|
||||
StockMarket[storm] = stormStk;
|
||||
|
||||
var defcomm = Locations.NewTokyoDefComm;
|
||||
var defcommStk = new Stock(defcomm, StockSymbols[defcomm], 0.65, true, 10, getRandomInt(10000, 15000));
|
||||
var defcommStk = new Stock(defcomm, StockSymbols[defcomm], getRandomInt(60, 70)/100, true, 10, getRandomInt(6e3, 19e3));
|
||||
StockMarket[defcomm] = defcommStk;
|
||||
|
||||
var helios = Locations.VolhavenHeliosLabs;
|
||||
var heliosStk = new Stock(helios, StockSymbols[helios], 0.6, true, 9, getRandomInt(12000, 16000));
|
||||
var heliosStk = new Stock(helios, StockSymbols[helios], getRandomInt(55, 65)/100, true, 9, getRandomInt(10e3, 18e3));
|
||||
StockMarket[helios] = heliosStk;
|
||||
|
||||
var vitalife = Locations.NewTokyoVitaLife;
|
||||
var vitalifeStk = new Stock(vitalife, StockSymbols[vitalife], 0.75, true, 7, getRandomInt(10000, 12000));
|
||||
var vitalifeStk = new Stock(vitalife, StockSymbols[vitalife], getRandomInt(70, 80)/100, true, 7, getRandomInt(8e3, 14e3));
|
||||
StockMarket[vitalife] = vitalifeStk;
|
||||
|
||||
var icarus = Locations.Sector12IcarusMicrosystems;
|
||||
var icarusStk = new Stock(icarus, StockSymbols[icarus], 0.65, true, 7.5, getRandomInt(16000, 20000));
|
||||
var icarusStk = new Stock(icarus, StockSymbols[icarus], getRandomInt(60, 70)/100, true, 7.5, getRandomInt(12e3, 24e3));
|
||||
StockMarket[icarus] = icarusStk;
|
||||
|
||||
var universalenergy = Locations.Sector12UniversalEnergy;
|
||||
var universalenergyStk = new Stock(universalenergy, StockSymbols[universalenergy], 0.55, true, 10, getRandomInt(20000, 25000));
|
||||
var universalenergyStk = new Stock(universalenergy, StockSymbols[universalenergy], getRandomInt(50, 60)/100, true, 10, getRandomInt(16e3, 29e3));
|
||||
StockMarket[universalenergy] = universalenergyStk;
|
||||
|
||||
var aerocorp = Locations.AevumAeroCorp;
|
||||
var aerocorpStk = new Stock(aerocorp, StockSymbols[aerocorp], 0.6, true, 6, getRandomInt(10000, 15000));
|
||||
var aerocorpStk = new Stock(aerocorp, StockSymbols[aerocorp], getRandomInt(55, 65)/100, true, 6, getRandomInt(8e3, 17e3));
|
||||
StockMarket[aerocorp] = aerocorpStk;
|
||||
|
||||
var omnia = Locations.VolhavenOmniaCybersystems;
|
||||
var omniaStk = new Stock(omnia, StockSymbols[omnia], 0.7, true, 4.5, getRandomInt(9000, 12000));
|
||||
var omniaStk = new Stock(omnia, StockSymbols[omnia], getRandomInt(65, 75)/100, true, 4.5, getRandomInt(6e3, 15e3));
|
||||
StockMarket[omnia] = omniaStk;
|
||||
|
||||
var solaris = Locations.ChongqingSolarisSpaceSystems;
|
||||
var solarisStk = new Stock(solaris, StockSymbols[solaris], 0.75, true, 8.5, getRandomInt(18000, 24000));
|
||||
var solarisStk = new Stock(solaris, StockSymbols[solaris], getRandomInt(70, 80)/100, true, 8.5, getRandomInt(14e3, 28e3));
|
||||
StockMarket[solaris] = solarisStk;
|
||||
|
||||
var globalpharm = Locations.NewTokyoGlobalPharmaceuticals;
|
||||
var globalpharmStk = new Stock(globalpharm, StockSymbols[globalpharm], 0.6, true, 10.5, getRandomInt(18000, 24000));
|
||||
var globalpharmStk = new Stock(globalpharm, StockSymbols[globalpharm], getRandomInt(55, 65)/100, true, 10.5, getRandomInt(12e3, 30e3));
|
||||
StockMarket[globalpharm] = globalpharmStk;
|
||||
|
||||
var nova = Locations.IshimaNovaMedical;
|
||||
var novaStk = new Stock(nova, StockSymbols[nova], 0.75, true, 5, getRandomInt(18000, 24000));
|
||||
var novaStk = new Stock(nova, StockSymbols[nova], getRandomInt(70, 80)/100, true, 5, getRandomInt(15e3, 27e3));
|
||||
StockMarket[nova] = novaStk;
|
||||
|
||||
var watchdog = Locations.AevumWatchdogSecurity;
|
||||
var watchdogStk = new Stock(watchdog, StockSymbols[watchdog], 2.5, true, 1.5, getRandomInt(5000, 7500));
|
||||
var watchdogStk = new Stock(watchdog, StockSymbols[watchdog], getRandomInt(240, 260)/100, true, 1.5, getRandomInt(4e3, 8.5e3));
|
||||
StockMarket[watchdog] = watchdogStk;
|
||||
|
||||
var lexocorp = Locations.VolhavenLexoCorp;
|
||||
var lexocorpStk = new Stock(lexocorp, StockSymbols[lexocorp], 1.25, true, 6, getRandomInt(5000, 7500));
|
||||
var lexocorpStk = new Stock(lexocorp, StockSymbols[lexocorp], getRandomInt(115, 135)/100, true, 6, getRandomInt(4.5e3, 8e3));
|
||||
StockMarket[lexocorp] = lexocorpStk;
|
||||
|
||||
var rho = Locations.AevumRhoConstruction;
|
||||
var rhoStk = new Stock(rho, StockSymbols[rho], 0.6, true, 1, getRandomInt(3000, 6000));
|
||||
var rhoStk = new Stock(rho, StockSymbols[rho], getRandomInt(50, 70)/100, true, 1, getRandomInt(2e3, 7e3));
|
||||
StockMarket[rho] = rhoStk;
|
||||
|
||||
var alpha = Locations.Sector12AlphaEnterprises;
|
||||
var alphaStk = new Stock(alpha, StockSymbols[alpha], 1.9, true, 10, getRandomInt(5000, 7500));
|
||||
var alphaStk = new Stock(alpha, StockSymbols[alpha], getRandomInt(175, 205)/100, true, 10, getRandomInt(4e3, 8.5e3));
|
||||
StockMarket[alpha] = alphaStk;
|
||||
|
||||
var syscore = Locations.VolhavenSysCoreSecurities;
|
||||
var syscoreStk = new Stock(syscore, StockSymbols[syscore], 1.6, true, 3, getRandomInt(4000, 7000))
|
||||
var syscoreStk = new Stock(syscore, StockSymbols[syscore], getRandomInt(150, 170)/100, true, 3, getRandomInt(3e3, 8e3));
|
||||
StockMarket[syscore] = syscoreStk;
|
||||
|
||||
var computek = Locations.VolhavenCompuTek;
|
||||
var computekStk = new Stock(computek, StockSymbols[computek], 0.9, true, 4, getRandomInt(2000, 5000));
|
||||
var computekStk = new Stock(computek, StockSymbols[computek], getRandomInt(80, 100)/100, true, 4, getRandomInt(1e3, 6e3));
|
||||
StockMarket[computek] = computekStk;
|
||||
|
||||
var netlink = Locations.AevumNetLinkTechnologies;
|
||||
var netlinkStk = new Stock(netlink, StockSymbols[netlink], 4.2, true, 1, getRandomInt(2000, 4000));
|
||||
var netlinkStk = new Stock(netlink, StockSymbols[netlink], getRandomInt(400, 430)/100, true, 1, getRandomInt(1e3, 5e3));
|
||||
StockMarket[netlink] = netlinkStk;
|
||||
|
||||
var omega = Locations.IshimaOmegaSoftware;
|
||||
var omegaStk = new Stock(omega, StockSymbols[omega], 1, true, 0.5, getRandomInt(3000, 6000));
|
||||
var omegaStk = new Stock(omega, StockSymbols[omega], getRandomInt(90, 110)/100, true, 0.5, getRandomInt(1e3, 8e3));
|
||||
StockMarket[omega] = omegaStk;
|
||||
|
||||
var fns = Locations.Sector12FoodNStuff;
|
||||
var fnsStk = new Stock(fns, StockSymbols[fns], 0.75, false, 1, getRandomInt(1000, 4000));
|
||||
var fnsStk = new Stock(fns, StockSymbols[fns], getRandomInt(70, 80)/100, false, 1, getRandomInt(500, 4.5e3));
|
||||
StockMarket[fns] = fnsStk;
|
||||
|
||||
var sigmacosm = "Sigma Cosmetics";
|
||||
var sigmacosmStk = new Stock(sigmacosm, StockSymbols[sigmacosm], 2.8, true, 0, getRandomInt(2000, 3000));
|
||||
var sigmacosmStk = new Stock(sigmacosm, StockSymbols[sigmacosm], getRandomInt(260, 300)/100, true, 0, getRandomInt(1.5e3, 3.5e3));
|
||||
StockMarket[sigmacosm] = sigmacosmStk;
|
||||
|
||||
var joesguns = "Joes Guns";
|
||||
var joesgunsStk = new Stock(joesguns, StockSymbols[joesguns], 3.8, true, 1, getRandomInt(500, 1000));
|
||||
var joesgunsStk = new Stock(joesguns, StockSymbols[joesguns], getRandomInt(360, 400)/100, true, 1, getRandomInt(250, 1.5e3));
|
||||
StockMarket[joesguns] = joesgunsStk;
|
||||
|
||||
var catalyst = "Catalyst Ventures";
|
||||
var catalystStk = new Stock(catalyst, StockSymbols[catalyst], 1.45, true, 13.5, getRandomInt(500, 1000));
|
||||
var catalystStk = new Stock(catalyst, StockSymbols[catalyst], getRandomInt(120, 175)/100, true, 13.5, getRandomInt(250, 1.5e3));
|
||||
StockMarket[catalyst] = catalystStk;
|
||||
|
||||
var microdyne = "Microdyne Technologies";
|
||||
var microdyneStk = new Stock(microdyne, StockSymbols[microdyne], 0.75, true, 8, getRandomInt(20000, 25000));
|
||||
var microdyneStk = new Stock(microdyne, StockSymbols[microdyne], getRandomInt(70, 80)/100, true, 8, getRandomInt(15e3, 30e3));
|
||||
StockMarket[microdyne] = microdyneStk;
|
||||
|
||||
var titanlabs = "Titan Laboratories";
|
||||
var titanlabsStk = new Stock(titanlabs, StockSymbols[titanlabs], 0.6, true, 11, getRandomInt(15000, 20000));
|
||||
var titanlabsStk = new Stock(titanlabs, StockSymbols[titanlabs], getRandomInt(50, 70)/100, true, 11, getRandomInt(12e3, 24e3));
|
||||
StockMarket[titanlabs] = titanlabsStk;
|
||||
|
||||
var orders = {};
|
||||
@ -435,7 +410,7 @@ 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 " +
|
||||
numeral(totalPrice + CONSTANTS.StockMarketCommission).format('($0.000a)') + ".");
|
||||
numeralWrapper.format(totalPrice + CONSTANTS.StockMarketCommission, '($0.000a)') + ".");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -445,9 +420,9 @@ function buyStock(stock, shares) {
|
||||
stock.playerShares += shares;
|
||||
stock.playerAvgPx = newTotal / stock.playerShares;
|
||||
updateStockPlayerPosition(stock);
|
||||
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.");
|
||||
dialogBoxCreate("Bought " + numeralWrapper.format(shares, '0,0') + " shares of " + stock.symbol + " at " +
|
||||
numeralWrapper.format(stock.price, '($0.000a)') + " per share. Paid " +
|
||||
numeralWrapper.format(CONSTANTS.StockMarketCommission, '($0.000a)') + " in commission fees.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -468,9 +443,9 @@ function sellStock(stock, shares) {
|
||||
stock.playerAvgPx = 0;
|
||||
}
|
||||
updateStockPlayerPosition(stock);
|
||||
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)') + ".");
|
||||
dialogBoxCreate("Sold " + numeralWrapper.format(shares, '0,0') + " shares of " + stock.symbol + " at " +
|
||||
numeralWrapper.format(stock.price, '($0.000a)') + " per share. After commissions, you gained " +
|
||||
"a total of " + numeralWrapper.format(gains, '($0.000a)') + ".");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -494,10 +469,10 @@ function shortStock(stock, shares, workerScript=null) {
|
||||
if (tixApi) {
|
||||
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)') + ".");
|
||||
numeralWrapper.format(totalPrice + CONSTANTS.StockMarketCommission, '($0.000a)') + ".");
|
||||
} else {
|
||||
dialogBoxCreate("You do not have enough money to purchase this short position. You need " +
|
||||
numeral(totalPrice + CONSTANTS.StockMarketCommission).format('($0.000a)') + ".");
|
||||
numeralWrapper.format(totalPrice + CONSTANTS.StockMarketCommission, '($0.000a)') + ".");
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -511,14 +486,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 " + 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.");
|
||||
workerScript.scriptRef.log("Bought a short position of " + numeralWrapper.format(shares, '0,0') + " shares of " + stock.symbol + " at " +
|
||||
numeralWrapper.format(stock.price, '($0.000a)') + " per share. Paid " +
|
||||
numeralWrapper.format(CONSTANTS.StockMarketCommission, '($0.000a)') + " in commission fees.");
|
||||
}
|
||||
} else {
|
||||
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.");
|
||||
dialogBoxCreate("Bought a short position of " + numeralWrapper.format(shares, '0,0') + " shares of " + stock.symbol + " at " +
|
||||
numeralWrapper.format(stock.price, '($0.000a)') + " per share. Paid " +
|
||||
numeralWrapper.format(CONSTANTS.StockMarketCommission, '($0.000a)') + " in commission fees.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -555,14 +530,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 " + 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)') + ".");
|
||||
workerScript.scriptRef.log("Sold your short position of " + numeralWrapper.format(shares, '0,0') + " shares of " + stock.symbol + " at " +
|
||||
numeralWrapper.format(stock.price, '($0.000a)') + " per share. After commissions, you gained " +
|
||||
"a total of " + numeralWrapper.format(origCost + profit, '($0.000a)') + ".");
|
||||
}
|
||||
} else {
|
||||
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)') + ".");
|
||||
dialogBoxCreate("Sold your short position of " + numeralWrapper.format(shares, '0,0') + " shares of " + stock.symbol + " at " +
|
||||
numeralWrapper.format(stock.price, '($0.000a)') + " per share. After commissions, you gained " +
|
||||
"a total of " + numeralWrapper.format(origCost + profit, '($0.000a)') + ".");
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -721,7 +696,7 @@ function displayStockMarketContent() {
|
||||
//Purchase WSE Account button
|
||||
var wseAccountButton = clearEventListeners("stock-market-buy-account");
|
||||
stylePurchaseButton(wseAccountButton, CONSTANTS.WSEAccountCost, Player.hasWseAccount,
|
||||
"Buy WSE Account - " + numeral(CONSTANTS.WSEAccountCost).format('($0.000a)'),
|
||||
"Buy WSE Account - " + numeralWrapper.format(CONSTANTS.WSEAccountCost, '($0.000a)'),
|
||||
"WSE Account - Purchased");
|
||||
wseAccountButton.addEventListener("click", function() {
|
||||
Player.hasWseAccount = true;
|
||||
@ -735,7 +710,7 @@ function displayStockMarketContent() {
|
||||
//Purchase TIX API Access account
|
||||
var tixApiAccessButton = clearEventListeners("stock-market-buy-tix-api");
|
||||
stylePurchaseButton(tixApiAccessButton, CONSTANTS.TIXAPICost, Player.hasTixApiAccess,
|
||||
"Buy Trade Information eXchange (TIX) API Access - " + numeral(CONSTANTS.TIXAPICost).format('($0.000a)'),
|
||||
"Buy Trade Information eXchange (TIX) API Access - " + numeralWrapper.format(CONSTANTS.TIXAPICost, '($0.000a)'),
|
||||
"TIX API Access - Purchased");
|
||||
tixApiAccessButton.addEventListener("click", function() {
|
||||
Player.hasTixApiAccess = true;
|
||||
@ -747,7 +722,7 @@ function displayStockMarketContent() {
|
||||
//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)'),
|
||||
"Buy 4S Market Data Access - " + numeralWrapper.format(CONSTANTS.MarketData4SCost, '($0.000a)'),
|
||||
"4S Market Data - Purchased");
|
||||
marketDataButton.addEventListener("click", function() {
|
||||
Player.has4SData = true;
|
||||
@ -785,7 +760,7 @@ function displayStockMarketContent() {
|
||||
//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)'),
|
||||
"Buy 4S Market Data TIX API Access - " + numeralWrapper.format(CONSTANTS.MarketDataTixApi4SCost, '($0.000a)'),
|
||||
"4S Market Data TIX API - Purchased");
|
||||
if (Player.hasTixApiAccess) {
|
||||
marketDataTixButton.addEventListener("click", function() {
|
||||
@ -848,7 +823,7 @@ function displayStockMarketContent() {
|
||||
console.log("Creating Stock Market UI");
|
||||
commissionText.innerHTML =
|
||||
"Commission Fees: Every transaction you make has a " +
|
||||
numeral(CONSTANTS.StockMarketCommission).format('($0.000a)') + " commission fee.<br><br>" +
|
||||
numeralWrapper.format(CONSTANTS.StockMarketCommission, '($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!";
|
||||
@ -1045,7 +1020,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 + " - " + numeral(stock.price).format('($0.000a)');
|
||||
hdr.innerHTML = stock.name + " - " + stock.symbol + " - " + numeralWrapper.format(stock.price, '($0.000a)');
|
||||
|
||||
//Div for entire panel
|
||||
var stockDiv = document.createElement("div");
|
||||
@ -1322,9 +1297,9 @@ function updateStockTicker(stock, increase) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
let hdrText = stock.name + " (" + stock.symbol + ") - " + numeral(stock.price).format('($0.000a)');
|
||||
let hdrText = stock.name + " (" + stock.symbol + ") - " + numeralWrapper.format(stock.price, '($0.000a)');
|
||||
if (Player.has4SData) {
|
||||
hdrText += " - Volatility: " + numeral(stock.mv).format('0,0.00') + "%" +
|
||||
hdrText += " - Volatility: " + numeralWrapper.format(stock.mv, '0,0.00') + "%" +
|
||||
" - Price Forecast: ";
|
||||
if (stock.b) {
|
||||
hdrText += "+".repeat(Math.floor(stock.otlkMag/10) + 1);
|
||||
@ -1388,21 +1363,21 @@ 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: " + 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') +
|
||||
" (" + numeral(percentageGains).format('0.00%') + ")<br><br>";
|
||||
"<br>Shares: " + numeralWrapper.format(stock.playerShares, '0,0') +
|
||||
"<br>Average Price: " + numeralWrapper.format(stock.playerAvgPx, '$0.000a') +
|
||||
" (Total Cost: " + numeralWrapper.format(totalCost, '$0.000a') + ")" +
|
||||
"<br>Profit: " + numeralWrapper.format(gains, '$0.000a') +
|
||||
" (" + numeralWrapper.format(percentageGains, '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: " + 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') +
|
||||
" (" + numeral(shortPercentageGains).format('0.00%') + ")" +
|
||||
"<br>Shares: " + numeralWrapper.format(stock.playerShortShares, '0,0') +
|
||||
"<br>Average Price: " + numeralWrapper.format(stock.playerAvgShortPx, '$0.000a') +
|
||||
" (Total Cost: " + numeralWrapper.format(shortTotalCost, '$0.000a') + ")" +
|
||||
"<br>Profit: " + numeralWrapper.format(shortGains, '$0.000a') +
|
||||
" (" + numeralWrapper.format(shortPercentageGains, '0.00%') + ")" +
|
||||
"<br><br><h1 class='stock-market-position-text'>Orders: </h1>";
|
||||
}
|
||||
|
||||
@ -1465,7 +1440,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 + " @ " + numeral(order.price).format('($0.000a)');
|
||||
order.shares + " @ " + numeralWrapper.format(order.price, '($0.000a)');
|
||||
|
||||
var cancelButton = document.createElement("span");
|
||||
cancelButton.classList.add("stock-market-order-cancel-btn");
|
||||
|
302
src/Terminal.js
302
src/Terminal.js
@ -10,17 +10,18 @@ import {executeDarkwebTerminalCommand,
|
||||
import {Engine} from "./engine";
|
||||
import {FconfSettings, parseFconfSettings,
|
||||
createFconf} from "./Fconf";
|
||||
import {calculateHackingChance,
|
||||
calculateHackingExpGain,
|
||||
calculatePercentMoneyHacked,
|
||||
calculateHackingTime,
|
||||
calculateGrowTime,
|
||||
calculateWeakenTime} from "./Hacking";
|
||||
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,
|
||||
scriptCalculateGrowTime,
|
||||
scriptCalculateWeakenTime} from "./NetscriptEvaluator";
|
||||
import {killWorkerScript, addWorkerScript} from "./NetscriptWorker";
|
||||
import numeral from "numeral/min/numeral.min";
|
||||
import {Player} from "./Player";
|
||||
import {hackWorldDaemon} from "./RedPill";
|
||||
import {findRunningScript, RunningScript,
|
||||
@ -32,10 +33,10 @@ import {Settings} from "./Settings";
|
||||
import {SpecialServerIps,
|
||||
SpecialServerNames} from "./SpecialServerIps";
|
||||
import {TextFile, getTextFile} from "./TextFile";
|
||||
|
||||
import {containsAllStrings, longestCommonStart,
|
||||
formatNumber} from "../utils/StringHelperFunctions";
|
||||
import {containsAllStrings,
|
||||
longestCommonStart} from "../utils/StringHelperFunctions";
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
import {KEY} from "../utils/helpers/keyCodes";
|
||||
import {addOffset} from "../utils/helpers/addOffset";
|
||||
import {isString} from "../utils/helpers/isString";
|
||||
@ -48,6 +49,7 @@ import {yesNoBoxCreate,
|
||||
import {post, hackProgressBarPost,
|
||||
hackProgressPost} from "./ui/postToTerminal";
|
||||
|
||||
import autosize from 'autosize';
|
||||
import * as JSZip from 'jszip';
|
||||
import * as FileSaver from 'file-saver';
|
||||
|
||||
@ -64,12 +66,12 @@ $(document).keydown(function(event) {
|
||||
|
||||
if (event.keyCode === KEY.ENTER) {
|
||||
event.preventDefault(); //Prevent newline from being entered in Script Editor
|
||||
var command = $('input[class=terminal-input]').val();
|
||||
var command = terminalInput.value;
|
||||
post(
|
||||
"[" +
|
||||
"<span class='prompt'>[" +
|
||||
(FconfSettings.ENABLE_TIMESTAMPS ? getTimestamp() + " " : "") +
|
||||
Player.getCurrentServer().hostname +
|
||||
" ~]> " + command
|
||||
" ~]></span> " + command
|
||||
);
|
||||
|
||||
if (command.length > 0) {
|
||||
@ -515,14 +517,25 @@ let Terminal = {
|
||||
//Flags to determine whether the player is currently running a hack or an analyze
|
||||
hackFlag: false,
|
||||
analyzeFlag: false,
|
||||
actionStarted: false,
|
||||
actionTime: 0,
|
||||
|
||||
commandHistory: [],
|
||||
commandHistoryIndex: 0,
|
||||
|
||||
resetTerminalInput: function() {
|
||||
if (FconfSettings.WRAP_INPUT) {
|
||||
document.getElementById("terminal-input-td").innerHTML =
|
||||
"<div id='terminal-input-header'>[" + Player.getCurrentServer().hostname + " ~]" + "$ </div>" +
|
||||
"<div id='terminal-input-header' class='prompt'>[" + Player.getCurrentServer().hostname + " ~]" + "$ </div>" +
|
||||
'<textarea type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1"/>';
|
||||
|
||||
//Auto re-size the line element as it wraps
|
||||
autosize(document.getElementById("terminal-input-text-box"));
|
||||
} else {
|
||||
document.getElementById("terminal-input-td").innerHTML =
|
||||
"<div id='terminal-input-header' class='prompt'>[" + Player.getCurrentServer().hostname + " ~]" + "$ </div>" +
|
||||
'<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1"/>';
|
||||
}
|
||||
var hdr = document.getElementById("terminal-input-header");
|
||||
hdr.style.display = "inline";
|
||||
},
|
||||
@ -620,6 +633,32 @@ let Terminal = {
|
||||
}
|
||||
},
|
||||
|
||||
startHack: function() {
|
||||
Terminal.hackFlag = true;
|
||||
|
||||
//Hacking through Terminal should be faster than hacking through a script
|
||||
Terminal.actionTime = calculateHackingTime(Player.getCurrentServer()) / 4;
|
||||
Terminal.startAction();
|
||||
},
|
||||
|
||||
startAnalyze: function() {
|
||||
Terminal.analyzeFlag = true;
|
||||
Terminal.actionTime = 1;
|
||||
post("Analyzing system...");
|
||||
Terminal.startAction();
|
||||
},
|
||||
|
||||
startAction: function() {
|
||||
Terminal.actionStarted = true;
|
||||
|
||||
hackProgressPost("Time left:");
|
||||
hackProgressBarPost("[");
|
||||
|
||||
//Disable terminal
|
||||
document.getElementById("terminal-input-td").innerHTML = '<input type="text" class="terminal-input"/>';
|
||||
$('input[class=terminal-input]').prop('disabled', true);
|
||||
},
|
||||
|
||||
finishAction: function(cancelled = false) {
|
||||
if (Terminal.hackFlag) {
|
||||
Terminal.finishHack(cancelled);
|
||||
@ -634,10 +673,10 @@ let Terminal = {
|
||||
var server = Player.getCurrentServer();
|
||||
|
||||
//Calculate whether hack was successful
|
||||
var hackChance = Player.calculateHackingChance();
|
||||
var hackChance = calculateHackingChance(server);
|
||||
var rand = Math.random();
|
||||
console.log("Hack success chance: " + hackChance + ", rand: " + rand);
|
||||
var expGainedOnSuccess = Player.calculateExpGain();
|
||||
var expGainedOnSuccess = calculateHackingExpGain(server);
|
||||
var expGainedOnFailure = (expGainedOnSuccess / 4);
|
||||
if (rand < hackChance) { //Success!
|
||||
if (SpecialServerIps[SpecialServerNames.WorldDaemon] &&
|
||||
@ -649,7 +688,7 @@ let Terminal = {
|
||||
return;
|
||||
}
|
||||
server.manuallyHacked = true;
|
||||
var moneyGained = Player.calculatePercentMoneyHacked();
|
||||
var moneyGained = calculatePercentMoneyHacked(server);
|
||||
moneyGained = Math.floor(server.moneyAvailable * moneyGained);
|
||||
|
||||
if (moneyGained <= 0) {moneyGained = 0;} //Safety check
|
||||
@ -661,11 +700,11 @@ let Terminal = {
|
||||
|
||||
server.fortify(CONSTANTS.ServerFortifyAmount);
|
||||
|
||||
post("Hack successful! Gained $" + formatNumber(moneyGained, 2) + " and " + formatNumber(expGainedOnSuccess, 4) + " hacking EXP");
|
||||
post("Hack successful! Gained " + numeralWrapper.format(moneyGained, '($0,0.00)') + " and " + numeralWrapper.format(expGainedOnSuccess, '0.0000') + " hacking EXP");
|
||||
} else { //Failure
|
||||
//Player only gains 25% exp for failure? TODO Can change this later to balance
|
||||
Player.gainHackingExp(expGainedOnFailure)
|
||||
post("Failed to hack " + server.hostname + ". Gained " + formatNumber(expGainedOnFailure, 4) + " hacking EXP");
|
||||
post("Failed to hack " + server.hostname + ". Gained " + numeralWrapper.format(expGainedOnFailure, '0.0000') + " hacking EXP");
|
||||
}
|
||||
}
|
||||
|
||||
@ -680,43 +719,45 @@ let Terminal = {
|
||||
|
||||
finishAnalyze: function(cancelled = false) {
|
||||
if (cancelled == false) {
|
||||
post(Player.getCurrentServer().hostname + ": ");
|
||||
post("Organization name: " + Player.getCurrentServer().organizationName);
|
||||
let currServ = Player.getCurrentServer();
|
||||
post(currServ.hostname + ": ");
|
||||
post("Organization name: " + currServ.organizationName);
|
||||
var rootAccess = "";
|
||||
if (Player.getCurrentServer().hasAdminRights) {rootAccess = "YES";}
|
||||
if (currServ.hasAdminRights) {rootAccess = "YES";}
|
||||
else {rootAccess = "NO";}
|
||||
post("Root Access: " + rootAccess);
|
||||
post("Required hacking skill: " + Player.getCurrentServer().requiredHackingSkill);
|
||||
post("Estimated server security level: " + formatNumber(addOffset(Player.getCurrentServer().hackDifficulty, 5), 3));
|
||||
post("Estimated chance to hack: " + formatNumber(addOffset(Player.calculateHackingChance() * 100, 5), 2) + "%");
|
||||
post("Estimated time to hack: " + formatNumber(addOffset(Player.calculateHackingTime(), 5), 3) + " seconds");
|
||||
post("Estimated total money available on server: $" + formatNumber(addOffset(Player.getCurrentServer().moneyAvailable, 5), 2));
|
||||
post("Required number of open ports for NUKE: " + Player.getCurrentServer().numOpenPortsRequired);
|
||||
if (Player.getCurrentServer().sshPortOpen) {
|
||||
post("Required hacking skill: " + currServ.requiredHackingSkill);
|
||||
post("Server security level: " + numeralWrapper.format(currServ.hackDifficulty, '0.000a'));
|
||||
post("Chance to hack: " + numeralWrapper.format(calculateHackingChance(currServ) * 100, '0.00%'));
|
||||
post("Time to hack: " + numeralWrapper.format(calculateHackingTime(currServ), '0.000') + " seconds");
|
||||
post("Total money available on server: $" + numeralWrapper.format(currServ.moneyAvailable, '$0,0.00'));
|
||||
post("Required number of open ports for NUKE: " + currServ.numOpenPortsRequired);
|
||||
|
||||
if (currServ.sshPortOpen) {
|
||||
post("SSH port: Open")
|
||||
} else {
|
||||
post("SSH port: Closed")
|
||||
}
|
||||
|
||||
if (Player.getCurrentServer().ftpPortOpen) {
|
||||
if (currServ.ftpPortOpen) {
|
||||
post("FTP port: Open")
|
||||
} else {
|
||||
post("FTP port: Closed")
|
||||
}
|
||||
|
||||
if (Player.getCurrentServer().smtpPortOpen) {
|
||||
if (currServ.smtpPortOpen) {
|
||||
post("SMTP port: Open")
|
||||
} else {
|
||||
post("SMTP port: Closed")
|
||||
}
|
||||
|
||||
if (Player.getCurrentServer().httpPortOpen) {
|
||||
if (currServ.httpPortOpen) {
|
||||
post("HTTP port: Open")
|
||||
} else {
|
||||
post("HTTP port: Closed")
|
||||
}
|
||||
|
||||
if (Player.getCurrentServer().sqlPortOpen) {
|
||||
if (currServ.sqlPortOpen) {
|
||||
post("SQL port: Open")
|
||||
} else {
|
||||
post("SQL port: Closed")
|
||||
@ -731,6 +772,55 @@ let Terminal = {
|
||||
$('input[class=terminal-input]').prop('disabled', false);
|
||||
},
|
||||
|
||||
writeToScriptFile : function(server, fn, code) {
|
||||
var ret = {success: false, overwritten: false};
|
||||
if (!isScriptFilename(fn) || !(server instanceof Server)) { return ret; }
|
||||
|
||||
//Check if the script already exists, and overwrite it if it does
|
||||
for (let i = 0; i < server.scripts.length; ++i) {
|
||||
if (fn === server.scripts[i].filename) {
|
||||
let script = server.scripts[i];
|
||||
script.code = code;
|
||||
script.updateRamUsage();
|
||||
script.module = "";
|
||||
ret.overwritten = true;
|
||||
ret.success = true;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
//Otherwise, create a new script
|
||||
var newScript = new Script();
|
||||
newScript.filename = fn;
|
||||
newScript.code = code;
|
||||
newScript.updateRamUsage();
|
||||
newScript.server = server.ip;
|
||||
server.scripts.push(newScript);
|
||||
ret.success = true;
|
||||
return ret;
|
||||
},
|
||||
|
||||
writeToTextFile : function(server, fn, txt) {
|
||||
var ret = {success: false, overwritten: false};
|
||||
if (!fn.endsWith("txt") || !(server instanceof Server)) { return ret; }
|
||||
|
||||
//Check if the text file already exists, and overwrite if it does
|
||||
for (let i = 0; i < server.textFiles.length; ++i) {
|
||||
if (server.textFiles[i].fn === fn) {
|
||||
ret.overwritten = true;
|
||||
server.textFiles[i].text = txt;
|
||||
ret.success = true;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
//Otherwise create a new text file
|
||||
var newFile = new TextFile(fn, txt);
|
||||
server.textFiles.push(newFile);
|
||||
ret.success = true;
|
||||
return ret;
|
||||
},
|
||||
|
||||
executeCommand : function(command) {
|
||||
command = command.trim();
|
||||
//Replace all extra whitespace in command with a single space
|
||||
@ -762,11 +852,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);
|
||||
@ -816,17 +906,7 @@ let Terminal = {
|
||||
if (commandArray.length != 1) {
|
||||
post("Incorrect usage of analyze command. Usage: analyze"); return;
|
||||
}
|
||||
//Analyze the current server for information
|
||||
Terminal.analyzeFlag = true;
|
||||
post("Analyzing system...");
|
||||
hackProgressPost("Time left:");
|
||||
hackProgressBarPost("[");
|
||||
Player.analyze();
|
||||
|
||||
//Disable terminal
|
||||
//Terminal.resetTerminalInput();
|
||||
document.getElementById("terminal-input-td").innerHTML = '<input type="text" class="terminal-input"/>';
|
||||
$('input[class=terminal-input]').prop('disabled', true);
|
||||
Terminal.startAnalyze();
|
||||
iTutorialNextStep();
|
||||
} else {
|
||||
post("Bad command. Please follow the tutorial");
|
||||
@ -842,15 +922,7 @@ let Terminal = {
|
||||
break;
|
||||
case iTutorialSteps.TerminalManualHack:
|
||||
if (commandArray.length == 1 && commandArray[0] == "hack") {
|
||||
Terminal.hackFlag = true;
|
||||
hackProgressPost("Time left:");
|
||||
hackProgressBarPost("[");
|
||||
Player.hack();
|
||||
|
||||
//Disable terminal
|
||||
//Terminal.resetTerminalInput();
|
||||
document.getElementById("terminal-input-td").innerHTML = '<input type="text" class="terminal-input"/>';
|
||||
$('input[class=terminal-input]').prop('disabled', true);
|
||||
Terminal.startHack();
|
||||
iTutorialNextStep();
|
||||
} else {post("Bad command. Please follow the tutorial");}
|
||||
break;
|
||||
@ -921,17 +993,7 @@ let Terminal = {
|
||||
if (commandArray.length != 1) {
|
||||
post("Incorrect usage of analyze command. Usage: analyze"); return;
|
||||
}
|
||||
//Analyze the current server for information
|
||||
Terminal.analyzeFlag = true;
|
||||
post("Analyzing system...");
|
||||
hackProgressPost("Time left:");
|
||||
hackProgressBarPost("[");
|
||||
Player.analyze();
|
||||
|
||||
//Disable terminal
|
||||
//Terminal.resetTerminalInput();
|
||||
document.getElementById("terminal-input-td").innerHTML = '<input type="text" class="terminal-input"/>';
|
||||
$('input[class=terminal-input]').prop('disabled', true);
|
||||
Terminal.startAnalyze();
|
||||
break;
|
||||
case "buy":
|
||||
if (SpecialServerIps.hasOwnProperty("Darkweb Server")) {
|
||||
@ -1084,15 +1146,7 @@ let Terminal = {
|
||||
} else if (Player.getCurrentServer().requiredHackingSkill > Player.hacking_skill) {
|
||||
post("Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill");
|
||||
} else {
|
||||
Terminal.hackFlag = true;
|
||||
hackProgressPost("Time left:");
|
||||
hackProgressBarPost("[");
|
||||
Player.hack();
|
||||
|
||||
//Disable terminal
|
||||
//Terminal.resetTerminalInput();
|
||||
document.getElementById("terminal-input-td").innerHTML = '<input type="text" class="terminal-input"/>';
|
||||
$('input[class=terminal-input]').prop('disabled', true);
|
||||
Terminal.startHack();
|
||||
}
|
||||
break;
|
||||
case "help":
|
||||
@ -1191,7 +1245,7 @@ let Terminal = {
|
||||
var scriptBaseRamUsage = currServ.scripts[i].ramUsage;
|
||||
var ramUsage = scriptBaseRamUsage * numThreads;
|
||||
|
||||
post("This script requires " + formatNumber(ramUsage, 2) + "GB of RAM to run for " + numThreads + " thread(s)");
|
||||
post("This script requires " + numeralWrapper.format(ramUsage, '0.00') + " GB of RAM to run for " + numThreads + " thread(s)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1346,6 +1400,7 @@ let Terminal = {
|
||||
post("Incorrect usage of scan-analyze command. usage: scan-analyze [depth]");
|
||||
}
|
||||
break;
|
||||
/* eslint-disable no-case-declarations */
|
||||
case "scp":
|
||||
if (commandArray.length != 2) {
|
||||
post("Incorrect usage of scp command. Usage: scp [file] [destination hostname/ip]");
|
||||
@ -1389,8 +1444,7 @@ let Terminal = {
|
||||
}
|
||||
}
|
||||
destServer.messages.push(scriptname);
|
||||
post(scriptname + " copied over to " + destServer.hostname);
|
||||
return;
|
||||
return post(scriptname + " copied over to " + destServer.hostname);
|
||||
}
|
||||
|
||||
//Scp for txt files
|
||||
@ -1406,18 +1460,15 @@ let Terminal = {
|
||||
|
||||
if (!found) {return post("Error: no such file exists!");}
|
||||
|
||||
for (var i = 0; i < destServer.textFiles.length; ++i) {
|
||||
if (destServer.textFiles[i].fn === scriptname) {
|
||||
//Overwrite
|
||||
destServer.textFiles[i].text = txtFile.text;
|
||||
post("WARNING: " + scriptname + " already exists on " + destServer.hostname +
|
||||
"and will be overwriten");
|
||||
return post(scriptname + " copied over to " + destServer.hostname);
|
||||
let tRes = Terminal.writeToTextFile(destServer, txtFile.fn, txtFile.text);
|
||||
if (!tRes.success) {
|
||||
return post("Error: scp failed");
|
||||
}
|
||||
if (tRes.overwritten) {
|
||||
post(`WARNING: ${scriptname} already exists on ${destServer.hostname} and will be overwriten`);
|
||||
return post(`${scriptname} overwritten on ${destServer.hostname}`);
|
||||
}
|
||||
var newFile = new TextFile(txtFile.fn, txtFile.text);
|
||||
destServer.textFiles.push(newFile);
|
||||
return post(scriptname + " copied over to " + destServer.hostname);
|
||||
return post(`${scriptname} copied over to ${destServer.hostname}`);
|
||||
}
|
||||
|
||||
//Get the current script
|
||||
@ -1433,27 +1484,17 @@ let Terminal = {
|
||||
return;
|
||||
}
|
||||
|
||||
//Overwrite script if it exists
|
||||
for (var i = 0; i < destServer.scripts.length; ++i) {
|
||||
if (scriptname == destServer.scripts[i].filename) {
|
||||
post("WARNING: " + scriptname + " already exists on " + destServer.hostname + " and will be overwritten");
|
||||
var oldScript = destServer.scripts[i];
|
||||
oldScript.code = sourceScript.code;
|
||||
oldScript.ramUsage = sourceScript.ramUsage;
|
||||
oldScript.module = "";
|
||||
post(scriptname + " overwriten on " + destServer.hostname);
|
||||
return;
|
||||
let sRes = Terminal.writeToScriptFile(destServer, scriptname, sourceScript.code);
|
||||
if (!sRes.success) {
|
||||
return post(`Error: scp failed`);
|
||||
}
|
||||
if (sRes.overwritten) {
|
||||
post(`WARNING: ${scriptname} already exists on ${destServer.hostname} and will be overwritten`);
|
||||
return post(`${scriptname} overwritten on ${destServer.hostname}`);
|
||||
}
|
||||
|
||||
var newScript = new Script();
|
||||
newScript.filename = scriptname;
|
||||
newScript.code = sourceScript.code;
|
||||
newScript.ramUsage = sourceScript.ramUsage;
|
||||
newScript.destServer = ip;
|
||||
destServer.scripts.push(newScript);
|
||||
post(scriptname + " copied over to " + destServer.hostname);
|
||||
post(`${scriptname} copied over to ${destServer.hostname}`);
|
||||
break;
|
||||
/* eslint-enable no-case-declarations */
|
||||
case "sudov":
|
||||
if (commandArray.length != 1) {
|
||||
post("Incorrect number of arguments. Usage: sudov"); return;
|
||||
@ -1556,7 +1597,7 @@ let Terminal = {
|
||||
var spacesThread = Array(numSpacesThread+1).join(" ");
|
||||
|
||||
//Calculate and transform RAM usage
|
||||
ramUsage = formatNumber(script.scriptRef.ramUsage * script.threads, 2).toString() + "GB";
|
||||
ramUsage = numeralWrapper.format(script.scriptRef.ramUsage * script.threads, '0.00') + " GB";
|
||||
|
||||
var entry = [script.filename, spacesScript, script.threads, spacesThread, ramUsage];
|
||||
post(entry.join(""));
|
||||
@ -1577,6 +1618,40 @@ let Terminal = {
|
||||
}
|
||||
}
|
||||
break;
|
||||
/* eslint-disable no-case-declarations */
|
||||
case "wget":
|
||||
if (commandArray.length !== 2) {
|
||||
return post("Incorrect usage of wget command. Usage: wget [url] [target file]");
|
||||
}
|
||||
var args = commandArray[1].split(" ");
|
||||
if (args.length !== 2) {
|
||||
return post("Incorrect usage of wget command. Usage: wget [url] [target file]");
|
||||
}
|
||||
|
||||
let url = args[0];
|
||||
let target = args[1];
|
||||
if (!isScriptFilename(target) && !target.endsWith(".txt")) {
|
||||
return post(`wget failed: Invalid target file. Target file must be script or text file`);
|
||||
}
|
||||
$.get(url, function(data) {
|
||||
let res;
|
||||
if (isScriptFilename(target)) {
|
||||
res = Terminal.writeToScriptFile(s, target, data);
|
||||
} else {
|
||||
res = Terminal.writeToTextFile(s, target, data);
|
||||
}
|
||||
if (!res.success) {
|
||||
return post("wget failed");
|
||||
}
|
||||
if (res.overwritten) {
|
||||
return post(`wget successfully retrieved content and overwrote ${target}`);
|
||||
}
|
||||
return post(`wget successfully retrieved content to new file ${target}`);
|
||||
}, 'text').fail(function(e) {
|
||||
return post("wget failed: " + JSON.stringify(e));
|
||||
})
|
||||
break;
|
||||
/* eslint-enable no-case-declarations */
|
||||
default:
|
||||
post("Command not found");
|
||||
}
|
||||
@ -1769,9 +1844,9 @@ let Terminal = {
|
||||
if (commandArray.length != 1) {
|
||||
post("Incorrect usage of free command. Usage: free"); return;
|
||||
}
|
||||
post("Total: " + formatNumber(Player.getCurrentServer().maxRam, 2) + " GB");
|
||||
post("Used: " + formatNumber(Player.getCurrentServer().ramUsed, 2) + " GB");
|
||||
post("Available: " + formatNumber(Player.getCurrentServer().maxRam - Player.getCurrentServer().ramUsed, 2) + " GB");
|
||||
post("Total: " + numeralWrapper.format(Player.getCurrentServer().maxRam, '0.00') + " GB");
|
||||
post("Used: " + numeralWrapper.format(Player.getCurrentServer().ramUsed, '0.00') + " GB");
|
||||
post("Available: " + numeralWrapper.format(Player.getCurrentServer().maxRam - Player.getCurrentServer().ramUsed, '0.00') + " GB");
|
||||
},
|
||||
|
||||
//First called when the "run [program]" command is called. Checks to see if you
|
||||
@ -1892,9 +1967,9 @@ let Terminal = {
|
||||
post("Server base security level: " + targetServer.baseDifficulty);
|
||||
post("Server current security level: " + targetServer.hackDifficulty);
|
||||
post("Server growth rate: " + targetServer.serverGrowth);
|
||||
post("Netscript hack() execution time: " + formatNumber(scriptCalculateHackingTime(targetServer), 1) + "s");
|
||||
post("Netscript grow() execution time: " + formatNumber(scriptCalculateGrowTime(targetServer)/1000, 1) + "s");
|
||||
post("Netscript weaken() execution time: " + formatNumber(scriptCalculateWeakenTime(targetServer)/1000, 1) + "s");
|
||||
post("Netscript hack() execution time: " + numeralWrapper.format(scriptCalculateHackingTime(targetServer), '0.0') + "s");
|
||||
post("Netscript grow() execution time: " + numeralWrapper.format(scriptCalculateGrowTime(targetServer), '0.0') + "s");
|
||||
post("Netscript weaken() execution time: " + numeralWrapper.format(scriptCalculateWeakenTime(targetServer), '0.0') + "s");
|
||||
};
|
||||
programHandlers[Programs.AutoLink.name] = () => {
|
||||
post("This executable cannot be run.");
|
||||
@ -1920,7 +1995,7 @@ let Terminal = {
|
||||
if(!fulfilled) {
|
||||
post("Augmentations: " + Player.augmentations.length + " / 30");
|
||||
|
||||
post("Money: " + numeral(Player.money.toNumber()).format('($0.000a)') + " / " + numeral(1e11).format('($0.000a)'));
|
||||
post("Money: " + numeralWrapper.format(Player.money.toNumber(), '($0.000a)') + " / " + numeralWrapper.format(1e11, '($0.000a)'));
|
||||
post("One path below must be fulfilled...");
|
||||
post("----------HACKING PATH----------");
|
||||
post("Hacking skill: " + Player.hacking_skill + " / 2500");
|
||||
@ -2053,6 +2128,7 @@ let Terminal = {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
post("ERROR: No such script");
|
||||
}
|
||||
};
|
||||
|
1543
src/data/servers.ts
Normal file
1543
src/data/servers.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,13 +5,14 @@ import {clearEventListeners} from "../utils/uiHelpers/clearEv
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
|
||||
import {removeLoadingScreen} from "../utils/uiHelpers/removeLoadingScreen";
|
||||
import numeral from "numeral/min/numeral.min";
|
||||
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
|
||||
import {formatNumber,
|
||||
convertTimeMsToTimeElapsedString,
|
||||
replaceAt} from "../utils/StringHelperFunctions";
|
||||
import {loxBoxCreate, logBoxUpdateText,
|
||||
logBoxOpened} from "../utils/LogBox";
|
||||
|
||||
import {updateActiveScriptsItems} from "./ActiveScriptsUI";
|
||||
import {Augmentations, installAugmentations,
|
||||
initAugmentations, AugmentationNames,
|
||||
@ -150,7 +151,7 @@ $(document).keydown(function(e) {
|
||||
}
|
||||
});
|
||||
|
||||
let Engine = {
|
||||
const Engine = {
|
||||
version: "",
|
||||
Debug: true,
|
||||
overview: new CharacterOverview(),
|
||||
@ -570,7 +571,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 = "";
|
||||
@ -587,18 +588,18 @@ let Engine = {
|
||||
'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>' +
|
||||
' (' + numeralWrapper.format(Player.hacking_exp, '(0.000a)') + ' experience)<br>' +
|
||||
'Strength: ' + (Player.strength).toLocaleString() +
|
||||
" (" + numeral(Player.strength_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
' (' + numeralWrapper.format(Player.strength_exp, '(0.000a)') + ' experience)<br>' +
|
||||
'Defense: ' + (Player.defense).toLocaleString() +
|
||||
" (" + numeral(Player.defense_exp).format('(0.000a)')+ ' experience)<br>' +
|
||||
' (' + numeralWrapper.format(Player.defense_exp, '(0.000a)') + ' experience)<br>' +
|
||||
'Dexterity: ' + (Player.dexterity).toLocaleString() +
|
||||
" (" + numeral(Player.dexterity_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
' (' + numeralWrapper.format(Player.dexterity_exp, '(0.000a)') + ' experience)<br>' +
|
||||
'Agility: ' + (Player.agility).toLocaleString() +
|
||||
" (" + numeral(Player.agility_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
' (' + numeralWrapper.format(Player.agility_exp, '(0.000a)') + ' experience)<br>' +
|
||||
'Charisma: ' + (Player.charisma).toLocaleString() +
|
||||
" (" + numeral(Player.charisma_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
intText +
|
||||
' (' + numeralWrapper.format(Player.charisma_exp, '(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>' +
|
||||
@ -923,14 +924,14 @@ let Engine = {
|
||||
Player.playtimeSinceLastBitnode += time;
|
||||
|
||||
//Start Manual hack
|
||||
if (Player.startAction == true) {
|
||||
Engine._totalActionTime = Player.actionTime;
|
||||
Engine._actionTimeLeft = Player.actionTime;
|
||||
if (Terminal.actionStarted === true) {
|
||||
Engine._totalActionTime = Terminal.actionTime;
|
||||
Engine._actionTimeLeft = Terminal.actionTime;
|
||||
Engine._actionInProgress = true;
|
||||
Engine._actionProgressBarCount = 1;
|
||||
Engine._actionProgressStr = "[ ]";
|
||||
Engine._actionTimeStr = "Time left: ";
|
||||
Player.startAction = false;
|
||||
Terminal.actionStarted = false;
|
||||
}
|
||||
|
||||
//Working
|
||||
@ -1324,9 +1325,9 @@ let Engine = {
|
||||
Player.lastUpdate = Engine._lastUpdate;
|
||||
Engine.start(); //Run main game loop and Scripts loop
|
||||
removeLoadingScreen();
|
||||
dialogBoxCreate("While you were offline, your scripts generated $" +
|
||||
formatNumber(offlineProductionFromScripts, 2) + " and your Hacknet Nodes generated $" +
|
||||
formatNumber(offlineProductionFromHacknetNodes, 2));
|
||||
dialogBoxCreate("While you were offline, your scripts generated <span class='money-gold'>$" +
|
||||
formatNumber(offlineProductionFromScripts, 2) + "</span> and your Hacknet Nodes generated <span class='money-gold'>$" +
|
||||
formatNumber(offlineProductionFromHacknetNodes, 2) + "</span>");
|
||||
//Close main menu accordions for loaded game
|
||||
var visibleMenuTabs = [terminal, createScript, activeScripts, stats,
|
||||
hacknetnodes, city, tutorial, options, dev];
|
||||
|
1059
src/index.html
Normal file
1059
src/index.html
Normal file
File diff suppressed because it is too large
Load Diff
39
src/ui/numeralFormat.js
Normal file
39
src/ui/numeralFormat.js
Normal file
@ -0,0 +1,39 @@
|
||||
import numeral from "numeral";
|
||||
import 'numeral/locales/bg';
|
||||
import 'numeral/locales/cs';
|
||||
import 'numeral/locales/da-dk';
|
||||
import 'numeral/locales/de';
|
||||
import 'numeral/locales/en-au';
|
||||
import 'numeral/locales/en-gb';
|
||||
import 'numeral/locales/es';
|
||||
import 'numeral/locales/fr';
|
||||
import 'numeral/locales/hu';
|
||||
import 'numeral/locales/it';
|
||||
import 'numeral/locales/lv';
|
||||
import 'numeral/locales/no';
|
||||
import 'numeral/locales/pl';
|
||||
import 'numeral/locales/ru';
|
||||
|
||||
/* eslint-disable class-methods-use-this */
|
||||
|
||||
class NumeralFormatter {
|
||||
constructor() {
|
||||
this.defaultLocale = 'en';
|
||||
}
|
||||
|
||||
updateLocale(l) {
|
||||
if (numeral.locale(l) == null) {
|
||||
console.warn(`Invalid locale for numeral: ${l}`);
|
||||
|
||||
numeral.locale(this.defaultLocale);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
format(n, format) {
|
||||
return numeral(n).format(format);
|
||||
}
|
||||
}
|
||||
|
||||
export const numeralWrapper = new NumeralFormatter();
|
@ -1,6 +1,9 @@
|
||||
import {Engine} from "../engine";
|
||||
import {Settings} from "../Settings";
|
||||
|
||||
import {numeralWrapper} from "./NumeralFormat";
|
||||
|
||||
|
||||
function setSettingsLabels() {
|
||||
var nsExecTime = document.getElementById("settingsNSExecTimeRangeValLabel");
|
||||
var nsLogLimit = document.getElementById("settingsNSLogRangeValLabel");
|
||||
@ -12,6 +15,7 @@ function setSettingsLabels() {
|
||||
var suppressHospitalizationPopup = document.getElementById("settingsSuppressHospitalizationPopup");
|
||||
var autosaveInterval = document.getElementById("settingsAutosaveIntervalValLabel");
|
||||
var disableHotkeys = document.getElementById("settingsDisableHotkeys");
|
||||
var locale = document.getElementById("settingsLocale");
|
||||
|
||||
//Initialize values on labels
|
||||
nsExecTime.innerHTML = Settings.CodeInstructionRunTime + "ms";
|
||||
@ -24,8 +28,10 @@ function setSettingsLabels() {
|
||||
suppressHospitalizationPopup.checked = Settings.SuppressHospitalizationPopup;
|
||||
autosaveInterval.innerHTML = Settings.AutosaveInterval;
|
||||
disableHotkeys.checked = Settings.DisableHotkeys;
|
||||
locale.value = Settings.Locale;
|
||||
numeralWrapper.updateLocale(Settings.Locale); //Initialize locale
|
||||
|
||||
//Set handlers for when input changes
|
||||
//Set handlers for when input changes for sliders
|
||||
var nsExecTimeInput = document.getElementById("settingsNSExecTimeRangeVal");
|
||||
var nsLogRangeInput = document.getElementById("settingsNSLogRangeVal");
|
||||
var nsPortRangeInput = document.getElementById("settingsNSPortRangeVal");
|
||||
@ -60,6 +66,7 @@ function setSettingsLabels() {
|
||||
}
|
||||
};
|
||||
|
||||
//Set handlers for when settings change on checkboxes
|
||||
suppressMsgs.onclick = function() {
|
||||
Settings.SuppressMessages = this.checked;
|
||||
};
|
||||
@ -84,6 +91,19 @@ function setSettingsLabels() {
|
||||
Settings.DisableHotkeys = this.checked;
|
||||
}
|
||||
|
||||
//Locale selector
|
||||
locale.onchange = function() {
|
||||
if (!numeralWrapper.updateLocale(locale.value)) {
|
||||
console.warn(`Invalid locale for numeral: ${locale.value}`);
|
||||
|
||||
let defaultValue = 'en';
|
||||
Settings.Locale = defaultValue;
|
||||
locale.value = defaultValue;
|
||||
return;
|
||||
}
|
||||
Settings.Locale = locale.value;
|
||||
}
|
||||
|
||||
//Theme
|
||||
if (Settings.ThemeHighlightColor == null || Settings.ThemeFontColor == null || Settings.ThemeBackgroundColor == null) {
|
||||
console.log("ERROR: Cannot find Theme Settings");
|
||||
|
@ -48,6 +48,7 @@
|
||||
"ignore-params",
|
||||
"ignore-properties"
|
||||
],
|
||||
"no-magic-numbers": [true, -1, 0, 1, 2, 10, 100],
|
||||
"no-null-keyword": false,
|
||||
"no-unsafe-any": false,
|
||||
"object-literal-key-quotes": [
|
||||
@ -59,6 +60,7 @@
|
||||
"allow-declarations",
|
||||
"allow-named-functions"
|
||||
],
|
||||
"triple-equals": [true, "allow-null-check", "allow-undefined-check"],
|
||||
"typedef": [
|
||||
true,
|
||||
"call-signatures",
|
||||
|
@ -57,9 +57,9 @@ function infiltrationBoxCreate(inst) {
|
||||
CONSTANTS.InfiltrationRepValue * BitNodeMultipliers.InfiltrationRep;
|
||||
var moneyValue = totalValue * CONSTANTS.InfiltrationMoneyValue * BitNodeMultipliers.InfiltrationMoney;
|
||||
infiltrationSetText("You can sell the classified documents and secrets " +
|
||||
"you stole from " + inst.companyName + " for $" +
|
||||
formatNumber(moneyValue, 2) + " on the black market or you can give it " +
|
||||
"to a faction to gain " + formatNumber(facValue, 3) + " reputation with " +
|
||||
"you stole from " + inst.companyName + " for <span class='money-gold'>$" +
|
||||
formatNumber(moneyValue, 2) + "</span> on the black market or you can give it " +
|
||||
"to a faction to gain <span class='light-yellow'>" + formatNumber(facValue, 3) + " reputation</span> with " +
|
||||
"that faction.");
|
||||
var selector = document.getElementById("infiltration-faction-select");
|
||||
selector.innerHTML = "";
|
||||
@ -85,7 +85,7 @@ function infiltrationBoxCreate(inst) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
Player.gainMoney(moneyValue);
|
||||
dialogBoxCreate("You sold the classified information you stole from " + inst.companyName +
|
||||
" for $" + moneyValue + " on the black market!<br><br>" +
|
||||
" for <span class='money-gold'>$" + formatNumber(moneyValue, 2) + "</span> on the black market!<br><br>" +
|
||||
"You gained:<br>" +
|
||||
formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" +
|
||||
formatNumber(inst.strExpGained, 3) + " str exp<br>" +
|
||||
@ -111,7 +111,7 @@ function infiltrationBoxCreate(inst) {
|
||||
}
|
||||
faction.playerReputation += facValue;
|
||||
dialogBoxCreate("You gave the classified information you stole from " + inst.companyName +
|
||||
" to " + facName + " and gained " + formatNumber(facValue, 3) + " reputation with the faction. <br><br>" +
|
||||
" to " + facName + " and gained <span class='light-yellow'>" + formatNumber(facValue, 3) + " reputation</span> with the faction. <br><br>" +
|
||||
"You gained:<br>" +
|
||||
formatNumber(inst.hackingExpGained, 3) + " hacking exp<br>" +
|
||||
formatNumber(inst.strExpGained, 3) + " str exp<br>" +
|
||||
|
@ -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 @@
|
||||
/**
|
||||
* Returns a MM/DD HH:MM timestamp for the current time
|
||||
*/
|
||||
export function getTimestamp() {
|
||||
const d: Date = new Date();
|
||||
// A negative slice value takes from the end of the string rather than the beginning.
|
||||
|
@ -1,6 +1,7 @@
|
||||
var path = require('path');
|
||||
var webpack = require('webpack');
|
||||
var MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
var HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
|
||||
module.exports = (env, argv) => ({
|
||||
plugins: [
|
||||
@ -16,6 +17,45 @@ module.exports = (env, argv) => ({
|
||||
jQuery: "jquery",
|
||||
$: "jquery"
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
title: "Bitburner" + (argv.mode === 'development' ? ' - development' : ""),
|
||||
template: "src/index.html",
|
||||
favicon: "favicon.ico",
|
||||
googleAnalytics: {
|
||||
trackingId: 'UA-100157497-1'
|
||||
},
|
||||
meta: {},
|
||||
minify: argv.mode === 'development' ? false : {
|
||||
collapseBooleanAttributes: true,
|
||||
collapseInlineTagWhitespace: false,
|
||||
collapseWhitespace: false,
|
||||
conservativeCollapse: false,
|
||||
html5: true,
|
||||
includeAutoGeneratedTags: false,
|
||||
keepClosingSlash: true,
|
||||
minifyCSS: false,
|
||||
minifyJS: false,
|
||||
minifyURLs: false,
|
||||
preserveLineBreaks: false,
|
||||
preventAttributesEscaping: false,
|
||||
processConditionalComments: false,
|
||||
quoteCharacter: "\"",
|
||||
removeAttributeQuotes: false,
|
||||
removeComments: false,
|
||||
removeEmptyAttributes: false,
|
||||
removeEmptyElements: false,
|
||||
removeOptionalTags: false,
|
||||
removeScriptTypeAttributes: false,
|
||||
removeStyleLinkTypeAttributes: false,
|
||||
removeTagWhitespace: false,
|
||||
sortAttributes: false,
|
||||
sortClassName: false,
|
||||
useShortDoctype: false
|
||||
},
|
||||
excludeChunks: [
|
||||
"tests/tests"
|
||||
]
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "[name].css",
|
||||
chunkFilename: "[id].css"
|
||||
|
Loading…
Reference in New Issue
Block a user