mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-16 14:28:36 +02:00
Compare commits
122 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7417fb6ef8 | ||
|
|
98a04e4932 | ||
|
|
8d33c5b571 | ||
|
|
221b81d802 | ||
|
|
df89cc5002 | ||
|
|
3b6b37f8a6 | ||
|
|
cf2acb8844 | ||
|
|
2e9b028174 | ||
|
|
c56645c794 | ||
|
|
3ce2e83dd8 | ||
|
|
3241945452 | ||
|
|
fb857642e8 | ||
|
|
cc0e6548ff | ||
|
|
6c3c569a44 | ||
|
|
b5ebbba43d | ||
|
|
bf9b837e31 | ||
|
|
7f88ade30e | ||
|
|
36499ae9f2 | ||
|
|
4b95ba9ed1 | ||
|
|
804e4c23e3 | ||
|
|
b6b6d8e9fa | ||
|
|
c566c838be | ||
|
|
51d9274626 | ||
|
|
c8b478c208 | ||
|
|
18a3f061b4 | ||
|
|
3f8b9e4a32 | ||
|
|
e63ad76701 | ||
|
|
cb66ad9628 | ||
|
|
971bfbada4 | ||
|
|
b646c15521 | ||
|
|
92f7d12c0e | ||
|
|
7172f4e527 | ||
|
|
5592a8bc96 | ||
|
|
c4cb7daac5 | ||
|
|
75bc34208c | ||
|
|
83fc4d81b2 | ||
|
|
3cf18f100a | ||
|
|
8fbb072596 | ||
|
|
ea7f0752cb | ||
|
|
0f8f572519 | ||
|
|
52b6defebd | ||
|
|
34d749809a | ||
|
|
2ce4af2498 | ||
|
|
227bcf146e | ||
|
|
139a5add20 | ||
|
|
3a61a5cfa1 | ||
|
|
29c5c9b99d | ||
|
|
49dc9b7cb0 | ||
|
|
856d02a129 | ||
|
|
9542879f86 | ||
|
|
1034f7cac5 | ||
|
|
9a7061503a | ||
|
|
449605d330 | ||
|
|
3556d6a1ff | ||
|
|
4858dabe99 | ||
|
|
d54439be8b | ||
|
|
31e703d126 | ||
|
|
2754a644ae | ||
|
|
b7170e4ded | ||
|
|
4df6638444 | ||
|
|
d4c72474cb | ||
|
|
1c0201534b | ||
|
|
fa14bb5362 | ||
|
|
f88c585714 | ||
|
|
8514104560 | ||
|
|
5b7743967e | ||
|
|
2e9fe02023 | ||
|
|
b8bdf0da82 | ||
|
|
1f639c6a3a | ||
|
|
035cdb8b0d | ||
|
|
2ba7ac82eb | ||
|
|
96db360a36 | ||
|
|
77571543f2 | ||
|
|
3f312d0ce6 | ||
|
|
4bdb34bc7b | ||
|
|
f7fd3c859f | ||
|
|
dfd7aa2d2e | ||
|
|
0df437ef35 | ||
|
|
bedd615c0e | ||
|
|
1f4f6bd179 | ||
|
|
d75ff5d95b | ||
|
|
c3bc6a0c28 | ||
|
|
066ccf343a | ||
|
|
c973663dc2 | ||
|
|
08136524be | ||
|
|
261abdea78 | ||
|
|
b132efbded | ||
|
|
f8f4299ed5 | ||
|
|
9f715020df | ||
|
|
060e0f7bfc | ||
|
|
8df7f8de4b | ||
|
|
e6c5ff7ab7 | ||
|
|
a28fe7ab9f | ||
|
|
c3ecc189fd | ||
|
|
b4057fcb26 | ||
|
|
8470f307ac | ||
|
|
8eecb1539c | ||
|
|
5230837dad | ||
|
|
da97c1b4b9 | ||
|
|
963cb0039d | ||
|
|
3e10f5de6d | ||
|
|
6969a8f92c | ||
|
|
2198bfd962 | ||
|
|
d4d5202cbd | ||
|
|
cde2c9e615 | ||
|
|
59018d9902 | ||
|
|
c378400a10 | ||
|
|
58062bf421 | ||
|
|
f3dbdad011 | ||
|
|
d9ee715bc7 | ||
|
|
bd13234f06 | ||
|
|
fa4e98d06c | ||
|
|
cca32923e3 | ||
|
|
a22bfb5015 | ||
|
|
18d8b2ecd4 | ||
|
|
9879d07d7c | ||
|
|
d54e39c9c6 | ||
|
|
67d083772a | ||
|
|
e6a3794849 | ||
|
|
473f0f1447 | ||
|
|
e1b8a23f1e | ||
|
|
af3323a111 |
@@ -5,7 +5,7 @@ played at https://danielyxie.github.io/bitburner.
|
||||
# Documentation
|
||||
The game's official documentation can be found on [Read The
|
||||
Docs](http://bitburner.readthedocs.io/). Please note that this is still a
|
||||
work-in-progress and is in its early stages.
|
||||
work-in-progress.
|
||||
|
||||
The documentation is created using [Sphinx](http://www.sphinx-doc.org).
|
||||
|
||||
@@ -14,11 +14,6 @@ files](/doc/source) and then making a pull request with your contributions.
|
||||
For further guidance, please refer to the "As A Documentor" section of
|
||||
[CONTRIBUTING](CONTRIBUTING.md).
|
||||
|
||||
# Wiki
|
||||
The game's wiki can be found on [Wikia](http://bitburner.wikia.com/). Please
|
||||
note that the wiki is in the process of being deprecated. Eventually all of
|
||||
the wiki content will be moved into the Read The Docs documentation.
|
||||
|
||||
# Contribution
|
||||
There are many ways to contribute to the game. It can be as simple as fixing
|
||||
a typo, correcting a bug, or improving the UI. For guidance on doing so,
|
||||
@@ -32,4 +27,4 @@ publish, and distribute your contributions to the project. A formal
|
||||
Contributor's License Agreement will be drawn up in the future.
|
||||
|
||||
If you would like to make significant contributions to the project as a
|
||||
collaborator, please reach out to @danielyxie to help coordinate the effort.
|
||||
collaborator, please reach out to @danielyxie to help coordinate the effort.
|
||||
|
||||
@@ -51,6 +51,44 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Checkbox for (de)selecting autoleveling */
|
||||
.bbcheckbox {
|
||||
position: relative;
|
||||
display: inline;
|
||||
label {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: black;
|
||||
border-width: 1px;
|
||||
border-color: white;
|
||||
border-style: solid;
|
||||
&:after {
|
||||
content: '';
|
||||
width: 9px;
|
||||
height: 5px;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
border: 3px solid white;
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
opacity: 0;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
input[type=checkbox] {
|
||||
margin: 3px;
|
||||
visibility: hidden;
|
||||
&:checked + label:after {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Bladeburner Console */
|
||||
.bladeburner-console-div {
|
||||
display: inline-block;
|
||||
|
||||
@@ -38,6 +38,7 @@ button {
|
||||
}
|
||||
|
||||
.a-link-button-inactive,
|
||||
.std-button-disabled,
|
||||
.std-button:disabled {
|
||||
text-decoration: none;
|
||||
background-color: #333;
|
||||
@@ -47,6 +48,11 @@ button {
|
||||
border: 1px solid #333;
|
||||
cursor: default;
|
||||
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
|
||||
&:hover {
|
||||
.tooltiptext,
|
||||
.tooltiptexthigh,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@import "theme";
|
||||
|
||||
/**
|
||||
* Styling for the Character Overview Panel (top-right)
|
||||
* Styling for the Character Overview Panel (top-right panel)
|
||||
*/
|
||||
|
||||
#character-overview-wrapper {
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
|
||||
#cmpy-mgmt-container p,
|
||||
#cmpy-mgmt-container a,
|
||||
#cmpy-mgmt-container div {
|
||||
#cmpy-mgmt-container div,
|
||||
#cmpy-mgmt-container br {
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
}
|
||||
|
||||
@@ -56,29 +57,33 @@
|
||||
.cmpy-mgmt-industry-left-panel,
|
||||
.cmpy-mgmt-industry-right-panel {
|
||||
display: inline-block;
|
||||
width: 45%;
|
||||
height: 100%;
|
||||
top: 10px;
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
overflow: visible;
|
||||
top: 10px;
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.cmpy-mgmt-industry-overview-panel {
|
||||
border: 1px solid #fff;
|
||||
color: var(--my-font-color);
|
||||
display: inline-block;
|
||||
padding: 3px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cmpy-mgmt-employee-panel {
|
||||
border: 1px solid #fff;
|
||||
display: block;
|
||||
padding: 3px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cmpy-mgmt-warehouse-panel {
|
||||
border: 1px solid #fff;
|
||||
display: inline-block;
|
||||
padding: 3px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -115,13 +120,18 @@
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
/* Upgrades */
|
||||
/* Corporation Upgrades */
|
||||
.cmpy-mgmt-upgrade-container {
|
||||
border: 1px solid #fff;
|
||||
width: 60%;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.cmpy-mgmt-upgrade-header {
|
||||
margin: 6px;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.cmpy-mgmt-upgrade-div {
|
||||
display: inline-block;
|
||||
border: 1px solid #fff;
|
||||
@@ -136,10 +146,20 @@
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
/* Industry Upgrades */
|
||||
.industry-purchases-and-upgrades-header {
|
||||
font-size: 14px;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
/* Advertising */
|
||||
.cmpy-mgmt-advertising-info {
|
||||
font-size: $defaultFontSize * 0.75;
|
||||
}
|
||||
|
||||
/* Research */
|
||||
#corporation-research-popup-box-content {
|
||||
overflow-x: visible !important;
|
||||
overflow-x: auto !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
36
css/dev-menu.css
Normal file
36
css/dev-menu.css
Normal file
@@ -0,0 +1,36 @@
|
||||
.add-exp-button {
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.remove-exp-button {
|
||||
margin-left:0px;
|
||||
}
|
||||
|
||||
.exp-input {
|
||||
margin-right: 0px;
|
||||
margin-left:0px;
|
||||
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.touch-right {
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.touch-left {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.touch-sides {
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
6
css/grid.min.css
vendored
Normal file
6
css/grid.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
75
css/hacknetnodes.scss
Normal file
75
css/hacknetnodes.scss
Normal file
@@ -0,0 +1,75 @@
|
||||
@import "mixins";
|
||||
@import "theme";
|
||||
|
||||
/**
|
||||
* Styling for the Hacknet Nodes UI Page
|
||||
*/
|
||||
|
||||
#hacknet-nodes-container {
|
||||
position: fixed;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.hacknet-general-info {
|
||||
margin: 10px;
|
||||
width: 70vw;
|
||||
}
|
||||
|
||||
#hacknet-nodes-container li {
|
||||
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 {
|
||||
list-style: none;
|
||||
width: 82vw;
|
||||
}
|
||||
|
||||
#hacknet-nodes-money {
|
||||
margin: 10px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#hacknet-nodes-money-multipliers-div {
|
||||
display: inline-block;
|
||||
width: 70vw;
|
||||
}
|
||||
|
||||
#hacknet-nodes-multipliers {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#hacknet-nodes-purchase-button {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.hacknet-node-container {
|
||||
display: inline-table;
|
||||
|
||||
.row {
|
||||
display: table-row;
|
||||
height: 30px;
|
||||
|
||||
p {
|
||||
display: table-cell;
|
||||
}
|
||||
}
|
||||
|
||||
.upgradable-info {
|
||||
display: inline-block;
|
||||
margin: 0 4px; /* Don't want the vertical margin/padding, just left & right */
|
||||
padding: 0 4px;
|
||||
width: $defaultFontSize * 4;
|
||||
}
|
||||
}
|
||||
@@ -138,81 +138,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Hacknet Nodes */
|
||||
#hacknet-nodes-container {
|
||||
position: fixed;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#hacknet-nodes-text,
|
||||
#hacknet-nodes-container li {
|
||||
margin: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#hacknet-nodes-container li {
|
||||
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 {
|
||||
list-style: none;
|
||||
width: 82vw;
|
||||
}
|
||||
|
||||
#hacknet-nodes-money {
|
||||
margin: 10px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#hacknet-nodes-money-multipliers-div {
|
||||
display: inline-block;
|
||||
width: 70vw;
|
||||
}
|
||||
|
||||
#hacknet-nodes-multipliers {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#hacknet-nodes-purchase-button {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.hacknet-node-container {
|
||||
display: inline-table;
|
||||
|
||||
.row {
|
||||
display: table-row;
|
||||
height: 30px;
|
||||
|
||||
p {
|
||||
display: table-cell;
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
/* World */
|
||||
#world-container {
|
||||
position: fixed;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
/* Pop-up boxes */
|
||||
.popup-box-container {
|
||||
display: none; /* Hidden by default */
|
||||
display: none; /* Initially hidden */
|
||||
position: fixed; /* Stay in place */
|
||||
z-index: 10; /* Sit on top */
|
||||
left: 0;
|
||||
|
||||
@@ -68,13 +68,14 @@
|
||||
@include boxShadow($boxShadowArgs);
|
||||
|
||||
background-color: #555;
|
||||
border: 2px solid var(--my-highlight-color);
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
float: center;
|
||||
resize: none;
|
||||
color: #fff;
|
||||
margin: 4px;
|
||||
padding: 2px;
|
||||
border: 2px solid var(--my-highlight-color);
|
||||
resize: none;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
#script-editor-status {
|
||||
|
||||
@@ -62,6 +62,9 @@ a:visited {
|
||||
.text-input {
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: white;
|
||||
}
|
||||
|
||||
/* Notification icon (for create program right now only) */
|
||||
@@ -203,7 +206,6 @@ a:visited {
|
||||
|
||||
.status-text {
|
||||
display: inline-block;
|
||||
height: 15%;
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
-webkit-animation: status-text 3s 1;
|
||||
@@ -215,10 +217,12 @@ a:visited {
|
||||
|
||||
#status-text {
|
||||
background-color: transparent;
|
||||
font-size: $defaultFontSize * 1.25;
|
||||
bottom: 0;
|
||||
color: #fff;
|
||||
display: none;
|
||||
font-size: $defaultFontSize * 1.25;
|
||||
margin-right: 14px;
|
||||
opacity: 0;
|
||||
padding: 4px;
|
||||
right: 0;
|
||||
top: 0;
|
||||
|
||||
2
dist/engine.bundle.js
vendored
2
dist/engine.bundle.js
vendored
File diff suppressed because one or more lines are too long
2710
dist/engine.css
vendored
2710
dist/engine.css
vendored
File diff suppressed because it is too large
Load Diff
152
dist/vendor.bundle.js
vendored
152
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@@ -14,6 +14,8 @@ Sleeve technology unlocks two different gameplay features:
|
||||
|
||||
Sleeve technology is unlocked in :ref:`BitNode-10 <gameplay_bitnodes>`.
|
||||
|
||||
.. _gameplay_duplicatesleeves:
|
||||
|
||||
Duplicate Sleeves
|
||||
^^^^^^^^^^^^^^^^^
|
||||
Duplicate Sleeves are MK-V Synthoids (synthetic androids) into which your consciuosness
|
||||
@@ -28,6 +30,19 @@ Sleeves are their own individuals, which means they each have their own experien
|
||||
When a sleeve earns experience, it earns experience for itself, the player's
|
||||
original consciousness, as well as all of the player's other sleeves.
|
||||
|
||||
Duplicate Sleeves are **not** reset when installing Augmentations, but they are reset
|
||||
when switching BitNodes.
|
||||
|
||||
Obtaining Duplicate Sleeves
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
There are two methods of obtaining Duplicate Sleeves:
|
||||
|
||||
1. Destroy BitNode-10. Each completion give you one additional Duplicate Sleeve
|
||||
2. Purchase Duplicate Sleeves from :ref:`the faction The Covenant <gameplay_factions>`.
|
||||
This is only available in BitNodes-10 and above, and is only available after defeating
|
||||
BitNode-10 at least once. Sleeves purchased this way are **permanent** (they persist
|
||||
through BitNodes). You can purchase up to 5 Duplicate Sleeves from The Covenant.
|
||||
|
||||
Synchronization
|
||||
~~~~~~~~~~~~~~~
|
||||
Synchronization is a measure of how aligned your consciousness is with that of your
|
||||
@@ -50,15 +65,30 @@ no shock. Shock affects the amount of experience earned by the sleeve.
|
||||
Sleeve shock slowly decreases over time. You can further increase the rate at which
|
||||
it decreases by assigning sleeves to the 'Shock Recovery' task.
|
||||
|
||||
Obtaining Duplicate Sleeves
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
There are two methods of obtaining Duplicate Sleeves:
|
||||
Augmentations
|
||||
~~~~~~~~~~~~~
|
||||
You can purchase :ref:`Augmentations <gameplay_augmentations>` for your Duplicate
|
||||
Sleeves. In order to do this, the Sleeve's Shock must be at 0. Any Augmentation
|
||||
that is currently available to you through a faction is also available for your
|
||||
Duplicate Sleeves. There are a few Augmentations, such as NeuroFlux Governor and
|
||||
Bladeburner-specific ones, that cannot be purchased for a Duplicate Sleeve.
|
||||
|
||||
1. Destroy BitNode-10. Each completion give you one additional Duplicate Sleeve
|
||||
2. Purchase Duplicate Sleeves from :ref:`the faction The Covenant <gameplay_factions>`.
|
||||
This is only available in BitNodes-10 and above, and is only available after defeating
|
||||
BitNode-10 at least once. Sleeves purchased this way are permanent. You can purchase
|
||||
up to 5 Duplicate Sleeves from The Covenant.
|
||||
When you purchase an Augmentation for a Duplicate Sleeve, it is instantly installed.
|
||||
When this happens, the Sleeve's stats are instantly reset back to 0, similar to
|
||||
when you normally install Augmentations.
|
||||
|
||||
The cost of purchasing an Augmentation for a Duplicate Sleeve is **not** affected
|
||||
by how many Augmentations you have purchased for yourself, and vice versa.
|
||||
|
||||
Memory
|
||||
~~~~~~
|
||||
Sleeve memory dictates what a sleeve's synchronization will be when its reset by
|
||||
switching BitNodes. For example, if a sleeve has a memory of 10, then when you
|
||||
switch BitNodes its synchronization will initially be set to 10, rather than 1.
|
||||
|
||||
Memory can only be increased by purchasing upgrades from The Covenant.
|
||||
It is a persistent stat, meaning it never gets reset back to 1.
|
||||
The maximum possible value for a sleeve's memory is 100.
|
||||
|
||||
Re-sleeving
|
||||
^^^^^^^^^^^
|
||||
|
||||
@@ -48,6 +48,7 @@ List of all Source-Files
|
||||
| BitNode-9: Coming Soon | |
|
||||
+------------------------------------+-------------------------------------------------------------------------------------+
|
||||
| BitNode-10: Digital Carbon | * Each level of this grants a Duplicate Sleeve |
|
||||
| | * Allows the player to access the :ref:`netscript_sleeveapi` in other BitNodes |
|
||||
+------------------------------------+-------------------------------------------------------------------------------------+
|
||||
| BitNode-11: The Big Crash | * Company favor increases both the player's salary and reputation gain at that |
|
||||
| | company by 1% per favor (rather than just the reputation gain) |
|
||||
|
||||
@@ -7,6 +7,11 @@ buy and sell stocks in order to make money.
|
||||
|
||||
The WSE can be found in the 'City' tab, and is accessible in every city.
|
||||
|
||||
Automating the Stock Market
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
You can write scripts to perform automatic and algorithmic trading on the Stock Market.
|
||||
See :ref:`netscript_tixapi` for more details.
|
||||
|
||||
Positions: Long vs Short
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
When making a transaction on the stock market, there are two types of positions:
|
||||
|
||||
@@ -16,6 +16,85 @@ the terminal and enter::
|
||||
|
||||
nano .fconf
|
||||
|
||||
|
||||
.. _terminal_filesystem:
|
||||
|
||||
Filesystem (Directories)
|
||||
------------------------
|
||||
The Terminal contains a **very** basic filesystem that allows you to store and
|
||||
organize your files into different directories. Note that this is **not** a true
|
||||
filesystem implementation. Instead, it is done almost entirely using string manipulation.
|
||||
For this reason, many of the nice & useful features you'd find in a real
|
||||
filesystem do not exist.
|
||||
|
||||
Here are the Terminal commands you'll commonly use when dealing with the filesystem.
|
||||
|
||||
* :ref:`ls_terminal_command`
|
||||
* :ref:`cd_terminal_command`
|
||||
* :ref:`mv_terminal_command`
|
||||
|
||||
Directories
|
||||
^^^^^^^^^^^
|
||||
In order to create a directory, simply name a file using a full absolute Linux-style path::
|
||||
|
||||
/scripts/myScript.js
|
||||
|
||||
This will automatically create a "directory" called :code:`scripts`. This will also work
|
||||
for subdirectories::
|
||||
|
||||
/scripts/hacking/helpers/myHelperScripts.script
|
||||
|
||||
Files in the root directory do not need to begin with a forward slash::
|
||||
|
||||
thisIsAFileInTheRootDirectory.txt
|
||||
|
||||
Note that there is no way to manually create or remove directories. The creation and
|
||||
deletion of directories is automatically handled as you name/rename/delete
|
||||
files.
|
||||
|
||||
Absolute vs Relative Paths
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Many Terminal commands accept absolute both absolute and relative paths for specifying a
|
||||
file.
|
||||
|
||||
An absolute path specifies the location of the file from the root directory (/).
|
||||
Any path that begins with the forward slash is an absolute path::
|
||||
|
||||
$ nano /scripts/myScript.js
|
||||
$ cat /serverList.txt
|
||||
|
||||
A relative path specifies the location of the file relative to the current working directory.
|
||||
Any path that does **not** begin with a forward slash is a relative path. Note that the
|
||||
Linux-style dot symbols will work for relative paths::
|
||||
|
||||
. (a single dot) - represents the current directory
|
||||
.. (two dots) - represents the parent directory
|
||||
|
||||
$ cd ..
|
||||
$ nano ../scripts/myScript.js
|
||||
$ nano ../../helper.js
|
||||
|
||||
Netscript
|
||||
^^^^^^^^^
|
||||
Note that in order to reference a file, :ref:`netscript` functions require the
|
||||
**full** absolute file path. For example
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
run("/scripts/hacking/helpers.myHelperScripts.script");
|
||||
rm("/logs/myHackingLogs.txt");
|
||||
rm("thisIsAFileInTheRootDirectory.txt");
|
||||
|
||||
.. note:: A full file path **must** begin with a forward slash (/) if that file
|
||||
is not in the root directory.
|
||||
|
||||
Missing Features
|
||||
^^^^^^^^^^^^^^^^
|
||||
These features that are typically in Linux filesystems have not yet been added to the game:
|
||||
|
||||
* Tab autocompletion does not work with relative paths
|
||||
* :code:`mv` only accepts full filepaths for the destination argument. It does not accept directories
|
||||
|
||||
Commands
|
||||
--------
|
||||
|
||||
@@ -98,6 +177,25 @@ Display a message (.msg), literature (.lit), or text (.txt) file::
|
||||
$ cat foo.lit
|
||||
$ cat servers.txt
|
||||
|
||||
.. _cd_terminal_command:
|
||||
|
||||
cd
|
||||
^^
|
||||
|
||||
$ cd [dir]
|
||||
|
||||
Change to the specified directory.
|
||||
|
||||
See :ref:`terminal_filesystem` for details on directories.
|
||||
|
||||
Note that this command works even for directories that don't exist. If you change
|
||||
to a directory that doesn't exist, it will not be created. A directory is only created
|
||||
once there is a file in it::
|
||||
|
||||
$ cd scripts/hacking
|
||||
$ cd /logs
|
||||
$ cd ..
|
||||
|
||||
check
|
||||
^^^^^
|
||||
|
||||
@@ -234,27 +332,35 @@ killall
|
||||
|
||||
Kills all scripts on the current server.
|
||||
|
||||
.. _ls_terminal_command:
|
||||
|
||||
ls
|
||||
^^
|
||||
|
||||
$ ls [| grep pattern]
|
||||
$ ls [dir] [| grep pattern]
|
||||
|
||||
Prints files on the current server to the Terminal screen.
|
||||
Prints files and directories on the current server to the Terminal screen.
|
||||
|
||||
If this command is run with no arguments, then it prints all files on the current
|
||||
server to the Terminal screen. The files will be displayed in alphabetical
|
||||
order.
|
||||
If this command is run with no arguments, then it prints all files and directories on the current
|
||||
server to the Terminal screen. Directories will be printed first in alphabetical order,
|
||||
followed by the files (also in alphabetical order).
|
||||
|
||||
The '| grep pattern' is an optional parameter that can be used to only display files
|
||||
whose filenames match the specified pattern. For example, if you wanted to only display
|
||||
files with the .script extension, you could use::
|
||||
The :code:`dir` optional parameter allows you to specify the directory for which to display
|
||||
files.
|
||||
|
||||
The :code:`| grep pattern` optional parameter allows you to only display files and directories
|
||||
with a certain pattern in their names.
|
||||
|
||||
Examples::
|
||||
|
||||
// List files/directories with the '.script' extension in the current directory
|
||||
$ ls | grep .script
|
||||
|
||||
Alternatively, if you wanted to display all files with the word *purchase* in the filename,
|
||||
you could use::
|
||||
// List files/directories with the '.js' extension in the root directory
|
||||
$ ls / | grep .js
|
||||
|
||||
$ ls | grep purchase
|
||||
// List files/directories with the word 'purchase' in the name, in the :code:`scripts` directory
|
||||
$ ls scripts | grep purchase
|
||||
|
||||
|
||||
lscpu
|
||||
@@ -282,6 +388,28 @@ The first example above will print the amount of RAM needed to run 'foo.script'
|
||||
with a single thread. The second example above will print the amount of RAM needed
|
||||
to run 'foo.script' with 50 threads.
|
||||
|
||||
.. _mv_terminal_command:
|
||||
|
||||
mv
|
||||
^^
|
||||
|
||||
$ mv [source] [destination]
|
||||
|
||||
Move the source file to the specified destination in the filesystem.
|
||||
See :ref:`terminal_filesystem` for more details about the Terminal's filesystem.
|
||||
This command only works for scripts and text files (.txt). It cannot, however, be used
|
||||
to convert from script to text file, or vice versa.
|
||||
|
||||
This function can also be used to rename files.
|
||||
|
||||
.. note:: Unlike the Linux :code:`mv` command, the *destination* argument must be the
|
||||
full filepath. It cannot be a directory.
|
||||
|
||||
Examples::
|
||||
|
||||
$ mv hacking.script scripts/hacking.script
|
||||
$ mv myScript.js myOldScript.js
|
||||
|
||||
nano
|
||||
^^^^
|
||||
|
||||
|
||||
@@ -3,12 +3,91 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
v0.46.2 - 4/14/2019
|
||||
-------------------
|
||||
* Source-File 2 now allows you to form gangs in other BitNodes when your karma reaches a very large negative value
|
||||
** (Karma is a hidden stat and is lowered by committing crimes)
|
||||
* Gang changes:
|
||||
** Bug Fix: Gangs can no longer clash with themselve
|
||||
** Bug Fix: Winning against another gang should properly reduce their power
|
||||
|
||||
* Bug Fix: Terminal 'wget' command now works properly
|
||||
* Bug Fix: Hacknet Server Hash upgrades now properly reset upon installing Augs/switching BitNodes
|
||||
* Bug Fix: Fixed button for creating Corporations
|
||||
|
||||
v0.46.1 - 4/12/2019
|
||||
-------------------
|
||||
* Added a very rudimentary directory system to the Terminal
|
||||
* Details here: https://bitburner.readthedocs.io/en/latest/basicgameplay/terminal.html#filesystem-directories
|
||||
|
||||
* Added numHashes(), hashCost(), and spendHashes() functions to the Netscript Hacknet Node API
|
||||
* 'Generate Coding Contract' hash upgrade is now more expensive
|
||||
* 'Generate Coding Contract' hash upgrade now generates the contract randomly on the server, rather than on home computer
|
||||
* The cost of selling hashes for money no longer increases each time
|
||||
* Selling hashes for money now costs 4 hashes (in exchange for $1m)
|
||||
* Bug Fix: Hacknet Node earnings should work properly when game is inactive/offline
|
||||
* Bug Fix: Duplicate Sleeve augmentations are now properly reset when switching to a new BitNode
|
||||
|
||||
v0.46.0 - 4/3/2019
|
||||
------------------
|
||||
* Added BitNode-9: Hacktocracy
|
||||
* Changed BitNode-11's multipliers to make it slightly harder overall
|
||||
* Source-File 11 is now slightly stronger
|
||||
* Added several functions to Netscript Sleeve API for buying Sleeve augmentations (by hydroflame)
|
||||
* Added a new stat for Duplicate Sleeves: Memory
|
||||
* Increase baseline experience earned from Infiltration, but it now gives diminishing returns (on exp) as you get to higher difficulties/levels
|
||||
* In Bladeburner, stamina gained from Hyperbolic Regeneration Chamber is now a percentage of your max stamina
|
||||
|
||||
* Corporation Changes:
|
||||
* 'Demand' value of products decreases more slowly
|
||||
* Bug Fix: Fixed a Corporation issue that broke the Market-TA2 Research
|
||||
* Bug Fix: Issuing New Shares now works properly
|
||||
|
||||
* Bug Fix: Money Statistics tracker was incorrectly recording profits when selling stocks manually
|
||||
* Bug Fix: Fixed an issue with the job requirement tooltip for security jobs
|
||||
|
||||
v0.45.1 - 3/23/2019
|
||||
-------------------
|
||||
* Added two new Corporation Researches
|
||||
* General UI improvements (by hydroflame and koriar)
|
||||
* Bug Fix: Sleeve Netscript API should no longer cause Dynamic RAM errors
|
||||
* Bug Fix: sleeve.getSleeveStats() should now work properly
|
||||
|
||||
v0.45.0 - 3/22/2019
|
||||
-------------------
|
||||
* Corporation changes:
|
||||
* Decreased the time of a full market cycle from 15 seconds to 10 seconds.
|
||||
* This means that each Corporation 'state' will now only take 2 seconds, rather than 3
|
||||
* Increased initial salaries for newly-hired employees
|
||||
* Increased the cost multiplier for upgrading office size (the cost will increase faster)
|
||||
* The stats of your employees now has a slightly larger effect on production & sales
|
||||
* Added several new Research upgrades
|
||||
* Market-TA research now allows you to automatically set sale price at optimal values
|
||||
* Market-TA research now works for Products (not just Materials)
|
||||
* Reduced the amount of Scientific Research needed to unlock the Hi-Tech R&D Laboratory from 10k to 5k
|
||||
* Energy Material requirement of the Software industry reduced from 1 to 0.5
|
||||
* It is now slightly easier to increase the Software industry's production multiplier
|
||||
* Industries now have a maximum number of allowed products, starting at 3. This can be increased through research.
|
||||
* You can now see an approximation of how each material affects an industry's production multiplier by clicking the "?" help tip next to it
|
||||
* Significantly changed the effects of the different employee positions. See updated descriptions
|
||||
* Reduced the amount of money you gain from private investors
|
||||
* Training employees is now 3x more effective
|
||||
* Bug Fix: An industry's products are now properly separated between different cities
|
||||
|
||||
* The QLink Augemntation is now significantly stronger, but also significantly more expensive (by hydroflame)
|
||||
* Added a Netscript API for Duplicate Sleeves (by hydroflame)
|
||||
* Modified the multipliers of BitNode-3 and BitNode-8 to make them slightly harder
|
||||
* After installing Augmentations, Duplicate Sleeves will now default to Synchronize if their Shock is 0
|
||||
* Bug Fix: Bladeburner's Hyperbolic Regeneration Chamber should no longer instantly refill all stamina
|
||||
* Bug Fix: growthAnalyze() function now properly accounts for BitNode multipliers
|
||||
* Bug Fix: The cost of purchasing Augmentations for Duplicate Sleeves no longer scales with how many Augs you've purchased for yourself
|
||||
|
||||
v0.44.1 - 3/4/2019
|
||||
------------------
|
||||
* Duplicate Sleeve changes:
|
||||
** You can now purchase Augmentations for your Duplicate Sleeves
|
||||
** Sleeves are now assigned to Shock Recovery task by default
|
||||
** Shock Recovery and Synchronize tasks are now twice as effective
|
||||
* You can now purchase Augmentations for your Duplicate Sleeves
|
||||
* Sleeves are now assigned to Shock Recovery task by default
|
||||
* Shock Recovery and Synchronize tasks are now twice as effective
|
||||
|
||||
* Changed documentation so that Netscript functions are own their own pages. Sorry if this is annoying, it was necessary for properly cross-referencing
|
||||
* Officially deprecated the Wiki (the fandom site). Use the 'readthedocs' Documentation instead
|
||||
|
||||
@@ -64,9 +64,9 @@ documentation_title = '{0} Documentation'.format(project)
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.44'
|
||||
version = '0.46'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.44.1'
|
||||
release = '0.46.2'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@@ -5,7 +5,7 @@ Netscript
|
||||
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 subset of `JavaScript <https://developer.mozilla.org/en-US/docs/Web/JavaScript>`_,.
|
||||
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.
|
||||
@@ -29,4 +29,5 @@ to reach out to the developer!
|
||||
Bladeburner API <netscript/netscriptbladeburnerapi>
|
||||
Gang API <netscript/netscriptgangapi>
|
||||
Coding Contract API <netscript/netscriptcodingcontractapi>
|
||||
Sleeve API <netscript/netscriptsleeveapi>
|
||||
Miscellaneous <netscript/netscriptmisc>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
enableLog() Netscript Function
|
||||
=============================
|
||||
==============================
|
||||
|
||||
.. js:function:: enableLog(fn)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
getScriptRam() Netscript Function
|
||||
===========================
|
||||
=================================
|
||||
|
||||
.. js:function:: getScriptRam(scriptname[, hostname/ip])
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ purchaseServer() Netscript Function
|
||||
.. js:function:: purchaseServer(hostname, ram)
|
||||
|
||||
:param string hostname: Hostname of the purchased server
|
||||
:param number ram: Amount of RAM of the purchased server. Must be a power of 2 (2, 4, 8, 16, etc.). Maximum value of 1048576 (2^20)
|
||||
:param number ram: Amount of RAM of the purchased server. Must be a power of 2. Maximum value of :js:func:`getPurchasedServerMaxRam`
|
||||
:RAM cost: 2.25 GB
|
||||
|
||||
Purchased a server with the specified hostname and amount of RAM.
|
||||
|
||||
@@ -10,3 +10,4 @@ getActionCountRemaining() Netscript Function
|
||||
|
||||
Note that this is meant to be used for Contracts and Operations.
|
||||
This function will return 'Infinity' for actions such as Training and Field Analysis.
|
||||
This function will return 1 for BlackOps not yet completed regardless of wether the player has the required rank to attempt the mission or not.
|
||||
|
||||
10
doc/source/netscript/bladeburnerapi/getBlackOpRank.rst
Normal file
10
doc/source/netscript/bladeburnerapi/getBlackOpRank.rst
Normal file
@@ -0,0 +1,10 @@
|
||||
getBlackOpRank() Netscript Function
|
||||
====================================
|
||||
|
||||
.. js:function:: getBlackOpRank(name)
|
||||
|
||||
:param string name: name of the BlackOp. Must be an exact match.
|
||||
|
||||
Returns the rank required to complete this BlackOp.
|
||||
|
||||
Returns -1 if an invalid action is specified.
|
||||
@@ -8,6 +8,7 @@ recruitMember() Netscript Function
|
||||
Attempt to recruit a new gang member.
|
||||
|
||||
Possible reasons for failure:
|
||||
|
||||
* Cannot currently recruit a new member
|
||||
* There already exists a member with the specified name
|
||||
|
||||
|
||||
17
doc/source/netscript/hacknetnodeapi/getCacheUpgradeCost.rst
Normal file
17
doc/source/netscript/hacknetnodeapi/getCacheUpgradeCost.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
getCacheUpgradeCost() Netscript Function
|
||||
========================================
|
||||
|
||||
.. warning:: This page contains spoilers for the game
|
||||
|
||||
.. js:function:: getCacheUpgradeCost(i, n)
|
||||
|
||||
:param number i: Index/Identifier of Hacknet Node. :ref:`See here for details <netscript_hacknetnodeapi_referencingahacknetnode>`
|
||||
:param number n: Number of times to upgrade cache. Must be positive. Rounded to nearest integer
|
||||
|
||||
.. note:: This function is only applicable for Hacknet Servers (the upgraded version of
|
||||
a Hacknet Node).
|
||||
|
||||
Returns the cost of upgrading the cache level of the specified Hacknet Server by *n*.
|
||||
|
||||
If an invalid value for *n* is provided, then this function returns 0. If the
|
||||
specified Hacknet Server is already at the max cache level, then Infinity is returned.
|
||||
@@ -1,6 +1,8 @@
|
||||
getNodeStats() Netscript Function
|
||||
=================================
|
||||
|
||||
.. warning:: This page contains spoilers for the game
|
||||
|
||||
.. js:function:: getNodeStats(i)
|
||||
|
||||
:param number i: Index/Identifier of Hacknet Node. :ref:`See here for details <netscript_hacknetnodeapi_referencingahacknetnode>`
|
||||
@@ -12,7 +14,12 @@ getNodeStats() Netscript Function
|
||||
level: Node's level,
|
||||
ram: Node's RAM,
|
||||
cores: Node's number of cores,
|
||||
production: Node's money earned per second,
|
||||
cache: Cache level. Only applicable for Hacknet Servers
|
||||
production: Node's production per second
|
||||
timeOnline: Number of seconds since Node has been purchased,
|
||||
totalProduction: Total number of money Node has produced
|
||||
totalProduction: Total amount that the Node has produced
|
||||
}
|
||||
|
||||
.. note:: Note that for Hacknet Nodes, production refers to the amount of money the node generates.
|
||||
For Hacknet Servers (the upgraded version of Hacknet Nodes), production refers to the amount
|
||||
of hashes the node generates.
|
||||
|
||||
23
doc/source/netscript/hacknetnodeapi/hashCost.rst
Normal file
23
doc/source/netscript/hacknetnodeapi/hashCost.rst
Normal file
@@ -0,0 +1,23 @@
|
||||
hashCost() Netscript Function
|
||||
=============================
|
||||
|
||||
.. warning:: This page contains spoilers for the game
|
||||
|
||||
.. js:function:: hashCost(upgName)
|
||||
|
||||
:param string upgName: Name of upgrade to get the cost of. Must be an exact match
|
||||
|
||||
.. note:: This function is only applicable for Hacknet Servers (the upgraded version
|
||||
of a Hacknet Node).
|
||||
|
||||
Returns the number of hashes required for the specified upgrade. The name of the
|
||||
upgrade must be an exact match.
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
var upgradeName = "Sell for Corporation Funds";
|
||||
if (hacknet.numHashes() > hacknet.hashCost(upgradeName)) {
|
||||
hacknet.spendHashes(upgName);
|
||||
}
|
||||
11
doc/source/netscript/hacknetnodeapi/numHashes.rst
Normal file
11
doc/source/netscript/hacknetnodeapi/numHashes.rst
Normal file
@@ -0,0 +1,11 @@
|
||||
numHashes() Netscript Function
|
||||
==============================
|
||||
|
||||
.. warning:: This page contains spoilers for the game
|
||||
|
||||
.. js:function:: numHashes()
|
||||
|
||||
.. note:: This function is only applicable for Hacknet Servers (the upgraded version
|
||||
of a Hacknet Node).
|
||||
|
||||
Returns the number of hashes you have
|
||||
26
doc/source/netscript/hacknetnodeapi/spendHashes.rst
Normal file
26
doc/source/netscript/hacknetnodeapi/spendHashes.rst
Normal file
@@ -0,0 +1,26 @@
|
||||
spendHashes() Netscript Function
|
||||
================================
|
||||
|
||||
.. warning:: This page contains spoilers for the game
|
||||
|
||||
.. js:function:: spendHashes(upgName, upgTarget)
|
||||
|
||||
:param string upgName: Name of upgrade to spend hashes on. Must be an exact match
|
||||
:param string upgTarget: Object to which upgrade applies. Required for certain upgrades
|
||||
|
||||
.. note:: This function is only applicable for Hacknet Servers (the upgraded version
|
||||
of a Hacknet Node).
|
||||
|
||||
Spend the hashes generated by your Hacknet Servers on an upgrade. Returns a boolean value -
|
||||
true if the upgrade is successfully purchased, and false otherwise.
|
||||
|
||||
The name of the upgrade must be an exact match. The :code:`upgTarget` argument is used
|
||||
for upgrades such as :code:`Reduce Minimum Security`, which applies to a specific server.
|
||||
In this case, the :code:`upgTarget` argument must be the hostname of the server.
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
hacknet.spendHashes("Sell for Corporation Funds");
|
||||
hacknet.spendHashes("Increase Maximum Money", "foodnstuff");
|
||||
19
doc/source/netscript/hacknetnodeapi/upgradeCache.rst
Normal file
19
doc/source/netscript/hacknetnodeapi/upgradeCache.rst
Normal file
@@ -0,0 +1,19 @@
|
||||
upgradeCache() Netscript Function
|
||||
=================================
|
||||
|
||||
.. warning:: This page contains spoilers for the game
|
||||
|
||||
.. js:function:: upgradeCache(i, n)
|
||||
|
||||
:param number i: Index/Identifier of Hacknet Node. :ref:`See here for details <netscript_hacknetnodeapi_referencingahacknetnode>`
|
||||
:param number n: Number of cache levels to purchase. Must be positive. Rounded to nearest integer
|
||||
|
||||
.. note:: This function is only applicable for Hacknet Servers (the upgraded version of
|
||||
a Hacknet Node).
|
||||
|
||||
Tries to upgrade the specified Hacknet Server's cache *n* times.
|
||||
|
||||
Returns true if it successfully upgrades the Server's cache *n* times, or if
|
||||
it purchases some positive amount and the Server reaches its max cache level.
|
||||
|
||||
Returns false otherwise.
|
||||
@@ -4,6 +4,8 @@ Netscript Advanced Functions
|
||||
These Netscript functions become relevant later on in the game. They are put on a separate page because
|
||||
they contain spoilers for the game.
|
||||
|
||||
.. warning:: This page contains spoilers for the game
|
||||
|
||||
.. toctree::
|
||||
|
||||
getBitNodeMultipliers() <advancedfunctions/getBitNodeMultipliers>
|
||||
|
||||
@@ -7,7 +7,7 @@ Netscript provides the following API for interacting with the game's Bladeburner
|
||||
The Bladeburner API is **not** immediately available to the player and must be unlocked
|
||||
later in the game
|
||||
|
||||
**WARNING: This page contains spoilers for the game**
|
||||
.. warning:: This page contains spoilers for the game
|
||||
|
||||
The Bladeburner API is unlocked in BitNode-7. If you are in BitNode-7, you will
|
||||
automatically gain access to this API. Otherwise, you must have Source-File 7 in
|
||||
@@ -46,6 +46,7 @@ In :ref:`netscriptjs`::
|
||||
setActionAutolevel() <bladeburnerapi/setActionAutolevel>
|
||||
setActionLevel() <bladeburnerapi/setActionLevel>
|
||||
getRank() <bladeburnerapi/getRank>
|
||||
getBlackOpRank() <bladeburnerapi/getBlackOpRank>
|
||||
getSkillPoints() <bladeburnerapi/getSkillPoints>
|
||||
getSkillLevel() <bladeburnerapi/getSkillLevel>
|
||||
getSkillUpgradeCost() <bladeburnerapi/getSkillUpgradeCost>
|
||||
|
||||
@@ -6,7 +6,7 @@ Netscript provides the following API for interacting with the game's Gang mechan
|
||||
The Gang API is **not** immediately available to the player and must be unlocked
|
||||
later in the game
|
||||
|
||||
**WARNING: This page contains spoilers for the game**
|
||||
.. warning:: This page contains spoilers for the game
|
||||
|
||||
The Gang API is unlocked in BitNode-2. Currently, BitNode-2 is the only location
|
||||
where the Gang mechanic is accessible. This may change in the future
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
Netscript Hacknet Node API
|
||||
==========================
|
||||
|
||||
.. warning:: Not all functions in the Hacknet Node API are immediately available.
|
||||
For this reason, the documentation for this API may contains spoilers
|
||||
for the game.
|
||||
|
||||
Netscript provides the following API for accessing and upgrading your Hacknet Nodes
|
||||
through scripts.
|
||||
|
||||
@@ -31,9 +35,14 @@ In :ref:`netscriptjs`::
|
||||
upgradeLevel() <hacknetnodeapi/upgradeLevel>
|
||||
upgradeRam() <hacknetnodeapi/upgradeRam>
|
||||
upgradeCore() <hacknetnodeapi/upgradeCore>
|
||||
upgradeCache() <hacknetnodeapi/upgradeCache>
|
||||
getLevelUpgradeCost() <hacknetnodeapi/getLevelUpgradeCost>
|
||||
getRamUpgradeCost() <hacknetnodeapi/getRamUpgradeCost>
|
||||
getCoreUpgradeCost() <hacknetnodeapi/getCoreUpgradeCost>
|
||||
getCacheUpgradeCost() <hacknetnodeapi/getCacheUpgradeCost>
|
||||
numHashes() <hacknetnodeapi/numHashes>
|
||||
hashCost() <hacknetnodeapi/hashCost>
|
||||
spendHashes() <hacknetnodeapi/spendHashes>
|
||||
|
||||
.. _netscript_hacknetnodeapi_referencingahacknetnode:
|
||||
|
||||
@@ -68,23 +77,25 @@ The following is an example of one way a script can be used to automate the
|
||||
purchasing and upgrading of Hacknet Nodes.
|
||||
|
||||
This script attempts to purchase Hacknet Nodes until the player has a total of 8. Then
|
||||
it gradually upgrades those Node's to a minimum of level 140, 64 GB RAM, and 8 cores::
|
||||
it gradually upgrades those Node's to a minimum of level 140, 64 GB RAM, and 8 cores
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
function myMoney() {
|
||||
return getServerMoneyAvailable("home");() <hacknetnodeapi/ return getServerMoneyAvailable("home");>
|
||||
}
|
||||
}() <hacknetnodeapi/>
|
||||
return getServerMoneyAvailable("home");
|
||||
}
|
||||
|
||||
disableLog("getServerMoneyAvailable");
|
||||
disableLog("sleep");
|
||||
|
||||
cnt = 8;
|
||||
var cnt = 8;
|
||||
|
||||
while(hacknet.numNodes() < cnt) {
|
||||
res = hacknet.purchaseNode();
|
||||
print("Purchased hacknet Node with index " + res);
|
||||
};
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
for (var i = 0; i < cnt; i++) {
|
||||
while (hacknet.getNodeStats(i).level <= 80) {
|
||||
var cost = hacknet.getLevelUpgradeCost(i, 10);
|
||||
while (myMoney() < cost) {
|
||||
@@ -95,9 +106,9 @@ it gradually upgrades those Node's to a minimum of level 140, 64 GB RAM, and 8 c
|
||||
};
|
||||
};
|
||||
|
||||
print("All nodes upgrade to level 80");
|
||||
print("All nodes upgraded to level 80");
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
for (var i = 0; i < cnt; i++) {
|
||||
while (hacknet.getNodeStats(i).ram < 16) {
|
||||
var cost = hacknet.getRamUpgradeCost(i, 2);
|
||||
while (myMoney() < cost) {
|
||||
@@ -108,43 +119,4 @@ it gradually upgrades those Node's to a minimum of level 140, 64 GB RAM, and 8 c
|
||||
};
|
||||
};
|
||||
|
||||
print("All nodes upgrade to 16GB RAM");
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
while (hacknet.getNodeStats(i).level <= 140) {
|
||||
var cost = hacknet.getLevelUpgradeCost(i, 5);
|
||||
while (myMoney() < cost) {
|
||||
print("Need $" + cost + " . Have $" + myMoney());
|
||||
sleep(3000);
|
||||
}
|
||||
res = hacknet.upgradeLevel(i, 5);
|
||||
};
|
||||
};
|
||||
|
||||
print("All nodes upgrade to level 140");
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
while (hacknet.getNodeStats(i).ram < 64) {
|
||||
var cost = hacknet.getRamUpgradeCost(i, 2);
|
||||
while (myMoney() < cost) {
|
||||
print("Need $" + cost + " . Have $" + myMoney());
|
||||
sleep(3000);
|
||||
}
|
||||
res = hacknet.upgradeRam(i, 2);
|
||||
};
|
||||
};
|
||||
|
||||
print("All nodes upgrade to 64GB RAM (MAX)");
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
while (hacknetnodes.getNodeStatsi(i).cores < 8) {
|
||||
var cost = hacknet.getCoreUpgradeCost(7);
|
||||
while (myMoney() < cost) {
|
||||
print("Need $" + cost + " . Have $" + myMoney());
|
||||
sleep(3000);
|
||||
}
|
||||
res = hacknet.upgradeCore(i, 7);
|
||||
};
|
||||
};
|
||||
|
||||
print("All nodes upgrade to 8 cores");
|
||||
print("All nodes upgraded to 16GB RAM");
|
||||
|
||||
@@ -9,7 +9,7 @@ and creating programs.
|
||||
|
||||
The Singularity Functions are **not** immediately available to the player and must be unlocked later in the game.
|
||||
|
||||
**WARNING: This page contains spoilers for the game**.
|
||||
.. warning:: This page contains spoilers for the game
|
||||
|
||||
The Singularity Functions are unlocked in BitNode-4. If you are in BitNode-4, then you will automatically have access to all of these functions.
|
||||
You can use the Singularity Functions in other BitNodes if and only if you have the Source-File for BitNode-4 (aka Source-File 4). Each level of
|
||||
@@ -20,7 +20,7 @@ Note that Singularity Functions require twice as much RAM outside of BitNode-4
|
||||
|
||||
.. toctree::
|
||||
:caption: Functions:
|
||||
|
||||
|
||||
universityCourse() <singularityfunctions/universityCourse>
|
||||
gymWorkout() <singularityfunctions/gymWorkout>
|
||||
travelToCity() <singularityfunctions/travelToCity>
|
||||
|
||||
79
doc/source/netscript/netscriptsleeveapi.rst
Normal file
79
doc/source/netscript/netscriptsleeveapi.rst
Normal file
@@ -0,0 +1,79 @@
|
||||
.. _netscript_sleeveapi:
|
||||
|
||||
Netscript Sleeve API
|
||||
=========================
|
||||
Netscript provides the following API for interacting with the game's
|
||||
:ref:`Duplicate Sleeve <gameplay_duplicatesleeves>` mechanic.
|
||||
|
||||
The Sleeve API is **not** immediately available to the player and must be unlocked
|
||||
later in the game.
|
||||
|
||||
.. warning:: This page contains spoilers for the game
|
||||
|
||||
The Sleeve API is unlocked in BitNode-10. If you are in BitNode-10, you will
|
||||
automatically gain access to this API. Otherwise, you must have Source-File 10 in
|
||||
order to use this API in other BitNodes
|
||||
|
||||
**Sleeve API functions must be accessed through the 'sleeve' namespace**
|
||||
|
||||
In :ref:`netscript1`::
|
||||
|
||||
sleeve.synchronize(0);
|
||||
sleeve.commitCrime(0, "shoplift");
|
||||
|
||||
In :ref:`netscriptjs`::
|
||||
|
||||
ns.sleeve.synchronize(0);
|
||||
ns.sleeve.commitCrime(0, "shoplift");
|
||||
|
||||
.. toctree::
|
||||
:caption: API Functions:
|
||||
|
||||
getNumSleeves() <sleeveapi/getNumSleeves>
|
||||
getSleeveStats() <sleeveapi/getSleeveStats>
|
||||
getInformation() <sleeveapi/getInformation>
|
||||
getTask() <sleeveapi/getTask>
|
||||
setToShockRecovery() <sleeveapi/setToShockRecovery>
|
||||
setToSynchronize() <sleeveapi/setToSynchronize>
|
||||
setToCommitCrime() <sleeveapi/setToCommitCrime>
|
||||
setToFactionWork() <sleeveapi/setToFactionWork>
|
||||
setToCompanyWork() <sleeveapi/setToCompanyWork>
|
||||
setToUniversityCourse() <sleeveapi/setToUniversityCourse>
|
||||
setToGymWorkout() <sleeveapi/setToGymWorkout>
|
||||
travel() <sleeveapi/travel>
|
||||
getSleeveAugmentations() <sleeveapi/getSleeveAugmentations>
|
||||
getSleevePurchasableAugs() <sleeveapi/getSleevePurchasableAugs>
|
||||
purchaseSleeveAug() <sleeveapi/purchaseSleeveAug>
|
||||
|
||||
.. _netscript_sleeveapi_referencingaduplicatesleeve:
|
||||
|
||||
Referencing a Duplicate Sleeve
|
||||
------------------------------
|
||||
Most of the functions in the Sleeve API perform an operation on a single Duplicate
|
||||
Sleeve. In order to specify which Sleeve the operation should be performed on,
|
||||
a numeric index is used as an identifier. The index should follow array-notation, such
|
||||
that the first Duplicate Sleeve has an index of 0, the second Duplicate Sleeve has
|
||||
an index of 1, and so on.
|
||||
|
||||
The order of the Duplicate Sleeves matches the order on the UI page.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
**Basic example usage**::
|
||||
|
||||
for (var i = 0; i < sleeve.getNumSleeves(); i++) {
|
||||
sleeve.shockRecovery(i);
|
||||
}
|
||||
|
||||
sleep(10*60*60); // wait 10h
|
||||
|
||||
for (var i = 0; i < sleeve.getNumSleeves(); i++) {
|
||||
sleeve.synchronize(i);
|
||||
}
|
||||
|
||||
sleep(10*60*60); // wait 10h
|
||||
|
||||
for (var i = 0; i < sleeve.getNumSleeves(); i++) {
|
||||
sleeve.commitCrime(i, 'shoplift');
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
workForCompany() Netscript Function
|
||||
===================================
|
||||
|
||||
.. js:function:: workForCompany()
|
||||
.. js:function:: workForCompany(companyName=lastCompany)
|
||||
|
||||
:param string companyName: Name of company to work for. Must be an exact match.
|
||||
Optional. If not specified, this argument defaults to
|
||||
the last job that you worked
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.
|
||||
|
||||
|
||||
65
doc/source/netscript/sleeveapi/getInformation.rst
Normal file
65
doc/source/netscript/sleeveapi/getInformation.rst
Normal file
@@ -0,0 +1,65 @@
|
||||
getInformation() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: getInformation(sleeveNumber)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to retrieve information. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
|
||||
Return a struct containing tons of information about this sleeve
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
city: location of the sleeve,
|
||||
hp: current hp of the sleeve,
|
||||
maxHp: max hp of the sleeve,
|
||||
jobs: jobs available to the sleeve,
|
||||
jobTitle: job titles available to the sleeve,
|
||||
tor: does this sleeve have access to the tor router,
|
||||
mult: {
|
||||
agility: agility multiplier,
|
||||
agilityExp: agility exp multiplier,
|
||||
companyRep: company reputation multiplier,
|
||||
crimeMoney: crime money multiplier,
|
||||
crimeSuccess: crime success chance multiplier,
|
||||
defense: defense multiplier,
|
||||
defenseExp: defense exp multiplier,
|
||||
dexterity: dexterity multiplier,
|
||||
dexterityExp: dexterity exp multiplier,
|
||||
factionRep: faction reputation multiplier,
|
||||
hacking: hacking skill multiplier,
|
||||
hackingExp: hacking exp multiplier,
|
||||
strength: strength multiplier,
|
||||
strengthExp: strength exp multiplier,
|
||||
workMoney: work money multiplier,
|
||||
},
|
||||
timeWorked: time spent on the current task in milliseconds,
|
||||
earningsForSleeves : { earnings synchronized to other sleeves
|
||||
workHackExpGain: hacking exp gained from work,
|
||||
workStrExpGain: strength exp gained from work,
|
||||
workDefExpGain: defense exp gained from work,
|
||||
workDexExpGain: dexterity exp gained from work,
|
||||
workAgiExpGain: agility exp gained from work,
|
||||
workChaExpGain: charisma exp gained from work,
|
||||
workMoneyGain: money gained from work,
|
||||
},
|
||||
earningsForPlayer : { earnings synchronized to the player
|
||||
workHackExpGain: hacking exp gained from work,
|
||||
workStrExpGain: strength exp gained from work,
|
||||
workDefExpGain: defense exp gained from work,
|
||||
workDexExpGain: dexterity exp gained from work,
|
||||
workAgiExpGain: agility exp gained from work,
|
||||
workChaExpGain: charisma exp gained from work,
|
||||
workMoneyGain: money gained from work,
|
||||
},
|
||||
earningsForTask : { earnings for this sleeve
|
||||
workHackExpGain: hacking exp gained from work,
|
||||
workStrExpGain: strength exp gained from work,
|
||||
workDefExpGain: defense exp gained from work,
|
||||
workDexExpGain: dexterity exp gained from work,
|
||||
workAgiExpGain: agility exp gained from work,
|
||||
workChaExpGain: charisma exp gained from work,
|
||||
workMoneyGain: money gained from work,
|
||||
},
|
||||
workRepGain: sl.getRepGain(),
|
||||
}
|
||||
6
doc/source/netscript/sleeveapi/getNumSleeves.rst
Normal file
6
doc/source/netscript/sleeveapi/getNumSleeves.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
getNumSleeves() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: getNumSleeves()
|
||||
|
||||
Return the number of duplicate sleeves the player has.
|
||||
@@ -0,0 +1,8 @@
|
||||
getSleeveAugmentations() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: getSleeveAugmentations(sleeveNumber)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to retrieve augmentations from. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
|
||||
Return a list of augmentation names that this sleeve has installed.
|
||||
17
doc/source/netscript/sleeveapi/getSleevePurchasableAugs.rst
Normal file
17
doc/source/netscript/sleeveapi/getSleevePurchasableAugs.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
getSleevePurchasableAugs() Netscript Function
|
||||
=============================================
|
||||
|
||||
.. js:function:: getSleevePurchasableAugs(sleeveNumber)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to retrieve purchasable augmentations from. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
|
||||
Return a list of augmentations that the player can buy for this sleeve.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
[
|
||||
{
|
||||
name: string, // augmentation name
|
||||
cost: number, // augmentation cost
|
||||
}
|
||||
]
|
||||
21
doc/source/netscript/sleeveapi/getSleeveStats.rst
Normal file
21
doc/source/netscript/sleeveapi/getSleeveStats.rst
Normal file
@@ -0,0 +1,21 @@
|
||||
getSleeveStats() Netscript Function
|
||||
===================================
|
||||
|
||||
.. js:function:: getSleeveStats(sleeveNumber)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to get stats of. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
|
||||
Return a structure containing the stats of the sleeve
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
shock: current shock of the sleeve [0-100],
|
||||
sync: current sync of the sleeve [0-100],
|
||||
hacking_skill: current hacking skill of the sleeve,
|
||||
strength: current strength of the sleeve,
|
||||
defense: current defense of the sleeve,
|
||||
dexterity: current dexterity of the sleeve,
|
||||
agility: current agility of the sleeve,
|
||||
charisma: current charisma of the sleeve,
|
||||
}
|
||||
18
doc/source/netscript/sleeveapi/getTask.rst
Normal file
18
doc/source/netscript/sleeveapi/getTask.rst
Normal file
@@ -0,0 +1,18 @@
|
||||
getTask() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: getTask(sleeveNumber)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to retrieve task from. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
|
||||
Return the current task that the sleeve is performing. type is set to "Idle" if the sleeve isn't doing anything
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
task: string, // task type
|
||||
crime: string, // crime currently attempting, if any
|
||||
location: string, // location of the task, if any
|
||||
gymStatType: string, // stat being trained at the gym, if any
|
||||
factionWorkType: string, // faction work type being performed, if any
|
||||
}
|
||||
9
doc/source/netscript/sleeveapi/purchaseSleeveAug.rst
Normal file
9
doc/source/netscript/sleeveapi/purchaseSleeveAug.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
purchaseSleeveAug() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: purchaseSleeveAug(sleeveNumber, augName)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to buy an aug for. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
:param string augName: Name of the aug to buy. Must be an exact match
|
||||
|
||||
Return true if the aug was purchased and installed on the sleeve.
|
||||
11
doc/source/netscript/sleeveapi/setToCommitCrime.rst
Normal file
11
doc/source/netscript/sleeveapi/setToCommitCrime.rst
Normal file
@@ -0,0 +1,11 @@
|
||||
setToCommitCrime() Netscript Function
|
||||
=====================================
|
||||
|
||||
.. js:function:: setToCommitCrime(sleeveNumber, name)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to start commiting crime. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
:param string name: Name of the crime. Must be an exact match.
|
||||
|
||||
Return a boolean indicating whether or not this action was set successfully.
|
||||
|
||||
Returns false if an invalid action is specified.
|
||||
9
doc/source/netscript/sleeveapi/setToCompanyWork.rst
Normal file
9
doc/source/netscript/sleeveapi/setToCompanyWork.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
setToCompanyWork() Netscript Function
|
||||
=====================================
|
||||
|
||||
.. js:function:: setToCompanyWork(sleeveNumber, companyName)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to work for the company. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
:param string companyName: Name of the company to work for.
|
||||
|
||||
Return a boolean indicating whether or not the sleeve started working or this company.
|
||||
10
doc/source/netscript/sleeveapi/setToFactionWork.rst
Normal file
10
doc/source/netscript/sleeveapi/setToFactionWork.rst
Normal file
@@ -0,0 +1,10 @@
|
||||
setToFactionWork() Netscript Function
|
||||
=====================================
|
||||
|
||||
.. js:function:: setToFactionWork(sleeveNumber, factionName, factionWorkType)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to work for the faction. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
:param string factionName: Name of the faction to work for.
|
||||
:param string factionWorkType: Name of the action to perform for this faction.
|
||||
|
||||
Return a boolean indicating whether or not the sleeve started working or this faction.
|
||||
10
doc/source/netscript/sleeveapi/setToGymWorkout.rst
Normal file
10
doc/source/netscript/sleeveapi/setToGymWorkout.rst
Normal file
@@ -0,0 +1,10 @@
|
||||
setToGymWorkout() Netscript Function
|
||||
====================================
|
||||
|
||||
.. js:function:: setToGymWorkout(sleeveNumber, gymName, stat)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to workout at the gym. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
:param string gymName: Name of the gym.
|
||||
:param string stat: Name of the stat to train.
|
||||
|
||||
Return a boolean indicating whether or not the sleeve started working out.
|
||||
8
doc/source/netscript/sleeveapi/setToShockRecovery.rst
Normal file
8
doc/source/netscript/sleeveapi/setToShockRecovery.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
setToShockRecovery() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: setToShockRecovery(sleeveNumber)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to start recovery. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
|
||||
Return a boolean indicating whether or not this action was set successfully.
|
||||
8
doc/source/netscript/sleeveapi/setToSynchronize.rst
Normal file
8
doc/source/netscript/sleeveapi/setToSynchronize.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
setToSynchronize() Netscript Function
|
||||
=====================================
|
||||
|
||||
.. js:function:: setToSynchronize(sleeveNumber)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to start synchronizing. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
|
||||
Return a boolean indicating whether or not this action was set successfully.
|
||||
10
doc/source/netscript/sleeveapi/setToUniversityCourse.rst
Normal file
10
doc/source/netscript/sleeveapi/setToUniversityCourse.rst
Normal file
@@ -0,0 +1,10 @@
|
||||
setToUniversityCourse() Netscript Function
|
||||
==========================================
|
||||
|
||||
.. js:function:: setToUniversityCourse(sleeveNumber, university, className)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to start taking class. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
:param string university: Name of the university to attend.
|
||||
:param string className: Name of the class to follow.
|
||||
|
||||
Return a boolean indicating whether or not this action was set successfully.
|
||||
9
doc/source/netscript/sleeveapi/travel.rst
Normal file
9
doc/source/netscript/sleeveapi/travel.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
travel() Netscript Function
|
||||
=======================================
|
||||
|
||||
.. js:function:: travel(sleeveNumber, cityName)
|
||||
|
||||
:param int sleeveNumber: Index of the sleeve to travel. See :ref:`here <netscript_sleeveapi_referencingaduplicatesleeve>`
|
||||
:param string cityName: Name of the destination city.
|
||||
|
||||
Return a boolean indicating whether or not the sleeve reached destination.
|
||||
437
index.html
437
index.html
@@ -115,7 +115,7 @@
|
||||
|
||||
<div id="script-editor-filename-wrapper">
|
||||
<p id="script-editor-filename-tag"> <strong style="background-color:#555;">Script name: </strong></p>
|
||||
<input id="script-editor-filename" type="text" maxlength="30" tabindex="1"/>
|
||||
<input id="script-editor-filename" type="text" maxlength="100" tabindex="1"/>
|
||||
</div>
|
||||
|
||||
<div id="ace-editor"></div>
|
||||
@@ -131,7 +131,7 @@
|
||||
<h1 style="color:white;"> Script Editor Options </h1>
|
||||
<fieldset>
|
||||
<label for="script-editor-option-editor">Editor</label>
|
||||
<select id="script-editor-option-editor">
|
||||
<select id="script-editor-option-editor" class="dropdown">
|
||||
<option value="Ace">Ace</option>
|
||||
<option value="CodeMirror">CodeMirror</option>
|
||||
</select>
|
||||
@@ -139,12 +139,12 @@
|
||||
|
||||
<fieldset>
|
||||
<label for="script-editor-option-theme">Theme</label>
|
||||
<select id="script-editor-option-theme"></select>
|
||||
<select id="script-editor-option-theme" class="dropdown"></select>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="script-editor-option-keybinding">Key Binding</label>
|
||||
<select id="script-editor-option-keybinding"></select>
|
||||
<select id="script-editor-option-keybinding" class="dropdown"></select>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
@@ -201,257 +201,9 @@
|
||||
|
||||
<!-- Hacknet Nodes -->
|
||||
<div id="hacknet-nodes-container" class="generic-menupage-container">
|
||||
<h1 id="hacknet-nodes-title"> Hacknet Nodes </h1>
|
||||
<p id="hacknet-nodes-text" class="menu-page-text">
|
||||
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/>
|
||||
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/>
|
||||
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/>
|
||||
<div id="hacknet-nodes-money-multipliers-div">
|
||||
<p id="hacknet-nodes-money">
|
||||
<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>
|
||||
<a id="hacknet-nodes-5x-multiplier" class="a-link-button"> x5 </a>
|
||||
<a id="hacknet-nodes-10x-multiplier" class="a-link-button"> x10 </a>
|
||||
<a id="hacknet-nodes-max-multiplier" class="a-link-button"> MAX </a>
|
||||
</span>
|
||||
</div>
|
||||
<ul id="hacknet-nodes-list">
|
||||
</ul>
|
||||
<!-- React Component -->
|
||||
</div>
|
||||
|
||||
<!-- World -->
|
||||
<div id="world-container" class="generic-menupage-container">
|
||||
<h2 id="world-city-name"> </h2>
|
||||
<p id="world-city-desc"> </p>
|
||||
<ul id="aevum-locations-list">
|
||||
<li id="aevum-travelagency-li">
|
||||
<a id="aevum-travelagency" class="a-link-button"> Travel Agency </a>
|
||||
</li>
|
||||
<li id="aevum-hospital-li">
|
||||
<a id="aevum-hospital" class="a-link-button">Hospital</a>
|
||||
</li>
|
||||
<li id="aevum-summituniversity-li">
|
||||
<a id="aevum-summituniversity" class="a-link-button"> Summit University </a>
|
||||
</li>
|
||||
<li id="aevum-ecorp-li">
|
||||
<a id="aevum-ecorp" class="a-link-button"> ECorp </a>
|
||||
</li>
|
||||
<li id="aevum-bachmanandassociates-li">
|
||||
<a id="aevum-bachmanandassociates" class="a-link-button"> Bachman & Associates</a>
|
||||
</li>
|
||||
<li id="aevum-clarkeincorporated-li">
|
||||
<a id="aevum-clarkeincorporated" class="a-link-button"> Clarke Incorporated </a>
|
||||
</li>
|
||||
<li id="aevum-fulcrumtechnologies-li">
|
||||
<a id="aevum-fulcrumtechnologies" class="a-link-button"> Fulcrum Technologies </a>
|
||||
</li>
|
||||
<li id="aevum-aerocorp-li">
|
||||
<a id="aevum-aerocorp" class="a-link-button"> AeroCorp </a>
|
||||
</li>
|
||||
<li id="aevum-galacticcybersystems-li">
|
||||
<a id="aevum-galacticcybersystems" class="a-link-button"> Galactic Cybersystems </a>
|
||||
</li>
|
||||
<li id="aevum-watchdogsecurity-li">
|
||||
<a id="aevum-watchdogsecurity" class="a-link-button">Watchdog Security </a>
|
||||
</li>
|
||||
<li id="aevum-rhoconstruction-li">
|
||||
<a id="aevum-rhoconstruction" class="a-link-button">Rho Construction </a>
|
||||
</li>
|
||||
<li id="aevum-aevumpolice-li">
|
||||
<a id="aevum-aevumpolice" class="a-link-button">Aevum Police</a>
|
||||
</li>
|
||||
<li id="aevum-netlinktechnologies-li">
|
||||
<a id="aevum-netlinktechnologies" class="a-link-button">NetLink Technologies</a>
|
||||
</li>
|
||||
<li id="aevum-crushfitnessgym-li">
|
||||
<a id="aevum-crushfitnessgym" class="a-link-button">Crush Fitness Gym </a>
|
||||
</li>
|
||||
<li id="aevum-snapfitnessgym-li">
|
||||
<a id="aevum-snapfitnessgym" class="a-link-button">Snap Fitness Gym</a>
|
||||
</li>
|
||||
<li id="aevum-slums-li">
|
||||
<a id="aevum-slums" class="a-link-button">The Slums</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul id="chongqing-locations-list">
|
||||
<li id="chongqing-travelagency-li">
|
||||
<a id="chongqing-travelagency" class="a-link-button"> Travel Agency </a>
|
||||
</li>
|
||||
<li id="chongqing-hospital-li">
|
||||
<a id="chongqing-hospital" class="a-link-button">Hospital</a>
|
||||
</li>
|
||||
<li id="chonqging-kuaigonginternational-li">
|
||||
<a id="chongqing-kuaigonginternational" class="a-link-button">KuaiGong International </a>
|
||||
</li>
|
||||
<li id="chongqing-solarisspacesystems-li">
|
||||
<a id="chongqing-solarisspacesystems" class="a-link-button">Solaris Space Systems</a>
|
||||
</li>
|
||||
<li id="chongqing-slums-li">
|
||||
<a id="chongqing-slums" class="a-link-button">The Slums</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul id="sector12-locations-list">
|
||||
<li id="sector12-travelagency-li">
|
||||
<a id="sector12-travelagency" class="a-link-button">Travel Agency </a>
|
||||
</li>
|
||||
<li id="sector12-hospital-li">
|
||||
<a id="sector12-hospital" class="a-link-button">Hospital</a>
|
||||
</li>
|
||||
<li id="sector12-rothmanuniversity-li">
|
||||
<a id="sector12-rothmanuniversity" class="a-link-button"> Rothman University</a>
|
||||
</li>
|
||||
<li id="sector12-megacorp-li">
|
||||
<a id="sector12-megacorp" class="a-link-button">MegaCorp</a>
|
||||
</li>
|
||||
<li id="sector12-bladeindustries-li">
|
||||
<a id="sector12-bladeindustries" class="a-link-button"> Blade Industries</a>
|
||||
</li>
|
||||
<li id="sector12-foursigma-li">
|
||||
<a id="sector12-foursigma" class="a-link-button">Four Sigma</a>
|
||||
</li>
|
||||
<li id="sector12-icarusmicrosystems-li">
|
||||
<a id="sector12-icarusmicrosystems" class="a-link-button"> Icarus Microsystems</a>
|
||||
</li>
|
||||
<li id="sector12-universalenergy-li">
|
||||
<a id="sector12-universalenergy" class="a-link-button">Universal Energy </a>
|
||||
</li>
|
||||
<li id="sector12-deltaone-li">
|
||||
<a id="sector12-deltaone" class="a-link-button">DeltaOne </a>
|
||||
</li>
|
||||
<li id="sector12-cia-li">
|
||||
<a id="sector12-cia" class="a-link-button">Central Intelligence Agency </a>
|
||||
</li>
|
||||
<li id="sector12-nsa-li">
|
||||
<a id="sector12-nsa" class="a-link-button">National Security Agency </a>
|
||||
</li>
|
||||
<li id="sector12-alphaenterprises-li">
|
||||
<a id="sector12-alphaenterprises" class="a-link-button">Alpha Enterprises</a>
|
||||
</li>
|
||||
<li id="sector12-carmichaelsecurity-li">
|
||||
<a id="sector12-carmichaelsecurity" class="a-link-button"> Carmichael Security</a>
|
||||
</li>
|
||||
<li id="sector12-foodnstuff-li">
|
||||
<a id="sector12-foodnstuff" class="a-link-button">FoodNStuff</a>
|
||||
</li>
|
||||
<li id="sector12-joesguns-li">
|
||||
<a id="sector12-joesguns" class="a-link-button"> Joe's Guns</a>
|
||||
</li>
|
||||
<li id="sector12-irongym-li">
|
||||
<a id="sector12-irongym" class="a-link-button">Iron Gym </a>
|
||||
</li>
|
||||
<li id="sector12-powerhousegym-li">
|
||||
<a id="sector12-powerhousegym" class="a-link-button">Powerhouse Gym</a>
|
||||
</li>
|
||||
<li id="sector12-slums-li">
|
||||
<a id="sector12-slums" class="a-link-button">The Slums</a>
|
||||
</li>
|
||||
<li id="sector12-cityhall-li">
|
||||
<a id="sector12-cityhall" class="a-link-button">City Hall</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul id="newtokyo-locations-list">
|
||||
<li id="newtokyo-travelagency-li">
|
||||
<a id="newtokyo-travelagency" class="a-link-button"> Travel Agency</a>
|
||||
</li>
|
||||
<li id="newtokyo-hospital-li">
|
||||
<a id="newtokyo-hospital" class="a-link-button">Hospital</a>
|
||||
</li>
|
||||
<li id="newtokyo-defcomm-li">
|
||||
<a id="newtokyo-defcomm" class="a-link-button"> DefComm</a>
|
||||
</li>
|
||||
<li id="newtokyo-vitalife-li">
|
||||
<a id="newtokyo-vitalife" class="a-link-button">VitaLife </a>
|
||||
</li>
|
||||
<li id="newtokyo-globalpharmaceuticals-li">
|
||||
<a id="newtokyo-globalpharmaceuticals" class="a-link-button">Global Pharmaceuticals</a>
|
||||
</li>
|
||||
<li id="newtokyo-noodlebar-li">
|
||||
<a id="newtokyo-noodlebar" class="a-link-button">Noodle Bar </a>
|
||||
</li>
|
||||
<li id="newtokyo-slums-li">
|
||||
<a id="newtokyo-slums" class="a-link-button">The Slums</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul id="ishima-locations-list">
|
||||
<li id="ishima-travelagency-li">
|
||||
<a id="ishima-travelagency" class="a-link-button">Travel Agency </a>
|
||||
</li>
|
||||
<li id="ishima-hospital-li">
|
||||
<a id="ishima-hospital" class="a-link-button">Hospital</a>
|
||||
</li>
|
||||
<li id="ishima-stormtechnologies-li">
|
||||
<a id="ishima-stormtechnologies" class="a-link-button">Storm Technologies</a>
|
||||
</li>
|
||||
<li id="ishima-novamedical-li">
|
||||
<a id="ishima-novamedical" class="a-link-button">Nova Medical</a>
|
||||
</li>
|
||||
<li id="ishima-omegasoftware-li">
|
||||
<a id="ishima-omegasoftware" class="a-link-button">Omega Software </a>
|
||||
</li>
|
||||
<li id="ishima-slums-li">
|
||||
<a id="ishima-slums" class="a-link-button">The Slums</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul id="volhaven-locations-list">
|
||||
<li id="volhaven-travelagency-li">
|
||||
<a id="volhaven-travelagency" class="a-link-button">Travel Agency </a>
|
||||
</li>
|
||||
<li id="volhaven-hospital-li">
|
||||
<a id="volhaven-hospital" class="a-link-button">Hospital</a>
|
||||
</li>
|
||||
<li id="volhaven-zbinstituteoftechnology-li">
|
||||
<a id="volhaven-zbinstituteoftechnology" class="a-link-button">ZB Insitute of Technology</a>
|
||||
</li>
|
||||
<li id="volhaven-omnitekincorporated-li">
|
||||
<a id="volhaven-omnitekincorporated" class="a-link-button">OmniTek Incorporated </a>
|
||||
</li>
|
||||
<li id="volhaven-nwo-li">
|
||||
<a id="volhaven-nwo" class="a-link-button">NWO</a>
|
||||
</li>
|
||||
<li id="volhaven-helislabs-li">
|
||||
<a id="volhaven-helioslabs" class="a-link-button">Helios Labs</a>
|
||||
</li>
|
||||
<li id="volhaven-omniacybersystems-li">
|
||||
<a id="volhaven-omniacybersystems" class="a-link-button">Omnia Cybersystems</a>
|
||||
</li>
|
||||
<li id="volhaven-lexocorp-li">
|
||||
<a id="volhaven-lexocorp" class="a-link-button">LexoCorp</a>
|
||||
</li>
|
||||
<li id="volhaven-syscoresecurities-li">
|
||||
<a id="volhaven-syscoresecurities" class="a-link-button">SysCore Securities</a>
|
||||
</li>
|
||||
<li id="volhaven-computek-li">
|
||||
<a id="volhaven-computek" class="a-link-button">CompuTek</a>
|
||||
</li>
|
||||
<li id="volhaven-milleniumfitnessgym-li">
|
||||
<a id="volhaven-milleniumfitnessgym" class="a-link-button">Millenium Fitness Gym</a>
|
||||
</li>
|
||||
<li id="volhaven-slums-li">
|
||||
<a id="volhaven-slums" class="a-link-button">The Slums</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul id="generic-locations-list"></ul>
|
||||
</div>
|
||||
|
||||
<!-- Create a program(executable) -->
|
||||
<div id="create-program-container" class="generic-menupage-container">
|
||||
<p id="create-program-page-text">
|
||||
@@ -469,8 +221,6 @@
|
||||
<!-- Single Faction info (when you select a faction from the Factions menu) -->
|
||||
<div id="faction-container" class="generic-menupage-container"></div>
|
||||
|
||||
<div id="faction-augmentations-container" class="generic-menupage-container"></div>
|
||||
|
||||
<!-- Augmentations -->
|
||||
<div id="augmentations-container" class="generic-menupage-container"></div>
|
||||
|
||||
@@ -478,150 +228,31 @@
|
||||
<div id="tutorial-container" class="generic-menupage-container">
|
||||
<h1> Tutorial (AKA Links to Documentation) </h1>
|
||||
<a id="tutorial-getting-started-link" class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/guidesandtips/gettingstartedguideforbeginnerprogrammers.html">
|
||||
Getting Started
|
||||
</a><br><br>
|
||||
Getting Started</a><br><br>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/servers.html">
|
||||
Servers & Networking
|
||||
</a><br><br>
|
||||
Servers & Networking</a><br><br>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/hacking.html">
|
||||
Hacking
|
||||
</a><br><br>
|
||||
Hacking</a><br><br>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/scripts.html">
|
||||
Scripts
|
||||
</a><br><br>
|
||||
Scripts</a><br><br>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/netscript.html">
|
||||
Netscript Programming Language
|
||||
</a><br><br>
|
||||
Netscript Programming Language</a><br><br>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/world.html">
|
||||
Traveling
|
||||
</a><br><br>
|
||||
Traveling</a><br><br>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/companies.html">
|
||||
Companies
|
||||
</a><br><br>
|
||||
Companies</a><br><br>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/infiltration.html">
|
||||
Infiltration
|
||||
</a><br><br>
|
||||
Infiltration</a><br><br>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/factions.html">
|
||||
Factions
|
||||
</a><br><br>
|
||||
Factions</a><br><br>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/augmentations.html">
|
||||
Augmentations
|
||||
</a><br><br>
|
||||
Augmentations</a><br><br>
|
||||
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/shortcuts.html">
|
||||
Keyboard Shortcuts
|
||||
</a>
|
||||
Keyboard Shortcuts</a>
|
||||
</div>
|
||||
|
||||
<!-- Location (visiting a location in World) -->
|
||||
<div id="location-container" class="generic-menupage-container">
|
||||
<a id="location-return-to-world-button" class="a-link-button"> Return to World </a>
|
||||
<h1 id="location-name"></h1>
|
||||
<p id="location-info"> </p>
|
||||
|
||||
<p id="location-job-title"> </p>
|
||||
<p id="location-text-divider-1"> --------------- </p>
|
||||
<p id="location-job-reputation" class="tooltip"> </p>
|
||||
<p id="location-text-divider-2"> --------------- </p>
|
||||
<p id="location-company-favor" class="tooltip"> </p>
|
||||
<p id="location-text-divider-3"> --------------- </p>
|
||||
|
||||
<!-- Jobs/Work at a company -->
|
||||
<a id="location-software-job" class="a-link-button tooltip"> Apply for Software Job</a>
|
||||
<a id="location-software-consultant-job" class="a-link-button tooltip"> Apply for Software Consultant Job</a>
|
||||
<a id="location-it-job" class="a-link-button tooltip"> Apply for IT Job </a>
|
||||
<a id="location-security-engineer-job" class="a-link-button tooltip"> Apply for Security Engineer Job</a>
|
||||
<a id="location-network-engineer-job" class="a-link-button tooltip"> Apply for Network Engineer Job</a>
|
||||
<a id="location-business-job" class="a-link-button tooltip"> Apply for Business Job</a>
|
||||
<a id="location-business-consultant-job" class="a-link-button tooltip"> Apply for Business Consultant Job </a>
|
||||
<a id="location-security-job" class="a-link-button tooltip"> Apply for Security Job</a>
|
||||
<a id="location-agent-job" class="a-link-button tooltip"> Apply to be an Agent</a>
|
||||
<a id="location-employee-job" class="a-link-button tooltip"> Apply to be an Employee </a>
|
||||
<a id="location-parttime-employee-job" class="a-link-button tooltip"> Apply to be a Part-time Employee </a>
|
||||
<a id="location-waiter-job" class="a-link-button tooltip"> Apply to be a Waiter</a>
|
||||
<a id="location-parttime-waiter-job" class="a-link-button tooltip"> Apply to be a Part-time Waiter</a>
|
||||
|
||||
<a id="location-work" class="a-link-button"> Work </a>
|
||||
|
||||
<!-- Gym -->
|
||||
<a id="location-gym-train-str" class="a-link-button">Train Strength</a>
|
||||
<a id="location-gym-train-def" class="a-link-button">Train Defense </a>
|
||||
<a id="location-gym-train-dex" class="a-link-button">Train Dexterity</a>
|
||||
<a id="location-gym-train-agi" class="a-link-button">Train Agility</a>
|
||||
|
||||
<!-- Study/Take classes at a university -->
|
||||
<a id="location-study-computer-science" class="a-link-button">Study Computer Science (free)</a>
|
||||
<a id="location-data-structures-class" class="a-link-button">Take Data Structures course</a>
|
||||
<a id="location-networks-class" class="a-link-button">Take Networks course</a>
|
||||
<a id="location-algorithms-class" class="a-link-button">Take Algorithms course</a>
|
||||
<a id="location-management-class" class="a-link-button">Take Management course</a>
|
||||
<a id="location-leadership-class" class="a-link-button">Take Leadership course</a>
|
||||
|
||||
<!-- Purchase servers -->
|
||||
<a id="location-purchase-2gb" class="a-link-button"> Purchase 2GB Server - $150,000</a>
|
||||
<a id="location-purchase-4gb" class="a-link-button"> Purchase 4GB Server - $300,000</a>
|
||||
<a id="location-purchase-8gb" class="a-link-button"> Purchase 8GB Server - $600,000</a>
|
||||
<a id="location-purchase-16gb" class="a-link-button"> Purchase 16GB Server - $1,200,000</a>
|
||||
<a id="location-purchase-32gb" class="a-link-button"> Purchase 32GB Server - $2,400,000</a>
|
||||
<a id="location-purchase-64gb" class="a-link-button"> Purchase 64GB Server - $4,800,000</a>
|
||||
<a id="location-purchase-128gb" class="a-link-button"> Purchase 128GB Server - $9,600,000</a>
|
||||
<a id="location-purchase-256gb" class="a-link-button"> Purchase 256GB Server - $19,200,000</a>
|
||||
<a id="location-purchase-512gb" class="a-link-button"> Purchase 512GB Server - $38,400,000</a>
|
||||
<a id="location-purchase-1tb" class="a-link-button"> Purchase 1TB Server - $75,000,000</a>
|
||||
<a id="location-purchase-tor" class="a-link-button"> Purchase TOR Router - $100,000</a>
|
||||
<a id="location-purchase-home-ram" class="a-link-button"> Purchase additional RAM for Home computer </a>
|
||||
<a id="location-purchase-home-cores" class="a-link-button"> Purchase additional Core for Home computer </a>
|
||||
|
||||
<!-- Infiltrate -->
|
||||
<a id="location-infiltrate" class="a-link-button tooltip"> Infiltrate Company
|
||||
<span class="tooltiptext">
|
||||
Infiltrate this company's facility to try and steal their classified secrets!
|
||||
Warning: You may end up hospitalized if you are unsuccessful!
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<!-- Hospital -->
|
||||
<a id="location-hospital-treatment" class="a-link-button"> Get Treatment for Wounds </a>
|
||||
|
||||
<!-- Travel agency -->
|
||||
<p id="location-travel-agency-text">
|
||||
From here, you can travel to any other city! A ticket costs $200,000.
|
||||
</p>
|
||||
<a id="location-travel-to-aevum" class="a-link-button"> Travel to Aevum </a>
|
||||
<a id="location-travel-to-chongqing" class="a-link-button"> Travel to Chongqing</a>
|
||||
<a id="location-travel-to-sector12" class="a-link-button"> Travel to Sector-12</a>
|
||||
<a id="location-travel-to-newtokyo" class="a-link-button"> Travel to New Tokyo</a>
|
||||
<a id="location-travel-to-ishima" class="a-link-button"> Travel to Ishima</a>
|
||||
<a id="location-travel-to-volhaven" class="a-link-button"> Travel to Volhaven</a>
|
||||
|
||||
<!-- 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
|
||||
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>
|
||||
<a id="location-slums-rob-store" class="a-link-button tooltip"> Rob a store </a>
|
||||
<a id="location-slums-mug" class="a-link-button tooltip"> Mug someone </a>
|
||||
<a id="location-slums-larceny" class="a-link-button tooltip"> Commit Larceny </a>
|
||||
<a id="location-slums-deal-drugs" class="a-link-button tooltip"> Deal Drugs </a>
|
||||
<a id="location-slums-bond-forgery" class="a-link-button tooltip">Bond Forgery</a>
|
||||
<a id="location-slums-traffic-arms" class="a-link-button tooltip">Traffick Illegal Arms</a>
|
||||
<a id="location-slums-homicide" class="a-link-button tooltip">Homicide</a>
|
||||
<a id="location-slums-gta" class="a-link-button tooltip"> Grand Theft Auto </a>
|
||||
<a id="location-slums-kidnap" class="a-link-button tooltip"> Kidnap and Ransom </a>
|
||||
<a id="location-slums-assassinate" class="a-link-button tooltip"> Assassinate </a>
|
||||
<a id="location-slums-heist" class="a-link-button tooltip"> Heist </a>
|
||||
|
||||
<!-- City Hall -->
|
||||
<a id="location-cityhall-create-corporation" class="a-link-button">Create a Corporation</a>
|
||||
|
||||
<!-- Bladeburner @ NSA -->
|
||||
<a id="location-nsa-bladeburner" class="a-link-button">Bladeburner Division</a>
|
||||
|
||||
<!-- Re-sleeving @ VitaLife -->
|
||||
<a id="location-vitalife-resleeve" class="a-link-button">Re-Sleeve</a>
|
||||
</div>
|
||||
|
||||
<div id="infiltration-container" class="generic-menupage-container">
|
||||
@@ -689,7 +320,7 @@
|
||||
<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 id="stock-market-watchlist-filter" class="text-input" 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>
|
||||
@@ -744,7 +375,7 @@
|
||||
<p id="infiltration-box-text"> </p>
|
||||
|
||||
<button id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </button> <br/><br/>
|
||||
<select id="infiltration-faction-select"> </select> <br/>
|
||||
<select id="infiltration-faction-select" class="dropdown"> </select> <br/>
|
||||
<button id="infiltration-box-faction" class="a-link-button"> Give to Faction for Reputation </button>
|
||||
|
||||
</div>
|
||||
@@ -783,35 +414,7 @@
|
||||
<div id="character-overview-wrapper">
|
||||
<div id="character-overview-container">
|
||||
<div id="character-overview-text">
|
||||
<table>
|
||||
<tr id="character-hp-wrapper">
|
||||
<td>Hp:</td><td id="character-hp-text" class="character-stat-cell"></td>
|
||||
</tr>
|
||||
<tr id="character-money-wrapper">
|
||||
<td>Money: </td><td id="character-money-text" class="character-stat-cell"></td>
|
||||
</tr>
|
||||
<tr id="character-hack-wrapper">
|
||||
<td>Hack: </td><td id="character-hack-text" class="character-stat-cell"></td>
|
||||
</tr>
|
||||
<tr id="character-str-wrapper">
|
||||
<td>Str: </td><td id="character-str-text" class="character-stat-cell"></td>
|
||||
</tr>
|
||||
<tr id="character-def-wrapper">
|
||||
<td>Def: </td><td id="character-def-text" class="character-stat-cell"></td>
|
||||
</tr>
|
||||
<tr id="character-dex-wrapper">
|
||||
<td>Dex: </td><td id="character-dex-text" class="character-stat-cell"></td>
|
||||
</tr>
|
||||
<tr id="character-agi-wrapper">
|
||||
<td>Agi: </td><td id="character-agi-text" class="character-stat-cell"></td>
|
||||
</tr>
|
||||
<tr id="character-cha-wrapper">
|
||||
<td>Cha: </td><td id="character-cha-text" class="character-stat-cell"></td>
|
||||
</tr>
|
||||
<tr id="character-int-wrapper">
|
||||
<td>Int: </td><td id="character-int-text" class="character-stat-cell"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- ReactJS Component -->
|
||||
</div>
|
||||
<div class="character-quick-options">
|
||||
<button id="character-overview-save-button" class="character-overview-btn">Save Game</button>
|
||||
@@ -959,7 +562,7 @@
|
||||
Sets the locale for displaying numbers. Defaults to 'en'
|
||||
</span>
|
||||
</label>
|
||||
<select name="settingsLocale" id="settingsLocale">
|
||||
<select name="settingsLocale" id="settingsLocale" class="dropdown">
|
||||
<option value="en">en</option>
|
||||
<option value="bg">bg</option>
|
||||
<option value="cs">cs</option>
|
||||
|
||||
1933
package-lock.json
generated
1933
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@@ -7,6 +7,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/numeral": "0.0.25",
|
||||
"@types/react": "^16.8.6",
|
||||
"@types/react-dom": "^16.8.2",
|
||||
"acorn": "^5.0.0",
|
||||
"acorn-dynamic-import": "^2.0.0",
|
||||
"ajv": "^5.1.5",
|
||||
@@ -22,7 +24,7 @@
|
||||
"file-saver": "^1.3.8",
|
||||
"interpret": "^1.0.0",
|
||||
"jquery": "^3.3.1",
|
||||
"jshint": "^2.9.7",
|
||||
"jshint": "^2.10.2",
|
||||
"json-loader": "^0.5.4",
|
||||
"jsplumb": "^2.6.8",
|
||||
"jszip": "^3.1.5",
|
||||
@@ -31,14 +33,18 @@
|
||||
"memory-fs": "~0.4.1",
|
||||
"normalize.css": "^8.0.0",
|
||||
"numeral": "2.0.6",
|
||||
"react": "^16.8.3",
|
||||
"react-dom": "^16.8.3",
|
||||
"sprintf-js": "^1.1.1",
|
||||
"tapable": "^1.0.0",
|
||||
"uglifyjs-webpack-plugin": "^1.2.5",
|
||||
"uuid": "^3.2.1",
|
||||
"w3c-blob": "0.0.1"
|
||||
},
|
||||
"description": "A cyberpunk-themed incremental game",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.3.4",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"babel-loader": "^8.0.5",
|
||||
"beautify-lint": "^1.0.3",
|
||||
"benchmark": "^2.1.1",
|
||||
"bundle-loader": "~0.5.0",
|
||||
@@ -54,7 +60,7 @@
|
||||
"istanbul": "^0.4.5",
|
||||
"js-beautify": "^1.5.10",
|
||||
"json5": "^1.0.1",
|
||||
"less": "^3.0.4",
|
||||
"less": "^3.9.0",
|
||||
"less-loader": "^4.1.0",
|
||||
"lodash": "^4.17.10",
|
||||
"mini-css-extract-plugin": "^0.4.1",
|
||||
@@ -73,15 +79,17 @@
|
||||
"stylelint": "^9.2.1",
|
||||
"stylelint-declaration-use-variable": "^1.6.1",
|
||||
"stylelint-order": "^0.8.1",
|
||||
"ts-loader": "^4.4.1",
|
||||
"ts-loader": "^4.5.0",
|
||||
"tslint": "^5.10.0",
|
||||
"typescript": "^2.9.2",
|
||||
"uglify-es": "^3.3.9",
|
||||
"uglifyjs-webpack-plugin": "^1.3.0",
|
||||
"url-loader": "^1.0.1",
|
||||
"watchpack": "^1.6.0",
|
||||
"webpack": "^4.12.0",
|
||||
"webpack-cli": "^3.0.4",
|
||||
"webpack-dev-middleware": "^3.1.3",
|
||||
"webpack-dev-server": "^3.1.4",
|
||||
"webpack-dev-server": "^3.2.1",
|
||||
"worker-loader": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -106,5 +114,5 @@
|
||||
"watch": "webpack --watch --mode production",
|
||||
"watch:dev": "webpack --watch --mode development"
|
||||
},
|
||||
"version": "0.40.2"
|
||||
"version": "0.46.2"
|
||||
}
|
||||
|
||||
@@ -1,35 +1,38 @@
|
||||
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";
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {createProgressBarText} from "../utils/helpers/createProgressBarText";
|
||||
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
|
||||
import {getElementById} from "../utils/uiHelpers/getElementById";
|
||||
import {logBoxCreate} from "../utils/LogBox";
|
||||
import {formatNumber,
|
||||
convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
import {removeElement} from "../utils/uiHelpers/removeElement";
|
||||
import {roundToTwo} from "../utils/helpers/roundToTwo";
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
// TODO - Convert this to React
|
||||
import { workerScripts, killWorkerScript } from "./NetscriptWorker";
|
||||
import { Player } from "./Player";
|
||||
import { getServer } from "./Server/ServerHelpers";
|
||||
|
||||
/* {
|
||||
* serverName: {
|
||||
* header: Server Header Element
|
||||
* panel: Server Panel List (ul) element
|
||||
* scripts: {
|
||||
* script id: Ref to Script information
|
||||
* }
|
||||
* }
|
||||
* ...
|
||||
import { Page, routing } from "./ui/navigationTracking";
|
||||
import { numeralWrapper } from "./ui/numeralFormat";
|
||||
|
||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||
import { logBoxCreate } from "../utils/LogBox";
|
||||
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||
import { arrayToString } from "../utils/helpers/arrayToString";
|
||||
import { createProgressBarText } from "../utils/helpers/createProgressBarText";
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { roundToTwo } from "../utils/helpers/roundToTwo";
|
||||
import { createAccordionElement } from "../utils/uiHelpers/createAccordionElement";
|
||||
import { createElement } from "../utils/uiHelpers/createElement";
|
||||
import { getElementById } from "../utils/uiHelpers/getElementById";
|
||||
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
import { removeElement } from "../utils/uiHelpers/removeElement";
|
||||
|
||||
|
||||
/**
|
||||
* {
|
||||
* serverName: {
|
||||
* header: Server Header Element
|
||||
* panel: Server Panel List (ul) element
|
||||
* scripts: {
|
||||
* script id: Ref to Script information
|
||||
* }
|
||||
* }
|
||||
* ...
|
||||
*/
|
||||
let ActiveScriptsUI = {};
|
||||
let ActiveScriptsTasks = []; //Sequentially schedule the creation/deletion of UI elements
|
||||
const ActiveScriptsUI = {};
|
||||
const ActiveScriptsTasks = []; // Sequentially schedule the creation/deletion of UI elements
|
||||
|
||||
const getHeaderHtml = (server) => {
|
||||
// TODO: calculate the longest hostname length rather than hard coding it
|
||||
@@ -48,7 +51,7 @@ const updateHeaderHtml = (server) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// convert it to a string, as that's how it's stored it will come out of the data attributes
|
||||
// Convert it to a string, as that's how it's stored it will come out of the data attributes
|
||||
const ramPercentage = '' + roundToTwo(server.ramUsed / server.maxRam);
|
||||
if (accordion.header.dataset.ramPercentage !== ramPercentage) {
|
||||
accordion.header.dataset.ramPercentage = ramPercentage;
|
||||
@@ -81,16 +84,18 @@ function createActiveScriptsServerPanel(server) {
|
||||
header: hdr,
|
||||
panel: panel,
|
||||
panelList: panelScriptList,
|
||||
scripts: {}, //Holds references to li elements for each active script
|
||||
scriptHdrs: {}, //Holds references to header elements for each active script
|
||||
scriptStats: {} //Holds references to the p elements containing text for each active script
|
||||
scripts: {}, // Holds references to li elements for each active script
|
||||
scriptHdrs: {}, // Holds references to header elements for each active script
|
||||
scriptStats: {}, // Holds references to the p elements containing text for each active script
|
||||
};
|
||||
|
||||
return li;
|
||||
}
|
||||
|
||||
//Deletes the info for a particular server (Dropdown header + Panel with all info)
|
||||
//in the Active Scripts page if it exists
|
||||
/**
|
||||
* Deletes the info for a particular server (Dropdown header + Panel with all info)
|
||||
* in the Active Scripts page if it exists
|
||||
*/
|
||||
function deleteActiveScriptsServerPanel(server) {
|
||||
let hostname = server.hostname;
|
||||
if (ActiveScriptsUI[hostname] == null) {
|
||||
@@ -98,9 +103,9 @@ function deleteActiveScriptsServerPanel(server) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Make sure it's empty
|
||||
// Make sure it's empty
|
||||
if (Object.keys(ActiveScriptsUI[hostname].scripts).length > 0) {
|
||||
console.log("WARNING: Tried to delete Active Scripts Server panel that still has scripts. Aborting");
|
||||
console.warn("Tried to delete Active Scripts Server panel that still has scripts. Aborting");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -112,7 +117,7 @@ function deleteActiveScriptsServerPanel(server) {
|
||||
function addActiveScriptsItem(workerscript) {
|
||||
var server = getServer(workerscript.serverIp);
|
||||
if (server == null) {
|
||||
console.log("ERROR: Invalid server IP for workerscript in addActiveScriptsItem()");
|
||||
console.warn("Invalid server IP for workerscript in addActiveScriptsItem()");
|
||||
return;
|
||||
}
|
||||
let hostname = server.hostname;
|
||||
@@ -122,7 +127,7 @@ function addActiveScriptsItem(workerscript) {
|
||||
createActiveScriptsServerPanel(server);
|
||||
}
|
||||
|
||||
//Create the unique identifier (key) for this script
|
||||
// Create the unique identifier (key) for this script
|
||||
var itemNameArray = ["active", "scripts", hostname, workerscript.name];
|
||||
for (var i = 0; i < workerscript.args.length; ++i) {
|
||||
itemNameArray.push(String(workerscript.args[i]));
|
||||
@@ -139,8 +144,10 @@ function addActiveScriptsItem(workerscript) {
|
||||
panel.classList.remove("accordion-panel");
|
||||
panel.classList.add("active-scripts-script-panel");
|
||||
|
||||
//Handle the constant elements on the panel that don't change after creation
|
||||
//Threads, args, kill/log button
|
||||
/**
|
||||
* Handle the constant elements on the panel that don't change after creation:
|
||||
* Threads, args, kill/log button
|
||||
*/
|
||||
panel.appendChild(createElement("p", {
|
||||
innerHTML: "Threads: " + workerscript.scriptRef.threads + "<br>" +
|
||||
"Args: " + arrayToString(workerscript.args)
|
||||
@@ -173,7 +180,7 @@ function addActiveScriptsItem(workerscript) {
|
||||
}
|
||||
}));
|
||||
|
||||
//Append element to list
|
||||
// Append element to list
|
||||
ActiveScriptsUI[hostname]["panelList"].appendChild(li);
|
||||
ActiveScriptsUI[hostname].scripts[itemName] = li;
|
||||
ActiveScriptsUI[hostname].scriptHdrs[itemName] = hdr;
|
||||
@@ -218,11 +225,13 @@ function deleteActiveScriptsItem(workerscript) {
|
||||
}.bind(null, workerscript));
|
||||
}
|
||||
|
||||
//Update the ActiveScriptsItems array
|
||||
function updateActiveScriptsItems(maxTasks=150) {
|
||||
//Run tasks that need to be done sequentially (adding items, creating/deleting server panels)
|
||||
//We'll limit this to 150 at a time in case someone decides to start a bunch of scripts all at once...
|
||||
let numTasks = Math.min(maxTasks, ActiveScriptsTasks.length);
|
||||
/**
|
||||
* Run tasks that need to be done sequentially (adding items, creating/deleting server panels)
|
||||
* We'll limit this to 150 at a time for performance (in case someone decides to start a
|
||||
* bunch of scripts all at once...)
|
||||
*/
|
||||
const numTasks = Math.min(maxTasks, ActiveScriptsTasks.length);
|
||||
for (let i = 0; i < numTasks; ++i) {
|
||||
let task = ActiveScriptsTasks.shift();
|
||||
try {
|
||||
@@ -233,8 +242,8 @@ function updateActiveScriptsItems(maxTasks=150) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!routing.isOn(Page.ActiveScripts)) {return;}
|
||||
var total = 0;
|
||||
if (!routing.isOn(Page.ActiveScripts)) { return; }
|
||||
let total = 0;
|
||||
for (var i = 0; i < workerScripts.length; ++i) {
|
||||
try {
|
||||
total += updateActiveScriptsItemContent(workerScripts[i]);
|
||||
@@ -246,10 +255,10 @@ function updateActiveScriptsItems(maxTasks=150) {
|
||||
getElementById("active-scripts-total-production-active").innerText = numeralWrapper.formatMoney(total);
|
||||
getElementById("active-scripts-total-prod-aug-total").innerText = numeralWrapper.formatMoney(Player.scriptProdSinceLastAug);
|
||||
getElementById("active-scripts-total-prod-aug-avg").innerText = numeralWrapper.formatMoney(Player.scriptProdSinceLastAug / (Player.playtimeSinceLastAug/1000));
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
//Updates the content of the given item in the Active Scripts list
|
||||
function updateActiveScriptsItemContent(workerscript) {
|
||||
var server = getServer(workerscript.serverIp);
|
||||
if (server == null) {
|
||||
@@ -258,7 +267,7 @@ function updateActiveScriptsItemContent(workerscript) {
|
||||
}
|
||||
let hostname = server.hostname;
|
||||
if (ActiveScriptsUI[hostname] == null) {
|
||||
return; //Hasn't been created yet. We'll skip it
|
||||
return; // Hasn't been created yet. We'll skip it
|
||||
}
|
||||
|
||||
updateHeaderHtml(server);
|
||||
@@ -270,11 +279,11 @@ function updateActiveScriptsItemContent(workerscript) {
|
||||
var itemName = itemNameArray.join("-");
|
||||
|
||||
if (ActiveScriptsUI[hostname].scriptStats[itemName] == null) {
|
||||
return; //Hasn't been fully added yet. We'll skip it
|
||||
return; // Hasn't been fully added yet. We'll skip it
|
||||
}
|
||||
var item = ActiveScriptsUI[hostname].scriptStats[itemName];
|
||||
|
||||
//Update the text if necessary. This fn returns the online $/s production
|
||||
// Update the text if necessary. This fn returns the online $/s production
|
||||
return updateActiveScriptsText(workerscript, item, itemName);
|
||||
}
|
||||
|
||||
@@ -293,7 +302,7 @@ function updateActiveScriptsText(workerscript, item, itemName) {
|
||||
updateHeaderHtml(server);
|
||||
var onlineMps = workerscript.scriptRef.onlineMoneyMade / workerscript.scriptRef.onlineRunningTime;
|
||||
|
||||
//Only update if the item is visible
|
||||
// Only update if the item is visible
|
||||
if (ActiveScriptsUI[hostname].header.classList.contains("active") === false) {return onlineMps;}
|
||||
if (ActiveScriptsUI[hostname].scriptHdrs[itemName].classList.contains("active") === false) {return onlineMps;}
|
||||
|
||||
@@ -302,7 +311,7 @@ function updateActiveScriptsText(workerscript, item, itemName) {
|
||||
var onlineTime = "Online Time: " + convertTimeMsToTimeElapsedString(workerscript.scriptRef.onlineRunningTime * 1e3);
|
||||
var offlineTime = "Offline Time: " + convertTimeMsToTimeElapsedString(workerscript.scriptRef.offlineRunningTime * 1e3);
|
||||
|
||||
//Online
|
||||
// Online
|
||||
var onlineTotalMoneyMade = "Total online production: " + numeralWrapper.formatMoney(workerscript.scriptRef.onlineMoneyMade);
|
||||
var onlineTotalExpEarned = (Array(26).join(" ") + numeralWrapper.formatBigNumber(workerscript.scriptRef.onlineExpGained) + " hacking exp").replace( / /g, " ");
|
||||
|
||||
@@ -310,7 +319,7 @@ function updateActiveScriptsText(workerscript, item, itemName) {
|
||||
var onlineEps = workerscript.scriptRef.onlineExpGained / workerscript.scriptRef.onlineRunningTime;
|
||||
var onlineEpsText = (Array(25).join(" ") + numeralWrapper.formatBigNumber(onlineEps) + " hacking exp / second").replace( / /g, " ");
|
||||
|
||||
//Offline
|
||||
// Offline
|
||||
var offlineTotalMoneyMade = "Total offline production: " + numeralWrapper.formatMoney(workerscript.scriptRef.offlineMoneyMade);
|
||||
var offlineTotalExpEarned = (Array(27).join(" ") + numeralWrapper.formatBigNumber(workerscript.scriptRef.offlineExpGained) + " hacking exp").replace( / /g, " ");
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import {post} from "./ui/postToTerminal";
|
||||
import { IMap } from "./types";
|
||||
import { post } from "./ui/postToTerminal";
|
||||
|
||||
let Aliases = {};
|
||||
let GlobalAliases = {};
|
||||
export let Aliases: IMap<string> = {};
|
||||
export let GlobalAliases: IMap<string> = {};
|
||||
|
||||
function loadAliases(saveString) {
|
||||
export function loadAliases(saveString: string): void {
|
||||
if (saveString === "") {
|
||||
Aliases = {};
|
||||
} else {
|
||||
@@ -11,7 +12,7 @@ function loadAliases(saveString) {
|
||||
}
|
||||
}
|
||||
|
||||
function loadGlobalAliases(saveString) {
|
||||
export function loadGlobalAliases(saveString: string): void {
|
||||
if (saveString === "") {
|
||||
GlobalAliases = {};
|
||||
} else {
|
||||
@@ -19,8 +20,8 @@ function loadGlobalAliases(saveString) {
|
||||
}
|
||||
}
|
||||
|
||||
//Print all aliases to terminal
|
||||
function printAliases() {
|
||||
// Prints all aliases to terminal
|
||||
export function printAliases(): void {
|
||||
for (var name in Aliases) {
|
||||
if (Aliases.hasOwnProperty(name)) {
|
||||
post("alias " + name + "=" + Aliases[name]);
|
||||
@@ -33,8 +34,8 @@ function printAliases() {
|
||||
}
|
||||
}
|
||||
|
||||
//True if successful, false otherwise
|
||||
function parseAliasDeclaration(dec,global=false) {
|
||||
// Returns true if successful, false otherwise
|
||||
export function parseAliasDeclaration(dec: string, global: boolean=false) {
|
||||
var re = /^([_|\w|!|%|,|@]+)="(.+)"$/;
|
||||
var matches = dec.match(re);
|
||||
if (matches == null || matches.length != 3) {return false;}
|
||||
@@ -46,50 +47,55 @@ function parseAliasDeclaration(dec,global=false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function addAlias(name, value) {
|
||||
if (name in GlobalAliases){
|
||||
function addAlias(name: string, value: string): void {
|
||||
if (name in GlobalAliases) {
|
||||
delete GlobalAliases[name];
|
||||
}
|
||||
Aliases[name] = value;
|
||||
}
|
||||
|
||||
function addGlobalAlias(name, value) {
|
||||
function addGlobalAlias(name: string, value: string): void {
|
||||
if (name in Aliases){
|
||||
delete Aliases[name];
|
||||
}
|
||||
GlobalAliases[name] = value;
|
||||
}
|
||||
|
||||
function getAlias(name) {
|
||||
function getAlias(name: string): string | null {
|
||||
if (Aliases.hasOwnProperty(name)) {
|
||||
return Aliases[name];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getGlobalAlias(name) {
|
||||
function getGlobalAlias(name: string): string | null {
|
||||
if (GlobalAliases.hasOwnProperty(name)) {
|
||||
return GlobalAliases[name];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function removeAlias(name) {
|
||||
export function removeAlias(name: string): boolean {
|
||||
if (Aliases.hasOwnProperty(name)) {
|
||||
delete Aliases[name];
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GlobalAliases.hasOwnProperty(name)) {
|
||||
delete GlobalAliases[name];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//Returns the original string with any aliases substituted in
|
||||
//Aliases only applied to "whole words", one level deep
|
||||
function substituteAliases(origCommand) {
|
||||
var commandArray = origCommand.split(" ");
|
||||
/**
|
||||
* Returns the original string with any aliases substituted in.
|
||||
* Aliases are only applied to "whole words", one level deep
|
||||
*/
|
||||
export function substituteAliases(origCommand: string): string {
|
||||
const commandArray = origCommand.split(" ");
|
||||
if (commandArray.length > 0){
|
||||
// For the unalias command, dont substite
|
||||
if (commandArray[0] === "unalias") { return commandArray.join(" "); }
|
||||
@@ -112,6 +118,3 @@ function substituteAliases(origCommand) {
|
||||
}
|
||||
return commandArray.join(" ");
|
||||
}
|
||||
|
||||
export {Aliases, GlobalAliases, printAliases, parseAliasDeclaration,
|
||||
removeAlias, substituteAliases, loadAliases, loadGlobalAliases};
|
||||
@@ -10,6 +10,7 @@ import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviv
|
||||
|
||||
interface IConstructorParams {
|
||||
info: string;
|
||||
isSpecial?: boolean;
|
||||
moneyCost: number;
|
||||
name: string;
|
||||
prereqs?: string[];
|
||||
@@ -62,6 +63,9 @@ export class Augmentation {
|
||||
// Description of what this Aug is and what it does
|
||||
info: string = "";
|
||||
|
||||
// Any Augmentation not immediately available in BitNode-1 is special (e.g. Bladeburner augs)
|
||||
isSpecial: boolean = false;
|
||||
|
||||
// Augmentation level - for repeatable Augs like NeuroFlux Governor
|
||||
level: number = 0;
|
||||
|
||||
@@ -90,6 +94,10 @@ export class Augmentation {
|
||||
this.baseCost = params.moneyCost * CONSTANTS.AugmentationCostMultiplier * BitNodeMultipliers.AugmentationMoneyCost;
|
||||
this.startingCost = this.baseCost;
|
||||
|
||||
if (params.isSpecial) {
|
||||
this.isSpecial = true;
|
||||
}
|
||||
|
||||
this.level = 0;
|
||||
|
||||
// Set multipliers
|
||||
|
||||
@@ -12,9 +12,9 @@ import { addWorkerScript } from "../NetscriptWorker";
|
||||
import { Player } from "../Player";
|
||||
import { prestigeAugmentation } from "../Prestige";
|
||||
import { saveObject } from "../SaveObject";
|
||||
import { Script,
|
||||
RunningScript} from "../Script";
|
||||
import { Server } from "../Server";
|
||||
import { RunningScript } from "../Script/RunningScript";
|
||||
import { Script } from "../Script/Script";
|
||||
import { Server } from "../Server/Server";
|
||||
import { OwnedAugmentationsOrderSetting } from "../Settings/SettingEnums";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
|
||||
@@ -1213,17 +1213,19 @@ function initAugmentations() {
|
||||
|
||||
//Illuminati
|
||||
var QLink = new Augmentation({
|
||||
name:AugmentationNames.QLink, repCost:750e3, moneyCost:1300e6,
|
||||
name:AugmentationNames.QLink, repCost:750e3, moneyCost:5e12,
|
||||
info:"A brain implant that wirelessly connects you to the Illuminati's " +
|
||||
"quantum supercomputer, allowing you to access and use its incredible " +
|
||||
"computing power.<br><br>" +
|
||||
"This augmentation:<br>" +
|
||||
"Increases the player's hacking speed by 10%.<br>" +
|
||||
"Increases the player's chance of successfully performing a hack by 30%.<br>" +
|
||||
"Increases the amount of money the player gains from hacking by 100%.",
|
||||
hacking_speed_mult: 1.1,
|
||||
hacking_chance_mult: 1.3,
|
||||
hacking_money_mult: 2,
|
||||
"Increases the player's hacking skill by 75%.<br>" +
|
||||
"Increases the player's hacking speed by 100%.<br>" +
|
||||
"Increases the player's chance of successfully performing a hack by 150%.<br>" +
|
||||
"Increases the amount of money the player gains from hacking by 300%.",
|
||||
hacking_mult: 1.75,
|
||||
hacking_speed_mult: 2,
|
||||
hacking_chance_mult: 2.5,
|
||||
hacking_money_mult: 4,
|
||||
});
|
||||
QLink.addToFactions(["Illuminati"]);
|
||||
if (augmentationExists(AugmentationNames.QLink)) {
|
||||
@@ -1675,19 +1677,6 @@ function initAugmentations() {
|
||||
}
|
||||
AddToAugmentations(SNA);
|
||||
|
||||
//For BitNode-2, add all Augmentations to crime/evil factions.
|
||||
//Do this before adding special Augmentations that become available in later BitNodes
|
||||
if (Player.bitNodeN === 2) {
|
||||
console.log("Adding all augmentations to crime factions for Bit node 2");
|
||||
Factions["Slum Snakes"].addAllAugmentations(Augmentations);
|
||||
Factions["Tetrads"].addAllAugmentations(Augmentations);
|
||||
Factions["The Syndicate"].addAllAugmentations(Augmentations);
|
||||
Factions["The Dark Army"].addAllAugmentations(Augmentations);
|
||||
Factions["Speakers for the Dead"].addAllAugmentations(Augmentations);
|
||||
Factions["NiteSec"].addAllAugmentations(Augmentations);
|
||||
Factions["The Black Hand"].addAllAugmentations(Augmentations);
|
||||
}
|
||||
|
||||
//Special Bladeburner Augmentations
|
||||
var BladeburnersFactionName = "Bladeburners";
|
||||
if (factionExists(BladeburnersFactionName)) {
|
||||
@@ -1706,6 +1695,7 @@ function initAugmentations() {
|
||||
"Increases the player's dexterity by 5%.",
|
||||
bladeburner_success_chance_mult: 1.03,
|
||||
dexterity_mult: 1.05,
|
||||
isSpecial: true,
|
||||
});
|
||||
EsperEyewear.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(EsperEyewear);
|
||||
@@ -1723,6 +1713,7 @@ function initAugmentations() {
|
||||
bladeburner_success_chance_mult: 1.03,
|
||||
bladeburner_analysis_mult: 1.05,
|
||||
bladeburner_stamina_gain_mult: 1.02,
|
||||
isSpecial: true,
|
||||
});
|
||||
EMS4Recombination.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(EMS4Recombination);
|
||||
@@ -1741,6 +1732,7 @@ function initAugmentations() {
|
||||
strength_mult: 1.05,
|
||||
dexterity_mult: 1.05,
|
||||
bladeburner_success_chance_mult: 1.04,
|
||||
isSpecial: true,
|
||||
});
|
||||
OrionShoulder.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(OrionShoulder);
|
||||
@@ -1756,6 +1748,7 @@ function initAugmentations() {
|
||||
"This augmentation:<br>" +
|
||||
"Increases the player's success chance in Bladeburner contracts/operations by 6%.",
|
||||
bladeburner_success_chance_mult: 1.06,
|
||||
isSpecial: true,
|
||||
});
|
||||
HyperionV1.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(HyperionV1);
|
||||
@@ -1770,6 +1763,7 @@ function initAugmentations() {
|
||||
"Increases the player's success chance in Bladeburner contracts/operations by 8%.",
|
||||
prereqs:[AugmentationNames.HyperionV1],
|
||||
bladeburner_success_chance_mult: 1.08,
|
||||
isSpecial: true,
|
||||
});
|
||||
HyperionV2.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(HyperionV2);
|
||||
@@ -1788,6 +1782,7 @@ function initAugmentations() {
|
||||
dexterity_mult: 1.07,
|
||||
agility_mult: 1.07,
|
||||
bladeburner_stamina_gain_mult: 1.05,
|
||||
isSpecial: true,
|
||||
});
|
||||
GolemSerum.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(GolemSerum);
|
||||
@@ -1803,6 +1798,7 @@ function initAugmentations() {
|
||||
dexterity_exp_mult: 1.1,
|
||||
bladeburner_analysis_mult: 1.1,
|
||||
bladeburner_success_chance_mult: 1.04,
|
||||
isSpecial: true,
|
||||
});
|
||||
VangelisVirus.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(VangelisVirus);
|
||||
@@ -1822,6 +1818,7 @@ function initAugmentations() {
|
||||
dexterity_exp_mult: 1.1,
|
||||
bladeburner_analysis_mult: 1.15,
|
||||
bladeburner_success_chance_mult: 1.05,
|
||||
isSpecial: true,
|
||||
});
|
||||
VangelisVirus3.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(VangelisVirus3);
|
||||
@@ -1840,6 +1837,7 @@ function initAugmentations() {
|
||||
dexterity_exp_mult: 1.05,
|
||||
agility_exp_mult: 1.05,
|
||||
bladeburner_max_stamina_mult: 1.1,
|
||||
isSpecial: true,
|
||||
});
|
||||
INTERLINKED.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(INTERLINKED);
|
||||
@@ -1857,6 +1855,7 @@ function initAugmentations() {
|
||||
agility_mult: 1.05,
|
||||
bladeburner_max_stamina_mult: 1.05,
|
||||
bladeburner_stamina_gain_mult: 1.05,
|
||||
isSpecial: true,
|
||||
});
|
||||
BladeRunner.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(BladeRunner);
|
||||
@@ -1877,6 +1876,7 @@ function initAugmentations() {
|
||||
agility_mult: 1.04,
|
||||
bladeburner_stamina_gain_mult: 1.02,
|
||||
bladeburner_success_chance_mult: 1.03,
|
||||
isSpecial: true,
|
||||
});
|
||||
BladeArmor.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(BladeArmor);
|
||||
@@ -1893,6 +1893,7 @@ function initAugmentations() {
|
||||
bladeburner_success_chance_mult: 1.05,
|
||||
bladeburner_stamina_gain_mult: 1.02,
|
||||
bladeburner_max_stamina_mult: 1.05,
|
||||
isSpecial: true,
|
||||
});
|
||||
BladeArmorPowerCells.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(BladeArmorPowerCells);
|
||||
@@ -1907,6 +1908,7 @@ function initAugmentations() {
|
||||
prereqs:[AugmentationNames.BladeArmor],
|
||||
defense_mult: 1.05,
|
||||
bladeburner_success_chance_mult: 1.06,
|
||||
isSpecial: true,
|
||||
});
|
||||
BladeArmorEnergyShielding.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(BladeArmorEnergyShielding);
|
||||
@@ -1920,6 +1922,7 @@ function initAugmentations() {
|
||||
"Increases the player's success chance in Bladeburner contracts/operations by 8%.",
|
||||
prereqs:[AugmentationNames.BladeArmor],
|
||||
bladeburner_success_chance_mult: 1.08,
|
||||
isSpecial: true,
|
||||
});
|
||||
BladeArmorUnibeam.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(BladeArmorUnibeam);
|
||||
@@ -1934,6 +1937,7 @@ function initAugmentations() {
|
||||
"Increases the player's success chance in Bladeburner contracts/operations by 10%.",
|
||||
prereqs:[AugmentationNames.BladeArmorUnibeam],
|
||||
bladeburner_success_chance_mult: 1.1,
|
||||
isSpecial: true,
|
||||
});
|
||||
BladeArmorOmnibeam.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(BladeArmorOmnibeam);
|
||||
@@ -1949,6 +1953,7 @@ function initAugmentations() {
|
||||
prereqs:[AugmentationNames.BladeArmor],
|
||||
bladeburner_analysis_mult: 1.15,
|
||||
bladeburner_success_chance_mult: 1.02,
|
||||
isSpecial: true,
|
||||
});
|
||||
BladeArmorIPU.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(BladeArmorIPU);
|
||||
@@ -1961,7 +1966,8 @@ function initAugmentations() {
|
||||
"extremely large radius. These specially-modified holograms were specially " +
|
||||
"weaponized by Bladeburner units to be used against Synthoids.<br><br>" +
|
||||
"This augmentation allows you to perform Bladeburner actions and other " +
|
||||
"actions (such as working, commiting crimes, etc.) at the same time."
|
||||
"actions (such as working, commiting crimes, etc.) at the same time.",
|
||||
isSpecial: true,
|
||||
});
|
||||
BladesSimulacrum.addToFactions([BladeburnersFactionName]);
|
||||
resetAugmentation(BladesSimulacrum);
|
||||
@@ -2067,7 +2073,7 @@ function installAugmentations(cbScript=null) {
|
||||
}
|
||||
var runningScriptObj = new RunningScript(script, []); //No args
|
||||
runningScriptObj.threads = 1; //Only 1 thread
|
||||
home.runningScripts.push(runningScriptObj);
|
||||
home.runScript(runningScriptObj, Player);
|
||||
addWorkerScript(runningScriptObj, home);
|
||||
}
|
||||
}
|
||||
@@ -2095,12 +2101,6 @@ function displayAugmentationsContent(contentEl) {
|
||||
innerText:"Purchased Augmentations",
|
||||
}));
|
||||
|
||||
//Bladeburner text, once mechanic is unlocked
|
||||
var bladeburnerText = "\n";
|
||||
if (Player.bitNodeN === 6 || hasBladeburnerSF) {
|
||||
bladeburnerText = "Bladeburner Progress\n\n";
|
||||
}
|
||||
|
||||
contentEl.appendChild(createElement("pre", {
|
||||
width:"70%", whiteSpace:"pre-wrap", display:"block",
|
||||
innerText:"Below is a list of all Augmentations you have purchased but not yet installed. Click the button below to install them.\n" +
|
||||
@@ -2112,7 +2112,6 @@ function displayAugmentationsContent(contentEl) {
|
||||
"Hacknet Nodes\n" +
|
||||
"Faction/Company reputation\n" +
|
||||
"Stocks\n" +
|
||||
bladeburnerText +
|
||||
"Installing Augmentations lets you start over with the perks and benefits granted by all " +
|
||||
"of the Augmentations you have ever installed. Also, you will keep any scripts and RAM/Core upgrades " +
|
||||
"on your home computer (but you will lose all programs besides NUKE.exe)."
|
||||
|
||||
@@ -57,8 +57,9 @@ export function initBitNodes() {
|
||||
"For every Faction NOT listed above, reputation gains are halved<br>" +
|
||||
"You will no longer gain passive reputation with Factions<br><br>" +
|
||||
"Destroying this BitNode will give you Source-File 2, or if you already have this Source-File it will " +
|
||||
"upgrade its level up to a maximum of 3. This Source-File increases the player's crime success rate, " +
|
||||
"crime money, and charisma multipliers by:<br><br>" +
|
||||
"upgrade its level up to a maximum of 3. This Source-File allows you to form gangs in other BitNodes " +
|
||||
"once your karma decreases to a certain value. " +
|
||||
"It also increases the player's crime success rate, crime money, and charisma multipliers by:<br><br>" +
|
||||
"Level 1: 24%<br>" +
|
||||
"Level 2: 36%<br>" +
|
||||
"Level 3: 42%");
|
||||
@@ -173,7 +174,24 @@ export function initBitNodes() {
|
||||
"Level 3: Ability to use limit/stop orders in other BitNodes<br><br>" +
|
||||
"This Source-File also increases your hacking growth multipliers by: " +
|
||||
"<br>Level 1: 12%<br>Level 2: 18%<br>Level 3: 21%");
|
||||
BitNodes["BitNode9"] = new BitNode(9, "Do Androids Dream?", "COMING SOON");
|
||||
BitNodes["BitNode9"] = new BitNode(9, "Hacktocracy", "Hacknet Unleashed",
|
||||
"When Fulcrum Technologies released their open-source Linux distro Chapeau, it quickly " +
|
||||
"became the OS of choice for the underground hacking community. Chapeau became especially notorious for " +
|
||||
"powering the Hacknet, a global, decentralized network used for nefarious purposes. Fulcrum quickly " +
|
||||
"abandoned the project and dissociated themselves from it.<br><br>" +
|
||||
"This BitNode unlocks the Hacknet Server, an upgraded version of the Hacknet Node. Hacknet Servers generate " +
|
||||
"hashes, which can be spent on a variety of different upgrades.<br><br>" +
|
||||
"In this BitNode:<br><br>" +
|
||||
"Your stats are significantly decreased<br>" +
|
||||
"You cannnot purchase additional servers<br>" +
|
||||
"Hacking is significantly less profitable<br><br>" +
|
||||
"Destroying this BitNode will give you Source-File 9, or if you already have this Source-File it will " +
|
||||
"upgrade its level up to a maximum of 3. This Source-File grants the following benefits:<br><br>" +
|
||||
"Level 1: Permanently unlocks the Hacknet Server in other BitNodes<br>" +
|
||||
"Level 2: You start with 128GB of RAM on your home computer when entering a new BitNode<br>" +
|
||||
"Level 3: Grants a highly-upgraded Hacknet Server when entering a new BitNode<br><br>" +
|
||||
"(Note that the Level 3 effect of this Source-File only applies when entering a new BitNode, NOT " +
|
||||
"when installing Augmentations)");
|
||||
BitNodes["BitNode10"] = new BitNode(10, "Digital Carbon", "Your body is not who you are",
|
||||
"In 2084, VitaLife unveiled to the world the Persona Core, a technology that allowed people " +
|
||||
"to digitize their consciousness. Their consciousness could then be transferred into Synthoids " +
|
||||
@@ -183,7 +201,7 @@ export function initBitNodes() {
|
||||
"1. Re-sleeve: Purchase and transfer your consciousness into a new body<br>" +
|
||||
"2. Duplicate Sleeves: Duplicate your consciousness into Synthoids, allowing you to perform different tasks synchronously<br><br>" +
|
||||
"In this BitNode:<br><br>" +
|
||||
"Your stats are significantly decreased.<br>" +
|
||||
"Your stats are significantly decreased<br>" +
|
||||
"All methods of gaining money are half as profitable (except Stock Market)<br>" +
|
||||
"Purchased servers are more expensive, have less max RAM, and a lower maximum limit<br>" +
|
||||
"Augmentations are 5x as expensive and require twice as much reputation<br><br>" +
|
||||
@@ -198,8 +216,9 @@ export function initBitNodes() {
|
||||
"were able to steal billions of dollars from the world's largest electronic banks, prompting an international banking crisis as " +
|
||||
"governments were unable to bail out insolvent banks. Now, the world is slowly crumbling in the middle of the biggest economic crisis of all time.<br><br>" +
|
||||
"In this BitNode:<br><br>" +
|
||||
"Your hacking stat and experience gain are halved<br>" +
|
||||
"The starting and maximum amount of money available on servers is significantly decreased<br>" +
|
||||
"The growth rate of servers is halved<br>" +
|
||||
"The growth rate of servers is significantly reduced<br>" +
|
||||
"Weakening a server is twice as effective<br>" +
|
||||
"Company wages are decreased by 50%<br>" +
|
||||
"Corporation valuations are 99% lower and are therefore significantly less profitable<br>" +
|
||||
@@ -210,9 +229,9 @@ export function initBitNodes() {
|
||||
"upgrade its level up to a maximum of 3. This Source-File makes it so that company favor increases BOTH " +
|
||||
"the player's salary and reputation gain rate at that company by 1% per favor (rather than just the reputation gain). " +
|
||||
"This Source-File also increases the player's company salary and reputation gain multipliers by:<br><br>" +
|
||||
"Level 1: 24%<br>" +
|
||||
"Level 2: 36%<br>" +
|
||||
"Level 3: 42%");
|
||||
"Level 1: 32%<br>" +
|
||||
"Level 2: 48%<br>" +
|
||||
"Level 3: 56%");
|
||||
BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.",
|
||||
"To iterate is human, to recurse divine.<br><br>" +
|
||||
"Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give your Souce-File 12, or " +
|
||||
@@ -245,9 +264,9 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
}
|
||||
|
||||
switch (p.bitNodeN) {
|
||||
case 1: //Source Genesis (every multiplier is 1)
|
||||
case 1: // Source Genesis (every multiplier is 1)
|
||||
break;
|
||||
case 2: //Rise of the Underworld
|
||||
case 2: // Rise of the Underworld
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.8;
|
||||
BitNodeMultipliers.ServerGrowthRate = 0.8;
|
||||
BitNodeMultipliers.ServerMaxMoney = 0.2;
|
||||
@@ -257,7 +276,8 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.FactionWorkRepGain = 0.5;
|
||||
BitNodeMultipliers.FactionPassiveRepGain = 0;
|
||||
break;
|
||||
case 3: //Corporatocracy
|
||||
case 3: // Corporatocracy
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.8;
|
||||
BitNodeMultipliers.RepToDonateToFaction = 0.5;
|
||||
BitNodeMultipliers.AugmentationRepCost = 3;
|
||||
BitNodeMultipliers.AugmentationMoneyCost = 3;
|
||||
@@ -268,8 +288,10 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.CompanyWorkMoney = 0.25;
|
||||
BitNodeMultipliers.CrimeMoney = 0.25;
|
||||
BitNodeMultipliers.HacknetNodeMoney = 0.25;
|
||||
BitNodeMultipliers.HomeComputerRamCost = 1.5;
|
||||
BitNodeMultipliers.PurchasedServerCost = 2;
|
||||
break;
|
||||
case 4: //The Singularity
|
||||
case 4: // The Singularity
|
||||
BitNodeMultipliers.ServerMaxMoney = 0.15;
|
||||
BitNodeMultipliers.ServerStartingMoney = 0.75;
|
||||
BitNodeMultipliers.ScriptHackMoney = 0.2;
|
||||
@@ -283,7 +305,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.CrimeExpGain = 0.5;
|
||||
BitNodeMultipliers.FactionWorkRepGain = 0.75;
|
||||
break;
|
||||
case 5: //Artificial intelligence
|
||||
case 5: // Artificial intelligence
|
||||
BitNodeMultipliers.ServerMaxMoney = 2;
|
||||
BitNodeMultipliers.ServerStartingSecurity = 2;
|
||||
BitNodeMultipliers.ServerStartingMoney = 0.5;
|
||||
@@ -296,7 +318,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.HackExpGain = 0.5;
|
||||
BitNodeMultipliers.CorporationValuation = 0.5;
|
||||
break;
|
||||
case 6: //Bladeburner
|
||||
case 6: // Bladeburner
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.35;
|
||||
BitNodeMultipliers.ServerMaxMoney = 0.4;
|
||||
BitNodeMultipliers.ServerStartingMoney = 0.5;
|
||||
@@ -311,7 +333,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.HackExpGain = 0.25;
|
||||
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
||||
break;
|
||||
case 7: //Bladeburner 2079
|
||||
case 7: // Bladeburner 2079
|
||||
BitNodeMultipliers.BladeburnerRank = 0.6;
|
||||
BitNodeMultipliers.BladeburnerSkillCost = 2;
|
||||
BitNodeMultipliers.AugmentationMoneyCost = 3;
|
||||
@@ -331,7 +353,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.FourSigmaMarketDataApiCost = 2;
|
||||
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
||||
break;
|
||||
case 8: //Ghost of Wall Street
|
||||
case 8: // Ghost of Wall Street
|
||||
BitNodeMultipliers.ScriptHackMoney = 0;
|
||||
BitNodeMultipliers.ManualHackMoney = 0;
|
||||
BitNodeMultipliers.CompanyWorkMoney = 0;
|
||||
@@ -342,6 +364,27 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.CorporationValuation = 0;
|
||||
BitNodeMultipliers.CodingContractMoney = 0;
|
||||
break;
|
||||
case 9: // Hacktocracy
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.4;
|
||||
BitNodeMultipliers.StrengthLevelMultiplier = 0.45;
|
||||
BitNodeMultipliers.DefenseLevelMultiplier = 0.45;
|
||||
BitNodeMultipliers.DexterityLevelMultiplier = 0.45;
|
||||
BitNodeMultipliers.AgilityLevelMultiplier = 0.45;
|
||||
BitNodeMultipliers.CharismaLevelMultiplier = 0.45;
|
||||
BitNodeMultipliers.PurchasedServerLimit = 0;
|
||||
BitNodeMultipliers.HomeComputerRamCost = 5;
|
||||
BitNodeMultipliers.CrimeMoney = 0.5;
|
||||
BitNodeMultipliers.ScriptHackMoney = 0.1;
|
||||
BitNodeMultipliers.HackExpGain = 0.05;
|
||||
BitNodeMultipliers.ServerStartingMoney = 0.1;
|
||||
BitNodeMultipliers.ServerMaxMoney = 0.1;
|
||||
BitNodeMultipliers.ServerStartingSecurity = 2.5;
|
||||
BitNodeMultipliers.CorporationValuation = 0.5;
|
||||
BitNodeMultipliers.FourSigmaMarketDataCost = 5;
|
||||
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
|
||||
BitNodeMultipliers.BladeburnerRank = 0.9;
|
||||
BitNodeMultipliers.BladeburnerSkillCost = 1.2;
|
||||
break;
|
||||
case 10: // Digital Carbon
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.2;
|
||||
BitNodeMultipliers.StrengthLevelMultiplier = 0.4;
|
||||
@@ -363,11 +406,14 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.PurchasedServerCost = 5;
|
||||
BitNodeMultipliers.PurchasedServerLimit = 0.6;
|
||||
BitNodeMultipliers.PurchasedServerMaxRam = 0.5;
|
||||
BitNodeMultipliers.BladeburnerRank = 0.8;
|
||||
break;
|
||||
case 11: //The Big Crash
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.5;
|
||||
BitNodeMultipliers.HackExpGain = 0.5;
|
||||
BitNodeMultipliers.ServerMaxMoney = 0.1;
|
||||
BitNodeMultipliers.ServerStartingMoney = 0.1;
|
||||
BitNodeMultipliers.ServerGrowthRate = 0.5;
|
||||
BitNodeMultipliers.ServerGrowthRate = 0.2;
|
||||
BitNodeMultipliers.ServerWeakenRate = 2;
|
||||
BitNodeMultipliers.CrimeMoney = 3;
|
||||
BitNodeMultipliers.CompanyWorkMoney = 0.5;
|
||||
@@ -375,8 +421,8 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.AugmentationMoneyCost = 2;
|
||||
BitNodeMultipliers.InfiltrationMoney = 2.5;
|
||||
BitNodeMultipliers.InfiltrationRep = 2.5;
|
||||
BitNodeMultipliers.CorporationValuation = 0.01;
|
||||
BitNodeMultipliers.CodingContractMoney = 0.5;
|
||||
BitNodeMultipliers.CorporationValuation = 0.1;
|
||||
BitNodeMultipliers.CodingContractMoney = 0.25;
|
||||
BitNodeMultipliers.FourSigmaMarketDataCost = 4;
|
||||
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
|
||||
break;
|
||||
|
||||
@@ -120,7 +120,8 @@ interface IBitNodeMultipliers {
|
||||
HackingLevelMultiplier: number;
|
||||
|
||||
/**
|
||||
* Influences how much money each Hacknet node can generate.
|
||||
* Influences how much money is produced by Hacknet Nodes.
|
||||
* Influeces the hash rate of Hacknet Servers (unlocked in BitNode-9)
|
||||
*/
|
||||
HacknetNodeMoney: number;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,59 +0,0 @@
|
||||
import {Player} from "./Player";
|
||||
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
|
||||
function CharacterOverview() {
|
||||
this.hp = document.getElementById("character-hp-text");
|
||||
this.money = document.getElementById("character-money-text");
|
||||
this.hack = document.getElementById("character-hack-text");
|
||||
this.str = document.getElementById("character-str-text");
|
||||
this.def = document.getElementById("character-def-text");
|
||||
this.dex = document.getElementById("character-dex-text");
|
||||
this.agi = document.getElementById("character-agi-text");
|
||||
this.cha = document.getElementById("character-cha-text");
|
||||
this.int = document.getElementById("character-int-text");
|
||||
this.intWrapper = document.getElementById("character-int-wrapper");
|
||||
this.repaintElem = document.getElementById("character-overview-text");
|
||||
}
|
||||
|
||||
CharacterOverview.prototype.repaint = function() {
|
||||
// this is an arbitrary function we can call to trigger a repaint.
|
||||
this.repaintElem.getClientRects();
|
||||
}
|
||||
|
||||
CharacterOverview.prototype.update = function() {
|
||||
if (Player.hp == null) {Player.hp = Player.max_hp;}
|
||||
|
||||
const replaceAndChanged = function(elem, text) {
|
||||
if(elem.textContent === text) {
|
||||
return false;
|
||||
}
|
||||
elem.textContent = text;
|
||||
return true;
|
||||
}
|
||||
|
||||
let changed = false;
|
||||
changed = replaceAndChanged(this.hp, Player.hp + " / " + Player.max_hp) || 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;
|
||||
changed = replaceAndChanged(this.dex, (Player.dexterity).toLocaleString()) || changed;
|
||||
changed = replaceAndChanged(this.agi, (Player.agility).toLocaleString()) || changed;
|
||||
changed = replaceAndChanged(this.cha, (Player.charisma).toLocaleString()) || changed;
|
||||
changed = replaceAndChanged(this.int, (Player.intelligence).toLocaleString()) || changed;
|
||||
|
||||
// handle int appearing
|
||||
const int = this.intWrapper;
|
||||
const old = int.style.display;
|
||||
const now = Player.intelligence >= 1 ? "" : "none";
|
||||
if(old !== now) {
|
||||
int.style.display = now;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// recalculate box size if something changed
|
||||
if(changed) this.repaint();
|
||||
}
|
||||
|
||||
export {CharacterOverview};
|
||||
@@ -1,29 +1,35 @@
|
||||
import {Engine} from "./engine";
|
||||
import { setTimeoutRef } from "./utils/SetTimeoutRef";
|
||||
|
||||
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
|
||||
import {isString} from "../utils/helpers/isString";
|
||||
import { Engine } from "./engine";
|
||||
import { setTimeoutRef } from "./utils/SetTimeoutRef";
|
||||
|
||||
var cinematicTextFlag = false;
|
||||
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
import { createElement } from "../utils/uiHelpers/createElement";
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { isString } from "../utils/helpers/isString";
|
||||
|
||||
//Lines must be an array of strings
|
||||
function writeCinematicText(lines) {
|
||||
export let cinematicTextFlag = false;
|
||||
|
||||
/**
|
||||
* Print a message using a hacking-style "typing" effect.
|
||||
* Note that this clears the UI so that the text from this is the only thing visible.
|
||||
*
|
||||
* @param lines {string[]} Array of strings to print, where each element is a separate line
|
||||
*/
|
||||
export function writeCinematicText(lines) {
|
||||
cinematicTextFlag = true;
|
||||
|
||||
if (lines.constructor !== Array) {
|
||||
throw new Error("Invalid non-array argument passed into writeCinematicText()");
|
||||
}
|
||||
|
||||
//We'll reuse the 'Red Pill' content
|
||||
// Reuse the 'Red Pill' content
|
||||
Engine.loadCinematicTextContent();
|
||||
var container = document.getElementById("cinematic-text-container");
|
||||
const container = document.getElementById("cinematic-text-container");
|
||||
container.style.width = "75%";
|
||||
if (container == null) {throw new Error("Could not find cinematic-text-container for writeCinematicText()");}
|
||||
removeChildrenFromElement(container);
|
||||
|
||||
for (var i = 0; i < lines.length; ++i) {
|
||||
for (let i = 0; i < lines.length; ++i) {
|
||||
if (!isString(lines[i])) {
|
||||
throw new Error("Invalid non-string element in 'lines' argument. writeCinematicText() failed");
|
||||
}
|
||||
@@ -45,11 +51,11 @@ function writeCinematicTextRecurse(lines, lineNumber=0) {
|
||||
|
||||
function writeCinematicTextLine(line) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var container = document.getElementById("cinematic-text-container");
|
||||
var pElem = document.createElement("p");
|
||||
const container = document.getElementById("cinematic-text-container");
|
||||
const pElem = document.createElement("p");
|
||||
container.appendChild(pElem);
|
||||
|
||||
var promise = writeCinematicTextLetter(pElem, line, 0);
|
||||
const promise = writeCinematicTextLetter(pElem, line, 0);
|
||||
promise.then(function(res) {
|
||||
resolve(res);
|
||||
}, function(e) {
|
||||
@@ -61,14 +67,15 @@ function writeCinematicTextLine(line) {
|
||||
function writeCinematicTextLetter(pElem, line, i=0) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
setTimeoutRef(function() {
|
||||
const textToShow = line.substring(0, i);
|
||||
|
||||
if (i >= line.length) {
|
||||
var textToShow = line.substring(0, i);
|
||||
pElem.innerHTML = textToShow;
|
||||
return resolve(true);
|
||||
}
|
||||
var textToShow = line.substring(0, i);
|
||||
|
||||
pElem.innerHTML = textToShow + "<span class='typed-cursor'> █ </span>";
|
||||
var promise = writeCinematicTextLetter(pElem, line, i+1);
|
||||
const promise = writeCinematicTextLetter(pElem, line, i+1);
|
||||
promise.then(function(res) {
|
||||
resolve(res);
|
||||
}, function(e) {
|
||||
@@ -96,5 +103,3 @@ function cinematicTextEnd() {
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
export {cinematicTextFlag, writeCinematicText};
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { CodingContract,
|
||||
CodingContractRewardType,
|
||||
CodingContractTypes } from "./CodingContracts";
|
||||
import { Factions } from "./Faction/Factions";
|
||||
import { Player } from "./Player";
|
||||
import { GetServerByHostname,
|
||||
AllServers } from "./Server";
|
||||
import {
|
||||
CodingContract,
|
||||
CodingContractRewardType,
|
||||
CodingContractTypes
|
||||
} from "./CodingContracts";
|
||||
import { Factions } from "./Faction/Factions";
|
||||
import { Player } from "./Player";
|
||||
import { AllServers } from "./Server/AllServers";
|
||||
import { GetServerByHostname } from "./Server/ServerHelpers";
|
||||
|
||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
|
||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
|
||||
export function generateRandomContract() {
|
||||
// First select a random problem type
|
||||
@@ -127,14 +130,15 @@ function getRandomReward() {
|
||||
});
|
||||
|
||||
switch (reward.type) {
|
||||
case CodingContractRewardType.FactionReputation:
|
||||
case CodingContractRewardType.FactionReputation: {
|
||||
// Get a random faction that player is a part of. That
|
||||
// faction must allow hacking contracts
|
||||
var numFactions = factionsThatAllowHacking.length;
|
||||
var randFaction = factionsThatAllowHacking[getRandomInt(0, numFactions - 1)];
|
||||
reward.name = randFaction;
|
||||
break;
|
||||
case CodingContractRewardType.CompanyReputation:
|
||||
}
|
||||
case CodingContractRewardType.CompanyReputation: {
|
||||
const allJobs = Object.keys(Player.jobs);
|
||||
if (allJobs.length > 0) {
|
||||
reward.name = allJobs[getRandomInt(0, allJobs.length - 1)];
|
||||
@@ -142,6 +146,7 @@ function getRandomReward() {
|
||||
reward.type = CodingContractRewardType.Money;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import { codingContractTypesMetadata,
|
||||
DescriptionFunc,
|
||||
GeneratorFunc,
|
||||
SolverFunc } from "./data/codingcontracttypes";
|
||||
import {
|
||||
codingContractTypesMetadata,
|
||||
DescriptionFunc,
|
||||
GeneratorFunc,
|
||||
SolverFunc
|
||||
} from "./data/codingcontracttypes";
|
||||
|
||||
import { IMap } from "./types";
|
||||
import { IMap } from "./types";
|
||||
|
||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
||||
import {
|
||||
Generic_fromJSON,
|
||||
Generic_toJSON,
|
||||
Reviver
|
||||
} from "../utils/JSONReviver";
|
||||
import { KEY } from "../utils/helpers/keyCodes";
|
||||
import { createElement } from "../utils/uiHelpers/createElement";
|
||||
import { createPopup } from "../utils/uiHelpers/createPopup";
|
||||
@@ -13,6 +19,7 @@ import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||
|
||||
|
||||
|
||||
|
||||
/* tslint:disable:no-magic-numbers completed-docs max-classes-per-file no-console */
|
||||
|
||||
/* Represents different types of problems that a Coding Contract can have */
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
|
||||
import { CompanyPosition } from "./CompanyPosition";
|
||||
import * as posNames from "./data/companypositionnames";
|
||||
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { IMap } from "../types";
|
||||
|
||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
|
||||
|
||||
export interface IConstructorParams {
|
||||
name: string;
|
||||
info: string;
|
||||
@@ -93,6 +96,43 @@ export class Company {
|
||||
}
|
||||
}
|
||||
|
||||
hasAgentPositions(): boolean {
|
||||
return (this.companyPositions[posNames.AgentCompanyPositions[0]] != null);
|
||||
}
|
||||
|
||||
hasBusinessConsultantPositions(): boolean {
|
||||
return (this.companyPositions[posNames.BusinessConsultantCompanyPositions[0]] != null);
|
||||
}
|
||||
|
||||
hasBusinessPositions(): boolean {
|
||||
return (this.companyPositions[posNames.BusinessCompanyPositions[0]] != null);
|
||||
}
|
||||
|
||||
hasEmployeePositions(): boolean {
|
||||
return (this.companyPositions[posNames.MiscCompanyPositions[1]] != null);
|
||||
}
|
||||
|
||||
hasITPositions(): boolean {
|
||||
return (this.companyPositions[posNames.ITCompanyPositions[0]] != null);
|
||||
}
|
||||
|
||||
hasSecurityPositions(): boolean {
|
||||
return (this.companyPositions[posNames.SecurityCompanyPositions[2]] != null);
|
||||
}
|
||||
|
||||
hasSoftwareConsultantPositions(): boolean {
|
||||
return (this.companyPositions[posNames.SoftwareConsultantCompanyPositions[0]] != null);
|
||||
}
|
||||
|
||||
hasSoftwarePositions(): boolean {
|
||||
return (this.companyPositions[posNames.SoftwareCompanyPositions[0]] != null);
|
||||
}
|
||||
|
||||
hasWaiterPositions(): boolean {
|
||||
return (this.companyPositions[posNames.MiscCompanyPositions[0]] != null);
|
||||
}
|
||||
|
||||
|
||||
gainFavor(): void {
|
||||
if (this.favor == null) { this.favor = 0; }
|
||||
if (this.rolloverRep == null) { this.rolloverRep = 0; }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import * as names from "./data/CompanyPositionNames";
|
||||
import * as names from "./data/companypositionnames";
|
||||
|
||||
/* tslint:disable:completed-docs */
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { CompanyPosition } from "./CompanyPosition";
|
||||
import { CompanyPositions } from "./CompanyPositions";
|
||||
|
||||
export function getNextCompanyPosition(currPos: CompanyPosition | null): CompanyPosition | null {
|
||||
export function getNextCompanyPositionHelper(currPos: CompanyPosition | null): CompanyPosition | null {
|
||||
if (currPos == null) { return null; }
|
||||
|
||||
const nextPosName: string | null = currPos.nextPosition;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { IConstructorParams } from "../Company";
|
||||
import { Locations } from "../../Locations";
|
||||
import * as posNames from "./CompanyPositionNames";
|
||||
import { IMap } from "../../types";
|
||||
import * as posNames from "./companypositionnames";
|
||||
import { IConstructorParams } from "../Company";
|
||||
|
||||
import { IMap } from "../../types";
|
||||
import { LocationName } from "../../Locations/data/LocationNames";
|
||||
|
||||
// Create Objects containing Company Positions by category
|
||||
// Will help in metadata construction later
|
||||
@@ -89,7 +90,7 @@ CEOOnly[posNames.BusinessCompanyPositions[5]] = true;
|
||||
// Metadata
|
||||
export const companiesMetadata: IConstructorParams[] = [
|
||||
{
|
||||
name: Locations.AevumECorp,
|
||||
name: LocationName.AevumECorp,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -101,7 +102,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 249,
|
||||
},
|
||||
{
|
||||
name: Locations.Sector12MegaCorp,
|
||||
name: LocationName.Sector12MegaCorp,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -113,7 +114,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 249,
|
||||
},
|
||||
{
|
||||
name: Locations.AevumBachmanAndAssociates,
|
||||
name: LocationName.AevumBachmanAndAssociates,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -125,7 +126,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 224,
|
||||
},
|
||||
{
|
||||
name: Locations.Sector12BladeIndustries,
|
||||
name: LocationName.Sector12BladeIndustries,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -137,7 +138,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 224,
|
||||
},
|
||||
{
|
||||
name: Locations.VolhavenNWO,
|
||||
name: LocationName.VolhavenNWO,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -149,7 +150,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 249,
|
||||
},
|
||||
{
|
||||
name: Locations.AevumClarkeIncorporated,
|
||||
name: LocationName.AevumClarkeIncorporated,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -161,7 +162,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 224,
|
||||
},
|
||||
{
|
||||
name: Locations.VolhavenOmniTekIncorporated,
|
||||
name: LocationName.VolhavenOmniTekIncorporated,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -173,7 +174,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 224,
|
||||
},
|
||||
{
|
||||
name: Locations.Sector12FourSigma,
|
||||
name: LocationName.Sector12FourSigma,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -185,7 +186,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 224,
|
||||
},
|
||||
{
|
||||
name: Locations.ChongqingKuaiGongInternational,
|
||||
name: LocationName.ChongqingKuaiGongInternational,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -197,7 +198,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 224,
|
||||
},
|
||||
{
|
||||
name: Locations.AevumFulcrumTechnologies,
|
||||
name: LocationName.AevumFulcrumTechnologies,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -208,7 +209,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 224,
|
||||
},
|
||||
{
|
||||
name: Locations.IshimaStormTechnologies,
|
||||
name: LocationName.IshimaStormTechnologies,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -220,7 +221,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
{
|
||||
name: Locations.NewTokyoDefComm,
|
||||
name: LocationName.NewTokyoDefComm,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
CEOOnly,
|
||||
@@ -232,7 +233,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
{
|
||||
name: Locations.VolhavenHeliosLabs,
|
||||
name: LocationName.VolhavenHeliosLabs,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
CEOOnly,
|
||||
@@ -244,7 +245,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
{
|
||||
name: Locations.NewTokyoVitaLife,
|
||||
name: LocationName.NewTokyoVitaLife,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -256,7 +257,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
{
|
||||
name: Locations.Sector12IcarusMicrosystems,
|
||||
name: LocationName.Sector12IcarusMicrosystems,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -268,7 +269,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
{
|
||||
name: Locations.Sector12UniversalEnergy,
|
||||
name: LocationName.Sector12UniversalEnergy,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -280,7 +281,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
{
|
||||
name: Locations.AevumGalacticCybersystems,
|
||||
name: LocationName.AevumGalacticCybersystems,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -292,7 +293,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
{
|
||||
name: Locations.AevumAeroCorp,
|
||||
name: LocationName.AevumAeroCorp,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
CEOOnly,
|
||||
@@ -305,7 +306,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
{
|
||||
name: Locations.VolhavenOmniaCybersystems,
|
||||
name: LocationName.VolhavenOmniaCybersystems,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
CEOOnly,
|
||||
@@ -318,7 +319,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
{
|
||||
name: Locations.ChongqingSolarisSpaceSystems,
|
||||
name: LocationName.ChongqingSolarisSpaceSystems,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
CEOOnly,
|
||||
@@ -331,7 +332,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
{
|
||||
name: Locations.Sector12DeltaOne,
|
||||
name: LocationName.Sector12DeltaOne,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
CEOOnly,
|
||||
@@ -344,7 +345,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
{
|
||||
name: Locations.NewTokyoGlobalPharmaceuticals,
|
||||
name: LocationName.NewTokyoGlobalPharmaceuticals,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -357,7 +358,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 224,
|
||||
},
|
||||
{
|
||||
name: Locations.IshimaNovaMedical,
|
||||
name: LocationName.IshimaNovaMedical,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -370,7 +371,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
{
|
||||
name: Locations.Sector12CIA,
|
||||
name: LocationName.Sector12CIA,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
SoftwarePositionsUpToHeadOfEngineering,
|
||||
@@ -385,7 +386,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 149,
|
||||
},
|
||||
{
|
||||
name: Locations.Sector12NSA,
|
||||
name: LocationName.Sector12NSA,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
SoftwarePositionsUpToHeadOfEngineering,
|
||||
@@ -400,7 +401,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 149,
|
||||
},
|
||||
{
|
||||
name: Locations.AevumWatchdogSecurity,
|
||||
name: LocationName.AevumWatchdogSecurity,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
SoftwarePositionsUpToHeadOfEngineering,
|
||||
@@ -415,7 +416,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 124,
|
||||
},
|
||||
{
|
||||
name: Locations.VolhavenLexoCorp,
|
||||
name: LocationName.VolhavenLexoCorp,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -428,7 +429,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 99,
|
||||
},
|
||||
{
|
||||
name: Locations.AevumRhoConstruction,
|
||||
name: LocationName.AevumRhoConstruction,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
SoftwarePositionsUpToLeadDeveloper,
|
||||
@@ -439,7 +440,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 49,
|
||||
},
|
||||
{
|
||||
name: Locations.Sector12AlphaEnterprises,
|
||||
name: LocationName.Sector12AlphaEnterprises,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
SoftwarePositionsUpToLeadDeveloper,
|
||||
@@ -451,7 +452,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 99,
|
||||
},
|
||||
{
|
||||
name: Locations.AevumPolice,
|
||||
name: LocationName.AevumPolice,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllSecurityPositions,
|
||||
@@ -462,7 +463,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 99,
|
||||
},
|
||||
{
|
||||
name: Locations.VolhavenSysCoreSecurities,
|
||||
name: LocationName.VolhavenSysCoreSecurities,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions
|
||||
@@ -472,7 +473,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 124,
|
||||
},
|
||||
{
|
||||
name: Locations.VolhavenCompuTek,
|
||||
name: LocationName.VolhavenCompuTek,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions
|
||||
@@ -482,7 +483,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 74,
|
||||
},
|
||||
{
|
||||
name: Locations.AevumNetLinkTechnologies,
|
||||
name: LocationName.AevumNetLinkTechnologies,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions
|
||||
@@ -492,7 +493,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 99,
|
||||
},
|
||||
{
|
||||
name: Locations.Sector12CarmichaelSecurity,
|
||||
name: LocationName.Sector12CarmichaelSecurity,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllTechnologyPositions,
|
||||
@@ -505,7 +506,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 74,
|
||||
},
|
||||
{
|
||||
name: Locations.Sector12FoodNStuff,
|
||||
name: LocationName.Sector12FoodNStuff,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
EmployeeOnly, PartTimeEmployeeOnly
|
||||
@@ -515,7 +516,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 0,
|
||||
},
|
||||
{
|
||||
name: Locations.Sector12JoesGuns,
|
||||
name: LocationName.Sector12JoesGuns,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
EmployeeOnly, PartTimeEmployeeOnly
|
||||
@@ -525,7 +526,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 0,
|
||||
},
|
||||
{
|
||||
name: Locations.IshimaOmegaSoftware,
|
||||
name: LocationName.IshimaOmegaSoftware,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
AllSoftwarePositions,
|
||||
@@ -537,7 +538,7 @@ export const companiesMetadata: IConstructorParams[] = [
|
||||
jobStatReqOffset: 49,
|
||||
},
|
||||
{
|
||||
name: Locations.NewTokyoNoodleBar,
|
||||
name: LocationName.NewTokyoNoodleBar,
|
||||
info: "",
|
||||
companyPositions: Object.assign({},
|
||||
WaiterOnly, PartTimeWaiterOnly
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Metadata used for constructing Company Positions
|
||||
import { IConstructorParams } from "../CompanyPosition";
|
||||
import * as posNames from "./CompanyPositionNames";
|
||||
import * as posNames from "./companypositionnames";
|
||||
|
||||
export const companyPositionMetadata: IConstructorParams[] = [
|
||||
{
|
||||
|
||||
247
src/Constants.ts
247
src/Constants.ts
@@ -1,109 +1,100 @@
|
||||
import {IMap} from "./types";
|
||||
/**
|
||||
* Generic Game Constants
|
||||
*
|
||||
* Constants for specific mechanics or features will NOT be here.
|
||||
*/
|
||||
import { IMap } from "./types";
|
||||
|
||||
export let CONSTANTS: IMap<any> = {
|
||||
Version: "0.44.1",
|
||||
Version: "0.46.2",
|
||||
|
||||
//Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
|
||||
//and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
|
||||
//the player will have this level assuming no multipliers. Multipliers can cause skills to go above this.
|
||||
/** 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
|
||||
// Milliseconds per game cycle
|
||||
MilliPerCycle: 200,
|
||||
|
||||
//How much reputation is needed to join a megacorporation's faction
|
||||
// How much reputation is needed to join a megacorporation's faction
|
||||
CorpFactionRepRequirement: 200e3,
|
||||
|
||||
/* Base costs */
|
||||
// Base RAM costs
|
||||
BaseCostFor1GBOfRamHome: 32000,
|
||||
BaseCostFor1GBOfRamServer: 55000, //1 GB of RAM
|
||||
BaseCostFor1GBOfRamHacknetNode: 30000,
|
||||
|
||||
// Cost to travel to another city
|
||||
TravelCost: 200e3,
|
||||
|
||||
BaseCostForHacknetNode: 1000,
|
||||
BaseCostForHacknetNodeCore: 500000,
|
||||
|
||||
/* Hacknet Node constants */
|
||||
HacknetNodeMoneyGainPerLevel: 1.6,
|
||||
HacknetNodePurchaseNextMult: 1.85, //Multiplier when purchasing an additional hacknet node
|
||||
HacknetNodeUpgradeLevelMult: 1.04, //Multiplier for cost when upgrading level
|
||||
HacknetNodeUpgradeRamMult: 1.28, //Multiplier for cost when upgrading RAM
|
||||
HacknetNodeUpgradeCoreMult: 1.48, //Multiplier for cost when buying another core
|
||||
|
||||
HacknetNodeMaxLevel: 200,
|
||||
HacknetNodeMaxRam: 64,
|
||||
HacknetNodeMaxCores: 16,
|
||||
|
||||
/* Faction and Company favor */
|
||||
BaseFavorToDonate: 150,
|
||||
DonateMoneyToRepDivisor: 1e6,
|
||||
// Faction and Company favor-related things
|
||||
BaseFavorToDonate: 150,
|
||||
DonateMoneyToRepDivisor: 1e6,
|
||||
FactionReputationToFavorBase: 500,
|
||||
FactionReputationToFavorMult: 1.02,
|
||||
CompanyReputationToFavorBase: 500,
|
||||
CompanyReputationToFavorMult: 1.02,
|
||||
|
||||
/* Augmentation */
|
||||
//NeuroFlux Governor cost multiplier as you level up
|
||||
// NeuroFlux Governor Augmentation cost multiplier
|
||||
NeuroFluxGovernorLevelMult: 1.14,
|
||||
|
||||
/* Netscript Constants */
|
||||
//RAM Costs for different commands
|
||||
ScriptBaseRamCost: 1.6,
|
||||
ScriptDomRamCost: 25,
|
||||
ScriptWhileRamCost: 0,
|
||||
ScriptForRamCost: 0,
|
||||
ScriptIfRamCost: 0,
|
||||
ScriptHackRamCost: 0.1,
|
||||
ScriptHackAnalyzeRamCost: 1,
|
||||
ScriptGrowRamCost: 0.15,
|
||||
ScriptGrowthAnalyzeRamCost: 1,
|
||||
ScriptWeakenRamCost: 0.15,
|
||||
ScriptScanRamCost: 0.2,
|
||||
ScriptPortProgramRamCost: 0.05,
|
||||
ScriptRunRamCost: 1.0,
|
||||
ScriptExecRamCost: 1.3,
|
||||
ScriptSpawnRamCost: 2.0,
|
||||
ScriptScpRamCost: 0.6,
|
||||
ScriptKillRamCost: 0.5, //Kill and killall
|
||||
ScriptHasRootAccessRamCost: 0.05,
|
||||
ScriptGetHostnameRamCost: 0.05, //getHostname() and getIp()
|
||||
ScriptGetHackingLevelRamCost: 0.05, //getHackingLevel()
|
||||
ScriptGetMultipliersRamCost: 4.0, //getHackingMultipliers() and getBitNodeMultipliers()
|
||||
ScriptGetServerRamCost: 0.1,
|
||||
ScriptFileExistsRamCost: 0.1,
|
||||
ScriptIsRunningRamCost: 0.1,
|
||||
ScriptHacknetNodesRamCost: 4.0, //Base cost for accessing Hacknet Node API
|
||||
ScriptHNUpgLevelRamCost: 0.4,
|
||||
ScriptHNUpgRamRamCost: 0.6,
|
||||
ScriptHNUpgCoreRamCost: 0.8,
|
||||
ScriptGetStockRamCost: 2.0,
|
||||
ScriptBuySellStockRamCost: 2.5,
|
||||
// RAM Costs for Netscript functions
|
||||
ScriptBaseRamCost: 1.6,
|
||||
ScriptDomRamCost: 25,
|
||||
ScriptWhileRamCost: 0,
|
||||
ScriptForRamCost: 0,
|
||||
ScriptIfRamCost: 0,
|
||||
ScriptHackRamCost: 0.1,
|
||||
ScriptHackAnalyzeRamCost: 1,
|
||||
ScriptGrowRamCost: 0.15,
|
||||
ScriptGrowthAnalyzeRamCost: 1,
|
||||
ScriptWeakenRamCost: 0.15,
|
||||
ScriptScanRamCost: 0.2,
|
||||
ScriptPortProgramRamCost: 0.05,
|
||||
ScriptRunRamCost: 1.0,
|
||||
ScriptExecRamCost: 1.3,
|
||||
ScriptSpawnRamCost: 2.0,
|
||||
ScriptScpRamCost: 0.6,
|
||||
ScriptKillRamCost: 0.5,
|
||||
ScriptHasRootAccessRamCost: 0.05,
|
||||
ScriptGetHostnameRamCost: 0.05,
|
||||
ScriptGetHackingLevelRamCost: 0.05,
|
||||
ScriptGetMultipliersRamCost: 4.0,
|
||||
ScriptGetServerRamCost: 0.1,
|
||||
ScriptFileExistsRamCost: 0.1,
|
||||
ScriptIsRunningRamCost: 0.1,
|
||||
ScriptHacknetNodesRamCost: 4.0,
|
||||
ScriptHNUpgLevelRamCost: 0.4,
|
||||
ScriptHNUpgRamRamCost: 0.6,
|
||||
ScriptHNUpgCoreRamCost: 0.8,
|
||||
ScriptGetStockRamCost: 2.0,
|
||||
ScriptBuySellStockRamCost: 2.5,
|
||||
ScriptGetPurchaseServerRamCost: 0.25,
|
||||
ScriptPurchaseServerRamCost: 2.25,
|
||||
ScriptGetPurchasedServerLimit: 0.05,
|
||||
ScriptPurchaseServerRamCost: 2.25,
|
||||
ScriptGetPurchasedServerLimit: 0.05,
|
||||
ScriptGetPurchasedServerMaxRam: 0.05,
|
||||
ScriptRoundRamCost: 0.05,
|
||||
ScriptReadWriteRamCost: 1.0,
|
||||
ScriptArbScriptRamCost: 1.0, //Functions that apply to all scripts regardless of args
|
||||
ScriptGetScriptRamCost: 0.1,
|
||||
ScriptGetHackTimeRamCost: 0.05,
|
||||
ScriptGetFavorToDonate: 0.10,
|
||||
ScriptCodingContractBaseRamCost:10,
|
||||
ScriptRoundRamCost: 0.05,
|
||||
ScriptReadWriteRamCost: 1.0,
|
||||
ScriptArbScriptRamCost: 1.0,
|
||||
ScriptGetScriptRamCost: 0.1,
|
||||
ScriptGetHackTimeRamCost: 0.05,
|
||||
ScriptGetFavorToDonate: 0.10,
|
||||
ScriptCodingContractBaseRamCost: 10,
|
||||
ScriptSleeveBaseRamCost: 4,
|
||||
|
||||
ScriptSingularityFn1RamCost: 1,
|
||||
ScriptSingularityFn2RamCost: 2,
|
||||
ScriptSingularityFn3RamCost: 3,
|
||||
ScriptSingularityFn1RamCost: 1,
|
||||
ScriptSingularityFn2RamCost: 2,
|
||||
ScriptSingularityFn3RamCost: 3,
|
||||
|
||||
ScriptSingularityFnRamMult: 2, // Multiplier for RAM cost outside of BN-4
|
||||
ScriptSingularityFnRamMult: 2, // Multiplier for RAM cost outside of BN-4
|
||||
|
||||
ScriptGangApiBaseRamCost: 4,
|
||||
ScriptGangApiBaseRamCost: 4,
|
||||
|
||||
ScriptBladeburnerApiBaseRamCost: 4,
|
||||
ScriptBladeburnerApiBaseRamCost: 4,
|
||||
|
||||
NumNetscriptPorts: 20,
|
||||
NumNetscriptPorts: 20,
|
||||
|
||||
//Server constants
|
||||
// Server-related constants
|
||||
HomeComputerMaxRam: 1073741824, // 2 ^ 30
|
||||
ServerBaseGrowthRate: 1.03, // Unadjusted Growth rate
|
||||
ServerMaxGrowthRate: 1.0035, // Maximum possible growth rate (max rate accounting for server security)
|
||||
@@ -111,48 +102,50 @@ export let CONSTANTS: IMap<any> = {
|
||||
ServerWeakenAmount: 0.05, // Amount by which server's security decreases when weakened
|
||||
|
||||
PurchasedServerLimit: 25,
|
||||
PurchasedServerMaxRam: 1048576, //2^20
|
||||
PurchasedServerMaxRam: 1048576, // 2^20
|
||||
|
||||
//Augmentation Constants
|
||||
AugmentationCostMultiplier: 5, //Used for balancing costs without having to readjust every Augmentation cost
|
||||
AugmentationRepMultiplier: 2.5, //Used for balancing rep cost without having to readjust every value
|
||||
MultipleAugMultiplier: 1.9,
|
||||
// Augmentation Constants
|
||||
AugmentationCostMultiplier: 5, // Used for balancing costs without having to readjust every Augmentation cost
|
||||
AugmentationRepMultiplier: 2.5, // Used for balancing rep cost without having to readjust every value
|
||||
MultipleAugMultiplier: 1.9,
|
||||
|
||||
//How much a TOR router costs
|
||||
TorRouterCost: 200000,
|
||||
// TOR Router
|
||||
TorRouterCost: 200e3,
|
||||
|
||||
//Infiltration constants
|
||||
// Infiltration
|
||||
InfiltrationBribeBaseAmount: 100e3, //Amount per clearance level
|
||||
InfiltrationMoneyValue: 5e3, //Convert "secret" value to money
|
||||
InfiltrationMoneyValue: 5e3, //Convert "secret" value to money
|
||||
InfiltrationRepValue: 1.4, //Convert "secret" value to faction reputation
|
||||
InfiltrationExpPow: 0.8,
|
||||
|
||||
//Stock market constants
|
||||
WSEAccountCost: 200e6,
|
||||
TIXAPICost: 5e9,
|
||||
MarketData4SCost: 1e9,
|
||||
// Stock market
|
||||
WSEAccountCost: 200e6,
|
||||
TIXAPICost: 5e9,
|
||||
MarketData4SCost: 1e9,
|
||||
MarketDataTixApi4SCost: 25e9,
|
||||
StockMarketCommission: 100e3,
|
||||
StockMarketCommission: 100e3,
|
||||
|
||||
//Hospital/Health
|
||||
// Hospital/Health
|
||||
HospitalCostPerHp: 100e3,
|
||||
|
||||
//Intelligence-related constants
|
||||
IntelligenceCrimeWeight: 0.05, //Weight for how much int affects crime success rates
|
||||
IntelligenceInfiltrationWeight: 0.1, //Weight for how much int affects infiltration success rates
|
||||
// Intelligence-related constants
|
||||
IntelligenceCrimeWeight: 0.05, // Weight for how much int affects crime success rates
|
||||
IntelligenceInfiltrationWeight: 0.1, // Weight for how much int affects infiltration success rates
|
||||
IntelligenceCrimeBaseExpGain: 0.001,
|
||||
IntelligenceProgramBaseExpGain: 500, //Program required hack level divided by this to determine int exp gain
|
||||
IntelligenceTerminalHackBaseExpGain: 200, //Hacking exp divided by this to determine int exp gain
|
||||
IntelligenceProgramBaseExpGain: 500, // Program required hack level divided by this to determine int exp gain
|
||||
IntelligenceTerminalHackBaseExpGain: 200, // Hacking exp divided by this to determine int exp gain
|
||||
IntelligenceSingFnBaseExpGain: 0.002,
|
||||
IntelligenceClassBaseExpGain: 0.000001,
|
||||
IntelligenceHackingMissionBaseExpGain: 0.03, //Hacking Mission difficulty multiplied by this to get exp gain
|
||||
IntelligenceHackingMissionBaseExpGain: 0.03, // Hacking Mission difficulty multiplied by this to get exp gain
|
||||
|
||||
//Hacking Missions
|
||||
HackingMissionRepToDiffConversion: 10000, //Faction rep is divided by this to get mission difficulty
|
||||
HackingMissionRepToRewardConversion: 7, //Faction rep divided byt his to get mission rep reward
|
||||
HackingMissionSpamTimeIncrease: 25000, //How much time limit increase is gained when conquering a Spam Node (ms)
|
||||
HackingMissionTransferAttackIncrease: 1.05, //Multiplier by which the attack for all Core Nodes is increased when conquering a Transfer Node
|
||||
HackingMissionMiscDefenseIncrease: 1.05, //The amount by which every misc node's defense is multiplied when one is conquered
|
||||
HackingMissionDifficultyToHacking: 135, //Difficulty is multiplied by this to determine enemy's "hacking" level (to determine effects of scan/attack, etc)
|
||||
// Hacking Missions
|
||||
// TODO Move this into Hacking Mission implementation
|
||||
HackingMissionRepToDiffConversion: 10000, // Faction rep is divided by this to get mission difficulty
|
||||
HackingMissionRepToRewardConversion: 7, // Faction rep divided byt his to get mission rep reward
|
||||
HackingMissionSpamTimeIncrease: 25000, // How much time limit increase is gained when conquering a Spam Node (ms)
|
||||
HackingMissionTransferAttackIncrease: 1.05, // Multiplier by which the attack for all Core Nodes is increased when conquering a Transfer Node
|
||||
HackingMissionMiscDefenseIncrease: 1.05, // The amount by which every misc node's defense is multiplied when one is conquered
|
||||
HackingMissionDifficultyToHacking: 135, // Difficulty is multiplied by this to determine enemy's "hacking" level (to determine effects of scan/attack, etc)
|
||||
HackingMissionHowToPlay: "Hacking missions are a minigame that, if won, will reward you with faction reputation.<br><br>" +
|
||||
"In this game you control a set of Nodes and use them to try and defeat an enemy. Your Nodes " +
|
||||
"are colored blue, while the enemy's are red. There are also other nodes on the map colored gray " +
|
||||
@@ -200,7 +193,7 @@ export let CONSTANTS: IMap<any> = {
|
||||
"-Miscellaneous Nodes slowly raise their defense over time<br><br>" +
|
||||
"-Nodes slowly regenerate health over time.",
|
||||
|
||||
/* Time Constants */
|
||||
// Time-related constants
|
||||
MillisecondsPer20Hours: 72000000,
|
||||
GameCyclesPer20Hours: 72000000 / 200,
|
||||
|
||||
@@ -228,7 +221,7 @@ export let CONSTANTS: IMap<any> = {
|
||||
MillisecondsPerFiveMinutes: 300000,
|
||||
GameCyclesPerFiveMinutes: 300000 / 200,
|
||||
|
||||
/* Player Work / Action related Constants */
|
||||
// Player Work & Action
|
||||
FactionWorkHacking: "Faction Hacking Work",
|
||||
FactionWorkField: "Faction Field Work",
|
||||
FactionWorkSecurity: "Faction Security Work",
|
||||
@@ -271,27 +264,37 @@ export let CONSTANTS: IMap<any> = {
|
||||
CrimeAssassination: "assassinate a high-profile target",
|
||||
CrimeHeist: "pull off the ultimate heist",
|
||||
|
||||
/* Coding Contract Constants */
|
||||
CodingContractBaseFactionRepGain: 2500,
|
||||
CodingContractBaseCompanyRepGain: 4000,
|
||||
CodingContractBaseMoneyGain: 75e6,
|
||||
// Coding Contract
|
||||
// TODO Move this into Coding contract impelmentation?
|
||||
CodingContractBaseFactionRepGain: 2500,
|
||||
CodingContractBaseCompanyRepGain: 4000,
|
||||
CodingContractBaseMoneyGain: 75e6,
|
||||
|
||||
// BitNode/Source-File related stuff
|
||||
TotalNumBitNodes: 24,
|
||||
|
||||
LatestUpdate:
|
||||
`
|
||||
v0.44.1
|
||||
* Duplicate Sleeve changes:
|
||||
** You can now purchase Augmentations for your Duplicate Sleeves
|
||||
** Sleeves are now assigned to Shock Recovery task by default
|
||||
** Shock Recovery and Synchronize tasks are now twice as effective
|
||||
v0.46.2
|
||||
* Source-File 2 now allows you to form gangs in other BitNodes when your karma reaches a very large negative value
|
||||
** (Karma is a hidden stat and is lowered by committing crimes)
|
||||
* Gang changes:
|
||||
** Bug Fix: Gangs can no longer clash with themselve
|
||||
** Bug Fix: Winning against another gang should properly reduce their power
|
||||
|
||||
* Changed documentation so that Netscript functions are own their own pages. Sorry if this is annoying, it was necessary for properly cross-referencing
|
||||
* Officially deprecated the Wiki (the fandom site). Use the 'readthedocs' Documentation instead
|
||||
* Bug Fix: 'rm' Terminal and Netscript commands now work on non-program files that have '.exe' in the name (by Github user MasonD)
|
||||
* Bug Fix: The 'Find All Valid Math Expressions' Coding Contract should now properly ignore whitespace in answers
|
||||
* Bug Fix: The 'Merge Overlapping Intervals' Coding Contract should now properly accept 2D arrays when being attempted through Netscript
|
||||
* Bug Fix: Terminal 'wget' command now works properly
|
||||
* Bug Fix: Hacknet Server Hash upgrades now properly reset upon installing Augs/switching BitNodes
|
||||
* Bug Fix: Fixed button for creating Corporations
|
||||
|
||||
v0.46.1
|
||||
* Added a very rudimentary directory system to the Terminal
|
||||
** Details here: https://bitburner.readthedocs.io/en/latest/basicgameplay/terminal.html#filesystem-directories
|
||||
* Added numHashes(), hashCost(), and spendHashes() functions to the Netscript Hacknet Node API
|
||||
* 'Generate Coding Contract' hash upgrade is now more expensive
|
||||
* 'Generate Coding Contract' hash upgrade now generates the contract randomly on the server, rather than on home computer
|
||||
* The cost of selling hashes for money no longer increases each time
|
||||
* Selling hashes for money now costs 4 hashes (in exchange for $1m)
|
||||
* Bug Fix: Hacknet Node earnings should work properly when game is inactive/offline
|
||||
* Bug Fix: Duplicate Sleeve augmentations are now properly reset when switching to a new BitNode
|
||||
`
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
2403
src/Corporation/Corporation.jsx
Normal file
2403
src/Corporation/Corporation.jsx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
import { ResearchTree } from "./ResearchTree";
|
||||
import { getBaseResearchTreeCopy } from "./data/BaseResearchTree";
|
||||
import { getBaseResearchTreeCopy,
|
||||
getProductIndustryResearchTreeCopy } from "./data/BaseResearchTree";
|
||||
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
|
||||
@@ -112,15 +113,15 @@ export let IndustryResearchTrees: IIndustryMap<ResearchTree> = {
|
||||
Agriculture: getBaseResearchTreeCopy(),
|
||||
Fishing: getBaseResearchTreeCopy(),
|
||||
Mining: getBaseResearchTreeCopy(),
|
||||
Food: getBaseResearchTreeCopy(),
|
||||
Tobacco: getBaseResearchTreeCopy(),
|
||||
Food: getProductIndustryResearchTreeCopy(),
|
||||
Tobacco: getProductIndustryResearchTreeCopy(),
|
||||
Chemical: getBaseResearchTreeCopy(),
|
||||
Pharmaceutical: getBaseResearchTreeCopy(),
|
||||
Computer: getBaseResearchTreeCopy(),
|
||||
Robotics: getBaseResearchTreeCopy(),
|
||||
Software: getBaseResearchTreeCopy(),
|
||||
Healthcare: getBaseResearchTreeCopy(),
|
||||
RealEstate: getBaseResearchTreeCopy(),
|
||||
Pharmaceutical: getProductIndustryResearchTreeCopy(),
|
||||
Computer: getProductIndustryResearchTreeCopy(),
|
||||
Robotics: getProductIndustryResearchTreeCopy(),
|
||||
Software: getProductIndustryResearchTreeCopy(),
|
||||
Healthcare: getProductIndustryResearchTreeCopy(),
|
||||
RealEstate: getProductIndustryResearchTreeCopy(),
|
||||
}
|
||||
|
||||
export function resetIndustryResearchTrees() {
|
||||
|
||||
@@ -12,7 +12,6 @@ export class Material {
|
||||
return Generic_fromJSON(Material, value.data);
|
||||
}
|
||||
|
||||
|
||||
// Name of material
|
||||
name: string = "InitName";
|
||||
|
||||
@@ -64,6 +63,11 @@ export class Material {
|
||||
prdman: any[] = [false, 0]; // Production
|
||||
sllman: any[] = [false, 0]; // Sale
|
||||
|
||||
// Flags that signal whether automatic sale pricing through Market TA is enabled
|
||||
marketTa1: boolean = false;
|
||||
marketTa2: boolean = false;
|
||||
marketTa2Price: number = 0;
|
||||
|
||||
constructor(params: IConstructorParams = {}) {
|
||||
if (params.name) { this.name = params.name; }
|
||||
this.init();
|
||||
@@ -82,7 +86,7 @@ export class Material {
|
||||
this.mku = 6;
|
||||
break;
|
||||
case "Energy":
|
||||
this.dmd = 90; this.dmdR = [80, 100];
|
||||
this.dmd = 90; this.dmdR = [80, 99];
|
||||
this.cmp = 80; this.cmpR = [65, 95];
|
||||
this.bCost = 2000; this.mv = 0.2;
|
||||
this.mku = 6;
|
||||
@@ -118,26 +122,26 @@ export class Material {
|
||||
this.mku = 2;
|
||||
break;
|
||||
case "Real Estate":
|
||||
this.dmd = 50; this.dmdR = [5, 100];
|
||||
this.dmd = 50; this.dmdR = [5, 99];
|
||||
this.cmp = 50; this.cmpR = [25, 75];
|
||||
this.bCost = 80e3; this.mv = 1.5; //Less mv bc its processed twice
|
||||
this.mku = 1.5;
|
||||
break;
|
||||
case "Drugs":
|
||||
this.dmd = 60; this.dmdR = [45, 75];
|
||||
this.cmp = 70; this.cmpR = [40, 100];
|
||||
this.cmp = 70; this.cmpR = [40, 99];
|
||||
this.bCost = 40e3; this.mv = 1.6;
|
||||
this.mku = 1;
|
||||
break;
|
||||
case "Robots":
|
||||
this.dmd = 90; this.dmdR = [80, 100];
|
||||
this.cmp = 90; this.cmpR = [80, 100];
|
||||
this.dmd = 90; this.dmdR = [80, 9];
|
||||
this.cmp = 90; this.cmpR = [80, 9];
|
||||
this.bCost = 75e3; this.mv = 0.5; //Less mv bc its processed twice
|
||||
this.mku = 1;
|
||||
break;
|
||||
case "AI Cores":
|
||||
this.dmd = 90; this.dmdR = [80, 100];
|
||||
this.cmp = 90; this.cmpR = [80, 100];
|
||||
this.dmd = 90; this.dmdR = [80, 99];
|
||||
this.cmp = 90; this.cmpR = [80, 9];
|
||||
this.bCost = 15e3; this.mv = 0.8; //Less mv bc its processed twice
|
||||
this.mku = 0.5;
|
||||
break;
|
||||
|
||||
@@ -2,15 +2,17 @@ import { IMap } from "../types";
|
||||
|
||||
// Map of material (by name) to their sizes (how much space it takes in warehouse)
|
||||
export const MaterialSizes: IMap<number> = {
|
||||
Water: 0.05,
|
||||
Energy: 0.01,
|
||||
Food: 0.03,
|
||||
Plants: 0.05,
|
||||
Metal: 0.1,
|
||||
Hardware: 0.06,
|
||||
Chemicals: 0.05,
|
||||
Drugs: 0.02,
|
||||
Robots: 0.5,
|
||||
AICores: 0.1,
|
||||
RealEstate: 0,
|
||||
Water: 0.05,
|
||||
Energy: 0.01,
|
||||
Food: 0.03,
|
||||
Plants: 0.05,
|
||||
Metal: 0.1,
|
||||
Hardware: 0.06,
|
||||
Chemicals: 0.05,
|
||||
Drugs: 0.02,
|
||||
Robots: 0.5,
|
||||
AICores: 0.1,
|
||||
RealEstate: 0,
|
||||
"Real Estate": 0,
|
||||
"AI Cores": 0,
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { MaterialSizes } from "./MaterialSizes";
|
||||
import { ProductRatingWeights,
|
||||
IProductRatingWeight } from "./ProductRatingWeights";
|
||||
|
||||
import { Cities } from "../Locations/Cities";
|
||||
import { createCityMap } from "../Locations/createCityMap";
|
||||
import { IMap } from "../types";
|
||||
|
||||
import { Generic_fromJSON,
|
||||
@@ -89,14 +89,7 @@ export class Product {
|
||||
// Data refers to the production, sale, and quantity of the products
|
||||
// These values are specific to a city
|
||||
// For each city, the data is [qty, prod, sell]
|
||||
data: IMap<number[]> = {
|
||||
[Cities.Aevum]: [0, 0, 0],
|
||||
[Cities.Chongqing]: [0, 0, 0],
|
||||
[Cities.Sector12]: [0, 0, 0],
|
||||
[Cities.NewTokyo]: [0, 0, 0],
|
||||
[Cities.Ishima]: [0, 0, 0],
|
||||
[Cities.Volhaven]: [0, 0, 0],
|
||||
}
|
||||
data: IMap<number[]> = createCityMap<number[]>([0, 0, 0]);
|
||||
|
||||
// Location of this Product
|
||||
// Only applies for location-based products like restaurants/hospitals
|
||||
@@ -113,23 +106,13 @@ export class Product {
|
||||
// Data to keep track of whether production/sale of this Product is
|
||||
// manually limited. These values are specific to a city
|
||||
// [Whether production/sale is limited, limit amount]
|
||||
prdman: IMap<any[]> = {
|
||||
[Cities.Aevum]: [false, 0],
|
||||
[Cities.Chongqing]: [false, 0],
|
||||
[Cities.Sector12]: [false, 0],
|
||||
[Cities.NewTokyo]: [false, 0],
|
||||
[Cities.Ishima]: [false, 0],
|
||||
[Cities.Volhaven]: [false, 0],
|
||||
}
|
||||
prdman: IMap<any[]> = createCityMap<any[]>([false, 0]);
|
||||
sllman: IMap<any[]> = createCityMap<any[]>([false, 0]);
|
||||
|
||||
sllman: IMap<any[]> = {
|
||||
[Cities.Aevum]: [false, 0],
|
||||
[Cities.Chongqing]: [false, 0],
|
||||
[Cities.Sector12]: [false, 0],
|
||||
[Cities.NewTokyo]: [false, 0],
|
||||
[Cities.Ishima]: [false, 0],
|
||||
[Cities.Volhaven]: [false, 0],
|
||||
}
|
||||
// Flags that signal whether automatic sale pricing through Market TA is enabled
|
||||
marketTa1: boolean = false;
|
||||
marketTa2: boolean = false;
|
||||
marketTa2Price: IMap<number> = createCityMap<number>(0);
|
||||
|
||||
constructor(params: IConstructorParams={}) {
|
||||
this.name = params.name ? params.name : "";
|
||||
@@ -164,11 +147,11 @@ export class Product {
|
||||
//Calculate properties
|
||||
var progrMult = this.prog / 100;
|
||||
|
||||
var engrRatio = employeeProd[EmployeePositions.Engineer] / employeeProd["total"],
|
||||
mgmtRatio = employeeProd[EmployeePositions.Management] / employeeProd["total"],
|
||||
rndRatio = employeeProd[EmployeePositions.RandD] / employeeProd["total"],
|
||||
opsRatio = employeeProd[EmployeePositions.Operations] / employeeProd["total"],
|
||||
busRatio = employeeProd[EmployeePositions.Business] / employeeProd["total"];
|
||||
const engrRatio = employeeProd[EmployeePositions.Engineer] / employeeProd["total"];
|
||||
const mgmtRatio = employeeProd[EmployeePositions.Management] / employeeProd["total"];
|
||||
const rndRatio = employeeProd[EmployeePositions.RandD] / employeeProd["total"];
|
||||
const opsRatio = employeeProd[EmployeePositions.Operations] / employeeProd["total"];
|
||||
const busRatio = employeeProd[EmployeePositions.Business] / employeeProd["total"];
|
||||
var designMult = 1 + (Math.pow(this.designCost, 0.1) / 100);
|
||||
console.log("designMult: " + designMult);
|
||||
var balanceMult = (1.2 * engrRatio) + (0.9 * mgmtRatio) + (1.3 * rndRatio) +
|
||||
|
||||
@@ -8,6 +8,7 @@ export interface IConstructorParams {
|
||||
employeeEffMult?: number;
|
||||
employeeIntMult?: number;
|
||||
productionMult?: number;
|
||||
productProductionMult?: number;
|
||||
salesMult?: number;
|
||||
sciResearchMult?: number;
|
||||
storageMult?: number;
|
||||
@@ -30,6 +31,7 @@ export class Research {
|
||||
employeeEffMult: number = 1;
|
||||
employeeIntMult: number = 1;
|
||||
productionMult: number = 1;
|
||||
productProductionMult: number = 1;
|
||||
salesMult: number = 1;
|
||||
sciResearchMult: number = 1;
|
||||
storageMult: number = 1;
|
||||
@@ -38,14 +40,15 @@ export class Research {
|
||||
this.name = p.name;
|
||||
this.cost = p.cost;
|
||||
this.desc = p.desc;
|
||||
if (p.advertisingMult) { this.advertisingMult = p.advertisingMult; }
|
||||
if (p.employeeChaMult) { this.employeeChaMult = p.employeeChaMult; }
|
||||
if (p.employeeCreMult) { this.employeeCreMult = p.employeeCreMult; }
|
||||
if (p.employeeEffMult) { this.employeeEffMult = p.employeeEffMult; }
|
||||
if (p.employeeIntMult) { this.employeeIntMult = p.employeeIntMult; }
|
||||
if (p.productionMult) { this.productionMult = p.productionMult; }
|
||||
if (p.salesMult) { this.salesMult = p.salesMult; }
|
||||
if (p.sciResearchMult) { this.sciResearchMult = p.sciResearchMult; }
|
||||
if (p.storageMult) { this.storageMult = p.storageMult; }
|
||||
if (p.advertisingMult) { this.advertisingMult = p.advertisingMult; }
|
||||
if (p.employeeChaMult) { this.employeeChaMult = p.employeeChaMult; }
|
||||
if (p.employeeCreMult) { this.employeeCreMult = p.employeeCreMult; }
|
||||
if (p.employeeEffMult) { this.employeeEffMult = p.employeeEffMult; }
|
||||
if (p.employeeIntMult) { this.employeeIntMult = p.employeeIntMult; }
|
||||
if (p.productionMult) { this.productionMult = p.productionMult; }
|
||||
if (p.productProductionMult) { this.productProductionMult = p.productProductionMult; }
|
||||
if (p.salesMult) { this.salesMult = p.salesMult; }
|
||||
if (p.sciResearchMult) { this.sciResearchMult = p.sciResearchMult; }
|
||||
if (p.storageMult) { this.storageMult = p.storageMult; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import { ResearchMap } from "./ResearchMap";
|
||||
|
||||
import { IMap } from "../types";
|
||||
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
|
||||
interface IConstructorParams {
|
||||
children?: Node[];
|
||||
cost: number;
|
||||
@@ -83,7 +85,7 @@ export class Node {
|
||||
children: childrenArray,
|
||||
HTMLclass: htmlClass,
|
||||
innerHTML: `<div id="${sanitizedName}-corp-research-click-listener" class="tooltip">` +
|
||||
`${this.text}<br>${this.cost} Scientific Research` +
|
||||
`${this.text}<br>${numeralWrapper.format(this.cost, "0,0")} Scientific Research` +
|
||||
`<span class="tooltiptext">` +
|
||||
`${research.desc}` +
|
||||
`</span>` +
|
||||
@@ -185,6 +187,10 @@ export class ResearchTree {
|
||||
return this.getMultiplierHelper("productionMult");
|
||||
}
|
||||
|
||||
getProductProductionMultiplier(): number {
|
||||
return this.getMultiplierHelper("productProductionMult");
|
||||
}
|
||||
|
||||
getSalesMultiplier(): number {
|
||||
return this.getMultiplierHelper("salesMult");
|
||||
}
|
||||
|
||||
115
src/Corporation/Warehouse.ts
Normal file
115
src/Corporation/Warehouse.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { Material } from "./Material";
|
||||
import { MaterialSizes } from "./MaterialSizes";
|
||||
import { IMap } from "../types";
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
import { Generic_fromJSON,
|
||||
Generic_toJSON,
|
||||
Reviver } from "../../utils/JSONReviver";
|
||||
import { exceptionAlert } from "../../utils/helpers/exceptionAlert";
|
||||
|
||||
interface IParent {
|
||||
getStorageMultiplier(): number;
|
||||
}
|
||||
|
||||
interface IConstructorParams {
|
||||
corp?: IParent;
|
||||
industry?: IParent;
|
||||
loc?: string;
|
||||
size?: number;
|
||||
}
|
||||
|
||||
export class Warehouse {
|
||||
// Initiatizes a Warehouse object from a JSON save state.
|
||||
static fromJSON(value: any): Warehouse {
|
||||
return Generic_fromJSON(Warehouse, value.data);
|
||||
}
|
||||
|
||||
// Text that describes how the space in this Warehouse is being used
|
||||
// Used to create a tooltip in the UI
|
||||
breakdown: string = "";
|
||||
|
||||
// Warehouse's level, which affects its maximum size
|
||||
level: number = 1;
|
||||
|
||||
// City that this Warehouse is in
|
||||
loc: string;
|
||||
|
||||
// Map of Materials held by this Warehouse
|
||||
materials: IMap<Material>;
|
||||
|
||||
// Maximum amount warehouse can hold
|
||||
size: number;
|
||||
|
||||
// Amount of space currently used by warehouse
|
||||
sizeUsed: number = 0;
|
||||
|
||||
// Whether Smart Supply is enabled for this Industry (the Industry that this Warehouse is for)
|
||||
smartSupplyEnabled: boolean = false;
|
||||
|
||||
// Flag that indicates whether Smart Supply accounts for imports when calculating
|
||||
// the amount fo purchase
|
||||
smartSupplyConsiderExports: boolean = false;
|
||||
|
||||
// Stores the amount of product to be produced. Used for Smart Supply unlock.
|
||||
// The production tracked by smart supply is always based on the previous cycle,
|
||||
// so it will always trail the "true" production by 1 cycle
|
||||
smartSupplyStore: number = 0;
|
||||
|
||||
constructor(params: IConstructorParams = {}) {
|
||||
this.loc = params.loc ? params.loc : "";
|
||||
this.size = params.size ? params.size : 0;
|
||||
|
||||
this.materials = {
|
||||
Water: new Material({name: "Water"}),
|
||||
Energy: new Material({name: "Energy"}),
|
||||
Food: new Material({name: "Food"}),
|
||||
Plants: new Material({name: "Plants"}),
|
||||
Metal: new Material({name: "Metal"}),
|
||||
Hardware: new Material({name: "Hardware"}),
|
||||
Chemicals: new Material({name: "Chemicals"}),
|
||||
Drugs: new Material({name: "Drugs"}),
|
||||
Robots: new Material({name: "Robots"}),
|
||||
AICores: new Material({name: "AI Cores"}),
|
||||
RealEstate: new Material({name: "Real Estate"})
|
||||
}
|
||||
|
||||
if (params.corp && params.industry) {
|
||||
this.updateSize(params.corp, params.industry);
|
||||
}
|
||||
}
|
||||
|
||||
// Re-calculate how much space is being used by this Warehouse
|
||||
updateMaterialSizeUsed() {
|
||||
this.sizeUsed = 0;
|
||||
this.breakdown = "";
|
||||
for (const matName in this.materials) {
|
||||
var mat = this.materials[matName];
|
||||
if (MaterialSizes.hasOwnProperty(matName)) {
|
||||
this.sizeUsed += (mat.qty * MaterialSizes[matName]);
|
||||
if (mat.qty > 0) {
|
||||
this.breakdown += (matName + ": " + numeralWrapper.format(mat.qty * MaterialSizes[matName], "0,0.0") + "<br>");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.sizeUsed > this.size) {
|
||||
console.warn("Warehouse size used greater than capacity, something went wrong");
|
||||
}
|
||||
}
|
||||
|
||||
updateSize(corporation: IParent, industry: IParent) {
|
||||
try {
|
||||
this.size = (this.level * 100)
|
||||
* corporation.getStorageMultiplier()
|
||||
* industry.getStorageMultiplier();
|
||||
} catch(e) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize the current object to a JSON save state.
|
||||
toJSON(): any {
|
||||
return Generic_toJSON("Warehouse", this);
|
||||
}
|
||||
}
|
||||
|
||||
Reviver.constructors.Warehouse = Warehouse;
|
||||
@@ -14,19 +14,21 @@ function makeNode(name: string): Node {
|
||||
return new Node({ text: research.name, cost: research.cost });
|
||||
}
|
||||
|
||||
|
||||
export function getBaseResearchTreeCopy(): ResearchTree {
|
||||
const baseResearchTree: ResearchTree = new ResearchTree();
|
||||
|
||||
// Creates the Nodes for the BaseResearchTree.
|
||||
// Return the Root Node
|
||||
function createBaseResearchTreeNodes(): Node {
|
||||
const rootNode: Node = makeNode("Hi-Tech R&D Laboratory");
|
||||
const autoBrew: Node = makeNode("AutoBrew");
|
||||
const autoParty: Node = makeNode("AutoPartyManager");
|
||||
const autoDrugs: Node = makeNode("Automatic Drug Administration");
|
||||
const bulkPurchasing: Node = makeNode("Bulk Purchasing");
|
||||
const cph4: Node = makeNode("CPH4 Injections");
|
||||
const drones: Node = makeNode("Drones");
|
||||
const dronesAssembly: Node = makeNode("Drones - Assembly");
|
||||
const dronesTransport: Node = makeNode("Drones - Transport");
|
||||
const goJuice: Node = makeNode("Go-Juice");
|
||||
const hrRecruitment: Node = makeNode("HRBuddy-Recruitment");
|
||||
const hrTraining: Node = makeNode("HRBuddy-Training");
|
||||
const joywire: Node = makeNode("JoyWire");
|
||||
const marketta1: Node = makeNode("Market-TA.I");
|
||||
const marketta2: Node = makeNode("Market-TA.II");
|
||||
@@ -40,6 +42,8 @@ export function getBaseResearchTreeCopy(): ResearchTree {
|
||||
drones.addChild(dronesAssembly);
|
||||
drones.addChild(dronesTransport);
|
||||
|
||||
hrRecruitment.addChild(hrTraining);
|
||||
|
||||
marketta1.addChild(marketta2);
|
||||
|
||||
overclock.addChild(stimu);
|
||||
@@ -47,13 +51,40 @@ export function getBaseResearchTreeCopy(): ResearchTree {
|
||||
rootNode.addChild(autoBrew);
|
||||
rootNode.addChild(autoParty);
|
||||
rootNode.addChild(autoDrugs);
|
||||
rootNode.addChild(bulkPurchasing);
|
||||
rootNode.addChild(drones);
|
||||
rootNode.addChild(hrRecruitment);
|
||||
rootNode.addChild(joywire);
|
||||
rootNode.addChild(marketta1);
|
||||
rootNode.addChild(overclock);
|
||||
rootNode.addChild(scAssemblers);
|
||||
|
||||
baseResearchTree.setRoot(rootNode);
|
||||
return rootNode;
|
||||
}
|
||||
|
||||
export function getBaseResearchTreeCopy(): ResearchTree {
|
||||
const baseResearchTree: ResearchTree = new ResearchTree();
|
||||
baseResearchTree.setRoot(createBaseResearchTreeNodes());
|
||||
|
||||
return baseResearchTree;
|
||||
}
|
||||
|
||||
// Base Research Tree for Industry's that make products
|
||||
export function getProductIndustryResearchTreeCopy(): ResearchTree {
|
||||
const researchTree: ResearchTree = new ResearchTree();
|
||||
const root = createBaseResearchTreeNodes();
|
||||
|
||||
const upgradeFulcrum = makeNode("uPgrade: Fulcrum");
|
||||
const upgradeCapacity1 = makeNode("uPgrade: Capacity.I");
|
||||
const upgradeCapacity2 = makeNode("uPgrade: Capacity.II");
|
||||
const upgradeDashboard = makeNode("uPgrade: Dashboard");
|
||||
|
||||
upgradeCapacity1.addChild(upgradeCapacity2);
|
||||
upgradeFulcrum.addChild(upgradeCapacity1);
|
||||
upgradeFulcrum.addChild(upgradeDashboard);
|
||||
root.addChild(upgradeFulcrum);
|
||||
|
||||
researchTree.setRoot(root);
|
||||
|
||||
return researchTree;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,12 @@ export const researchMetadata: IConstructorParams[] = [
|
||||
desc: "Research how to automatically administer performance-enhacing drugs to all of " +
|
||||
"your employees. This unlocks Drug-related Research.",
|
||||
},
|
||||
{
|
||||
name: "Bulk Purchasing",
|
||||
cost: 5e3,
|
||||
desc: "Research the art of buying materials in bulk. This allows you to purchase " +
|
||||
"any amount of a material instantly.",
|
||||
},
|
||||
{
|
||||
name: "CPH4 Injections",
|
||||
cost: 25e3,
|
||||
@@ -64,13 +70,28 @@ export const researchMetadata: IConstructorParams[] = [
|
||||
},
|
||||
{
|
||||
name: "Hi-Tech R&D Laboratory",
|
||||
cost: 10e3,
|
||||
cost: 5e3,
|
||||
desc: "Construct a cutting edge facility dedicated to advanced research and " +
|
||||
"and development. This allows you to spend Scientific Research " +
|
||||
"on powerful upgrades. It also globally increases Scientific Research " +
|
||||
"production by 10%.",
|
||||
sciResearchMult: 1.1,
|
||||
},
|
||||
{
|
||||
name: "HRBuddy-Recruitment",
|
||||
cost: 15e3,
|
||||
desc: "Use automated software to handle the hiring of employees. With this " +
|
||||
"research, each office will automatically hire one employee per " +
|
||||
"market cycle if there is available space."
|
||||
|
||||
},
|
||||
{
|
||||
name: "HRBuddy-Training",
|
||||
cost: 20e3,
|
||||
desc: "Use automated software to handle the training of employees. With this " +
|
||||
"research, each employee hired with HRBuddy-Recruitment will automatically " +
|
||||
"be assigned to 'Training', rather than being unassigned."
|
||||
},
|
||||
{
|
||||
name: "JoyWire",
|
||||
cost: 20e3,
|
||||
@@ -83,15 +104,18 @@ export const researchMetadata: IConstructorParams[] = [
|
||||
desc: "Develop advanced AI software that uses technical analysis to " +
|
||||
"help you understand and exploit the market. This research " +
|
||||
"allows you to know what price to sell your Materials/Products " +
|
||||
"at in order to avoid losing sales due to having too high of a mark-up.",
|
||||
"at in order to avoid losing sales due to having too high of a mark-up. " +
|
||||
"It also lets you automatically use that sale price.",
|
||||
},
|
||||
{
|
||||
name: "Market-TA.II",
|
||||
cost: 40e3,
|
||||
cost: 50e3,
|
||||
desc: "Develop double-advanced AI software that uses technical analysis to " +
|
||||
"help you understand and exploit the market. This research " +
|
||||
"allows you to know how many sales of a Material/Product you lose or gain " +
|
||||
"from having too high or too low or a sale price.",
|
||||
"from having too high or too low or a sale price. It also lets you automatically " +
|
||||
"set the sale price of your Materials/Products at the optimal price such that " +
|
||||
"the amount sold matches the amount produced.",
|
||||
},
|
||||
{
|
||||
name: "Overclock",
|
||||
@@ -118,7 +142,38 @@ export const researchMetadata: IConstructorParams[] = [
|
||||
"control confidence and enthusiasm. This research increases the max " +
|
||||
"morale of all employees by 10.",
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
name: "sudo.Assist",
|
||||
cost: 15e3,
|
||||
desc: "Develop a virtual assistant AI to handle and manage administrative " +
|
||||
"issues for your corporation.",
|
||||
},
|
||||
{
|
||||
name: "uPgrade: Capacity.I",
|
||||
cost: 20e3,
|
||||
desc: "Expand the industry's capacity for designing and manufacturing its " +
|
||||
"various products. This increases the industry's maximum number of products " +
|
||||
"by 1 (from 3 to 4).",
|
||||
},
|
||||
{
|
||||
name: "uPgrade: Capacity.II",
|
||||
cost: 30e3,
|
||||
desc: "Expand the industry's capacity for designing and manufacturing its " +
|
||||
"various products. This increases the industry's maximum number of products " +
|
||||
"by 1 (from 4 to 5).",
|
||||
},
|
||||
{
|
||||
name: "uPgrade: Dashboard",
|
||||
cost: 5e3,
|
||||
desc: "Improve the software used to manage the industry's production line " +
|
||||
"for its various products. This allows you to manage the production and " +
|
||||
"sale of a product before it's finished being designed.",
|
||||
},
|
||||
{
|
||||
name: "uPgrade: Fulcrum",
|
||||
cost: 10e3,
|
||||
desc: "Streamline the manufacturing of this industry's various products. " +
|
||||
"This research increases the production of your products by 5%",
|
||||
productProductionMult: 1.05,
|
||||
},
|
||||
];
|
||||
|
||||
22
src/Corporation/ui/BaseReactComponent.js
Normal file
22
src/Corporation/ui/BaseReactComponent.js
Normal file
@@ -0,0 +1,22 @@
|
||||
// Base class for React Components for Corporation UI
|
||||
// Contains a few helper functions that let derived classes easily
|
||||
// access Corporation properties
|
||||
import React from "react";
|
||||
|
||||
const Component = React.Component;
|
||||
|
||||
export class BaseReactComponent extends Component {
|
||||
corp() {
|
||||
return this.props.corp;
|
||||
}
|
||||
|
||||
eventHandler() {
|
||||
return this.props.eventHandler;
|
||||
}
|
||||
|
||||
routing() {
|
||||
return this.props.routing;
|
||||
}
|
||||
|
||||
render() {}
|
||||
}
|
||||
62
src/Corporation/ui/CityTabs.jsx
Normal file
62
src/Corporation/ui/CityTabs.jsx
Normal file
@@ -0,0 +1,62 @@
|
||||
// React Components for the Corporation UI's City navigation tabs
|
||||
// These allow player to navigate between different cities for each industry
|
||||
import React from "react";
|
||||
import { BaseReactComponent } from "./BaseReactComponent";
|
||||
|
||||
export class CityTabs extends BaseReactComponent {
|
||||
constructor(props) {
|
||||
// An object with [key = city name] and [value = click handler]
|
||||
// needs to be passed into the constructor as the "onClicks" property.
|
||||
// We'll make sure that that happens here
|
||||
if (props.onClicks == null) {
|
||||
throw new Error(`CityTabs component constructed without onClick handlers`);
|
||||
}
|
||||
if (props.city == null) {
|
||||
throw new Error(`CityTabs component constructed without 'city' property`)
|
||||
}
|
||||
if (props.cityStateSetter == null) {
|
||||
throw new Error(`CityTabs component constructed without 'cityStateSetter' property`)
|
||||
}
|
||||
|
||||
super(props);
|
||||
}
|
||||
|
||||
renderTab(props) {
|
||||
let className = "cmpy-mgmt-city-tab";
|
||||
if (props.current) {
|
||||
className += " current";
|
||||
}
|
||||
|
||||
return (
|
||||
<button className={className} onClick={props.onClick} key={props.key}>
|
||||
{props.key}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const division = this.routing().currentDivision;
|
||||
|
||||
const tabs = [];
|
||||
|
||||
// Tabs for each city
|
||||
for (const cityName in this.props.onClicks) {
|
||||
tabs.push(this.renderTab({
|
||||
current: this.props.city === cityName,
|
||||
key: cityName,
|
||||
onClick: this.props.onClicks[cityName],
|
||||
}));
|
||||
}
|
||||
|
||||
// Tab to "Expand into new City"
|
||||
const newCityOnClick = this.eventHandler().createNewCityPopup.bind(this.eventHandler(), division, this.props.cityStateSetter);
|
||||
|
||||
tabs.push(this.renderTab({
|
||||
current: false,
|
||||
key: "Expand into new City",
|
||||
onClick: newCityOnClick,
|
||||
}));
|
||||
|
||||
return tabs;
|
||||
}
|
||||
}
|
||||
1747
src/Corporation/ui/CorporationUIEventHandler.js
Normal file
1747
src/Corporation/ui/CorporationUIEventHandler.js
Normal file
File diff suppressed because it is too large
Load Diff
80
src/Corporation/ui/HeaderTabs.jsx
Normal file
80
src/Corporation/ui/HeaderTabs.jsx
Normal file
@@ -0,0 +1,80 @@
|
||||
// React Components for the Corporation UI's navigation tabs
|
||||
// These are the tabs at the top of the UI that let you switch to different
|
||||
// divisions, see an overview of your corporation, or create a new industry
|
||||
import React from "react";
|
||||
import { BaseReactComponent } from "./BaseReactComponent";
|
||||
|
||||
import { overviewPage } from "./Routing";
|
||||
|
||||
function HeaderTab(props) {
|
||||
let className = "cmpy-mgmt-header-tab";
|
||||
if (props.current) {
|
||||
className += " current";
|
||||
}
|
||||
|
||||
return (
|
||||
<button className={className} onClick={props.onClick}>
|
||||
{props.text}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
export class HeaderTabs extends BaseReactComponent {
|
||||
renderTab(props) {
|
||||
return (
|
||||
<HeaderTab
|
||||
current={props.current}
|
||||
key={props.key}
|
||||
onClick={props.onClick}
|
||||
text={props.text}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const overviewOnClick = () => {
|
||||
this.routing().routeToOverviewPage();
|
||||
this.corp().rerender();
|
||||
}
|
||||
|
||||
const divisionOnClicks = {};
|
||||
for (const division of this.corp().divisions) {
|
||||
const name = division.name;
|
||||
const onClick = () => {
|
||||
this.routing().routeTo(name);
|
||||
this.corp().rerender();
|
||||
}
|
||||
|
||||
divisionOnClicks[name] = onClick;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
this.renderTab({
|
||||
current: this.routing().isOnOverviewPage(),
|
||||
key: "overview",
|
||||
onClick: overviewOnClick,
|
||||
text: this.corp().name,
|
||||
})
|
||||
}
|
||||
{
|
||||
this.corp().divisions.map((division) => {
|
||||
return this.renderTab({
|
||||
current: this.routing().isOn(division.name),
|
||||
key: division.name,
|
||||
onClick: divisionOnClicks[division.name],
|
||||
text: division.name,
|
||||
});
|
||||
})
|
||||
}
|
||||
{
|
||||
this.renderTab({
|
||||
onClick: this.eventHandler().createNewIndustryPopup.bind(this.eventHandler()),
|
||||
text: "Expand into new Industry"
|
||||
})
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
34
src/Corporation/ui/Industry.jsx
Normal file
34
src/Corporation/ui/Industry.jsx
Normal file
@@ -0,0 +1,34 @@
|
||||
// React Component for managing the Corporation's Industry UI
|
||||
// This Industry component does NOT include the city tabs at the top
|
||||
import React from "react";
|
||||
import { BaseReactComponent } from "./BaseReactComponent";
|
||||
|
||||
import { IndustryOffice } from "./IndustryOffice";
|
||||
import { IndustryOverview } from "./IndustryOverview";
|
||||
import { IndustryWarehouse } from "./IndustryWarehouse";
|
||||
|
||||
export class Industry extends BaseReactComponent {
|
||||
constructor(props) {
|
||||
if (props.currentCity == null) {
|
||||
throw new Error(`Industry component constructed without 'city' prop`);
|
||||
}
|
||||
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div className={"cmpy-mgmt-industry-left-panel"}>
|
||||
<IndustryOverview {...this.props} />
|
||||
<IndustryOffice {...this.props} />
|
||||
</div>
|
||||
|
||||
<div className={"cmpy-mgmt-industry-right-panel"}>
|
||||
<IndustryWarehouse {...this.props} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
609
src/Corporation/ui/IndustryOffice.jsx
Normal file
609
src/Corporation/ui/IndustryOffice.jsx
Normal file
@@ -0,0 +1,609 @@
|
||||
// React Component for displaying an Industry's OfficeSpace information
|
||||
// (bottom-left panel in the Industry UI)
|
||||
import React from "react";
|
||||
import { BaseReactComponent } from "./BaseReactComponent";
|
||||
|
||||
import { OfficeSpace } from "../Corporation";
|
||||
import { EmployeePositions } from "../EmployeePositions";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
import { getSelectText } from "../../../utils/uiHelpers/getSelectData";
|
||||
|
||||
export class IndustryOffice extends BaseReactComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
city: "",
|
||||
division: "",
|
||||
employeeManualAssignMode: false,
|
||||
employee: null, // Reference to employee being referenced if in Manual Mode
|
||||
numEmployees: 0,
|
||||
numOperations: 0,
|
||||
numEngineers: 0,
|
||||
numBusiness: 0,
|
||||
numManagement: 0,
|
||||
numResearch: 0,
|
||||
numUnassigned: 0,
|
||||
numTraining: 0,
|
||||
}
|
||||
|
||||
this.updateEmployeeCount(); // This function validates division and office refs
|
||||
}
|
||||
|
||||
resetEmployeeCount() {
|
||||
this.state.numEmployees = 0;
|
||||
this.state.numOperations = 0;
|
||||
this.state.numEngineers = 0;
|
||||
this.state.numBusiness = 0;
|
||||
this.state.numManagement = 0;
|
||||
this.state.numResearch = 0;
|
||||
this.state.numUnassigned = 0;
|
||||
this.state.numTraining = 0;
|
||||
}
|
||||
|
||||
updateEmployeeCount() {
|
||||
const division = this.routing().currentDivision;
|
||||
if (division == null) {
|
||||
throw new Error(`Routing does not hold reference to the current Industry`);
|
||||
}
|
||||
const office = division.offices[this.props.currentCity];
|
||||
if (!(office instanceof OfficeSpace)) {
|
||||
throw new Error(`Current City (${this.props.currentCity}) for UI does not have an OfficeSpace object`);
|
||||
}
|
||||
|
||||
// If we're in a new city, we have to reset the state
|
||||
if (division.name !== this.state.division || this.props.currentCity !== this.state.city) {
|
||||
this.resetEmployeeCount();
|
||||
this.state.division = division.name;
|
||||
this.state.city = this.props.currentCity;
|
||||
}
|
||||
|
||||
// Calculate how many NEW emplyoees we need to account for
|
||||
const currentNumEmployees = office.employees.length;
|
||||
const newEmployees = currentNumEmployees - this.state.numEmployees;
|
||||
|
||||
// Record the number of employees in each position, for NEW employees only
|
||||
for (let i = this.state.numEmployees; i < office.employees.length; ++i) {
|
||||
switch (office.employees[i].pos) {
|
||||
case EmployeePositions.Operations:
|
||||
++this.state.numOperations;
|
||||
break;
|
||||
case EmployeePositions.Engineer:
|
||||
++this.state.numEngineers;
|
||||
break;
|
||||
case EmployeePositions.Business:
|
||||
++this.state.numBusiness;
|
||||
break;
|
||||
case EmployeePositions.Management:
|
||||
++this.state.numManagement;
|
||||
break;
|
||||
case EmployeePositions.RandD:
|
||||
++this.state.numResearch;
|
||||
break;
|
||||
case EmployeePositions.Unassigned:
|
||||
++this.state.numUnassigned;
|
||||
break;
|
||||
case EmployeePositions.Training:
|
||||
++this.state.numTraining;
|
||||
break;
|
||||
default:
|
||||
console.error("Unrecognized employee position: " + office.employees[i].pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.state.numEmployees = currentNumEmployees;
|
||||
}
|
||||
|
||||
// Renders the "Employee Management" section of the Office UI
|
||||
renderEmployeeManagement() {
|
||||
this.updateEmployeeCount();
|
||||
|
||||
if (this.state.employeeManualAssignMode) {
|
||||
return this.renderManualEmployeeManagement();
|
||||
} else {
|
||||
return this.renderAutomaticEmployeeManagement();
|
||||
}
|
||||
}
|
||||
|
||||
renderAutomaticEmployeeManagement() {
|
||||
const division = this.routing().currentDivision; // Validated in constructor
|
||||
const office = division.offices[this.props.currentCity]; // Validated in constructor
|
||||
const vechain = (this.corp().unlockUpgrades[4] === 1); // Has Vechain upgrade
|
||||
|
||||
const switchModeOnClick = () => {
|
||||
this.state.employeeManualAssignMode = true;
|
||||
this.corp().rerender();
|
||||
}
|
||||
|
||||
// Calculate average morale, happiness, and energy. Also salary
|
||||
// TODO is this efficient?
|
||||
let totalMorale = 0, totalHappiness = 0, totalEnergy = 0, totalSalary = 0;
|
||||
for (let i = 0; i < office.employees.length; ++i) {
|
||||
totalMorale += office.employees[i].mor;
|
||||
totalHappiness += office.employees[i].hap;
|
||||
totalEnergy += office.employees[i].ene;
|
||||
totalSalary += office.employees[i].sal;
|
||||
}
|
||||
|
||||
let avgMorale = 0, avgHappiness = 0, avgEnergy = 0;
|
||||
if (office.employees.length > 0) {
|
||||
avgMorale = totalMorale / office.employees.length;
|
||||
avgHappiness = totalHappiness / office.employees.length;
|
||||
avgEnergy = totalEnergy / office.employees.length;
|
||||
}
|
||||
|
||||
// Helper functions for (re-)assigning employees to different positions
|
||||
const assignEmployee = (to) => {
|
||||
if (this.state.numUnassigned <= 0) {
|
||||
console.warn("Cannot assign employee. No unassigned employees available");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (to) {
|
||||
case EmployeePositions.Operations:
|
||||
++this.state.numOperations;
|
||||
break;
|
||||
case EmployeePositions.Engineer:
|
||||
++this.state.numEngineers;
|
||||
break;
|
||||
case EmployeePositions.Business:
|
||||
++this.state.numBusiness;
|
||||
break;
|
||||
case EmployeePositions.Management:
|
||||
++this.state.numManagement;
|
||||
break;
|
||||
case EmployeePositions.RandD:
|
||||
++this.state.numResearch;
|
||||
break;
|
||||
case EmployeePositions.Unassigned:
|
||||
++this.state.numUnassigned;
|
||||
break;
|
||||
case EmployeePositions.Training:
|
||||
++this.state.numTraining;
|
||||
break;
|
||||
default:
|
||||
console.error("Unrecognized employee position: " + to);
|
||||
break;
|
||||
}
|
||||
--this.state.numUnassigned;
|
||||
|
||||
office.assignEmployeeToJob(to);
|
||||
office.calculateEmployeeProductivity({ corporation: this.corp(), industry:division });
|
||||
this.corp().rerender();
|
||||
}
|
||||
|
||||
const unassignEmployee = (from) => {
|
||||
function logWarning(pos) {
|
||||
console.warn(`Cannot unassign from ${pos} because there is nobody assigned to that position`);
|
||||
}
|
||||
|
||||
switch (from) {
|
||||
case EmployeePositions.Operations:
|
||||
if (this.state.numOperations <= 0) { return logWarning(EmployeePositions.Operations); }
|
||||
--this.state.numOperations;
|
||||
break;
|
||||
case EmployeePositions.Engineer:
|
||||
if (this.state.numEngineers <= 0) { return logWarning(EmployeePositions.Operations); }
|
||||
--this.state.numEngineers;
|
||||
break;
|
||||
case EmployeePositions.Business:
|
||||
if (this.state.numBusiness <= 0) { return logWarning(EmployeePositions.Operations); }
|
||||
--this.state.numBusiness;
|
||||
break;
|
||||
case EmployeePositions.Management:
|
||||
if (this.state.numManagement <= 0) { return logWarning(EmployeePositions.Operations); }
|
||||
--this.state.numManagement;
|
||||
break;
|
||||
case EmployeePositions.RandD:
|
||||
if (this.state.numResearch <= 0) { return logWarning(EmployeePositions.Operations); }
|
||||
--this.state.numResearch;
|
||||
break;
|
||||
case EmployeePositions.Unassigned:
|
||||
console.warn(`Tried to unassign from the Unassigned position`);
|
||||
break;
|
||||
case EmployeePositions.Training:
|
||||
if (this.state.numTraining <= 0) { return logWarning(EmployeePositions.Operations); }
|
||||
--this.state.numTraining;
|
||||
break;
|
||||
default:
|
||||
console.error("Unrecognized employee position: " + from);
|
||||
break;
|
||||
}
|
||||
++this.state.numUnassigned;
|
||||
|
||||
office.unassignEmployeeFromJob(from);
|
||||
office.calculateEmployeeProductivity({ corporation: this.corp(), industry:division });
|
||||
this.corp().rerender();
|
||||
}
|
||||
|
||||
const positionHeaderStyle = {
|
||||
fontSize: "15px",
|
||||
margin: "5px 0px 5px 0px",
|
||||
width: "50%",
|
||||
}
|
||||
const assignButtonClass = this.state.numUnassigned > 0 ? "std-button" : "a-link-button-inactive";
|
||||
|
||||
const operationAssignButtonOnClick = () => {
|
||||
assignEmployee(EmployeePositions.Operations);
|
||||
this.corp().rerender();
|
||||
}
|
||||
const operationUnassignButtonOnClick = () => {
|
||||
unassignEmployee(EmployeePositions.Operations);
|
||||
this.corp().rerender();
|
||||
}
|
||||
const operationUnassignButtonClass = this.state.numOperations > 0 ? "std-button" : "a-link-button-inactive";
|
||||
|
||||
const engineerAssignButtonOnClick = () => {
|
||||
assignEmployee(EmployeePositions.Engineer);
|
||||
this.corp().rerender();
|
||||
}
|
||||
const engineerUnassignButtonOnClick = () => {
|
||||
unassignEmployee(EmployeePositions.Engineer);
|
||||
this.corp().rerender();
|
||||
}
|
||||
const engineerUnassignButtonClass = this.state.numEngineers > 0 ? "std-button" : "a-link-button-inactive";
|
||||
|
||||
const businessAssignButtonOnClick = () => {
|
||||
assignEmployee(EmployeePositions.Business);
|
||||
this.corp().rerender();
|
||||
}
|
||||
const businessUnassignButtonOnClick = () => {
|
||||
unassignEmployee(EmployeePositions.Business);
|
||||
this.corp().rerender();
|
||||
}
|
||||
const businessUnassignButtonClass = this.state.numBusiness > 0 ? "std-button" : "a-link-button-inactive";
|
||||
|
||||
const managementAssignButtonOnClick = () => {
|
||||
assignEmployee(EmployeePositions.Management);
|
||||
this.corp().rerender();
|
||||
}
|
||||
const managementUnassignButtonOnClick = () => {
|
||||
unassignEmployee(EmployeePositions.Management);
|
||||
this.corp().rerender();
|
||||
}
|
||||
const managementUnassignButtonClass = this.state.numManagement > 0 ? "std-button" : "a-link-button-inactive";
|
||||
|
||||
const rndAssignButtonOnClick = () => {
|
||||
assignEmployee(EmployeePositions.RandD);
|
||||
this.corp().rerender();
|
||||
}
|
||||
const rndUnassignButtonOnClick = () => {
|
||||
unassignEmployee(EmployeePositions.RandD);
|
||||
this.corp().rerender();
|
||||
}
|
||||
const rndUnassignButtonClass = this.state.numResearch > 0 ? "std-button" : "a-link-button-inactive";
|
||||
|
||||
const trainingAssignButtonOnClick = () => {
|
||||
assignEmployee(EmployeePositions.Training);
|
||||
this.corp().rerender();
|
||||
}
|
||||
const trainingUnassignButtonOnClick = () => {
|
||||
unassignEmployee(EmployeePositions.Training);
|
||||
this.corp().rerender();
|
||||
}
|
||||
const trainingUnassignButtonClass = this.state.numTraining > 0 ? "std-button" : "a-link-button-inactive";
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button className={"std-button tooltip"} onClick={switchModeOnClick}>
|
||||
Switch to Manual Mode
|
||||
<span className={"tooltiptext"}>
|
||||
Switch to Manual Assignment Mode, which allows you to
|
||||
specify which employees should get which jobs
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<p><strong>Unassigned Employees: {this.state.numUnassigned}</strong></p>
|
||||
<br />
|
||||
|
||||
<p>Avg Employee Morale: {numeralWrapper.format(avgMorale, "0.000")}</p>
|
||||
<p>Avg Employee Happiness: {numeralWrapper.format(avgHappiness, "0.000")}</p>
|
||||
<p>Avg Employee Energy: {numeralWrapper.format(avgEnergy, "0.000")}</p>
|
||||
<p>Total Employee Salary: {numeralWrapper.formatMoney(totalSalary)}</p>
|
||||
{
|
||||
vechain &&
|
||||
<p className={"tooltip"} style={{display: "inline-block"}}>
|
||||
Material Production: {numeralWrapper.format(division.getOfficeProductivity(office), "0.000")}
|
||||
<span className={"tooltiptext"}>
|
||||
The base amount of material this office can produce. Does not include
|
||||
production multipliers from upgrades and materials. This value is based off
|
||||
the productivity of your Operations, Engineering, and Management employees
|
||||
</span>
|
||||
</p>
|
||||
}
|
||||
{
|
||||
vechain && <br />
|
||||
}
|
||||
{
|
||||
vechain &&
|
||||
<p className={"tooltip"} style={{display: "inline-block"}}>
|
||||
Product Production: {numeralWrapper.format(division.getOfficeProductivity(office, {forProduct:true}), "0.000")}
|
||||
<span className={"tooltiptext"}>
|
||||
The base amount of any given Product this office can produce. Does not include
|
||||
production multipliers from upgrades and materials. This value is based off
|
||||
the productivity of your Operations, Engineering, and Management employees
|
||||
</span>
|
||||
</p>
|
||||
}
|
||||
{
|
||||
vechain && <br />
|
||||
}
|
||||
{
|
||||
vechain &&
|
||||
<p className={"tooltip"} style={{display: "inline-block"}}>
|
||||
Business Multiplier: x{numeralWrapper.format(division.getBusinessFactor(office), "0.000")}
|
||||
<span className={"tooltiptext"}>
|
||||
The effect this office's 'Business' employees has on boosting sales
|
||||
</span>
|
||||
</p>
|
||||
}
|
||||
{
|
||||
vechain && <br />
|
||||
}
|
||||
|
||||
<h2 className={"tooltip"} style={positionHeaderStyle}>
|
||||
{EmployeePositions.Operations} ({this.state.numOperations})
|
||||
<span className={"tooltiptext"}>
|
||||
Manages supply chain operations. Improves the amount of Materials and Products you produce.
|
||||
</span>
|
||||
</h2>
|
||||
<button className={assignButtonClass} onClick={operationAssignButtonOnClick}>+</button>
|
||||
<button className={operationUnassignButtonClass} onClick={operationUnassignButtonOnClick}>-</button>
|
||||
<br />
|
||||
|
||||
<h2 className={"tooltip"} style={positionHeaderStyle}>
|
||||
{EmployeePositions.Engineer} ({this.state.numEngineers})
|
||||
<span className={"tooltiptext"}>
|
||||
Develops and maintains products and production systems. Increases the quality of
|
||||
everything you produce. Also increases the amount you produce (not as much
|
||||
as Operations, however)
|
||||
</span>
|
||||
</h2>
|
||||
<button className={assignButtonClass} onClick={engineerAssignButtonOnClick}>+</button>
|
||||
<button className={engineerUnassignButtonClass} onClick={engineerUnassignButtonOnClick}>-</button>
|
||||
<br />
|
||||
|
||||
<h2 className={"tooltip"} style={positionHeaderStyle}>
|
||||
{EmployeePositions.Business} ({this.state.numBusiness})
|
||||
<span className={"tooltiptext"}>
|
||||
Handles sales and finances. Improves the amount of Materials and Products you can sell.
|
||||
</span>
|
||||
</h2>
|
||||
<button className={assignButtonClass} onClick={businessAssignButtonOnClick}>+</button>
|
||||
<button className={businessUnassignButtonClass} onClick={businessUnassignButtonOnClick}>-</button>
|
||||
<br />
|
||||
|
||||
<h2 className={"tooltip"} style={positionHeaderStyle}>
|
||||
{EmployeePositions.Management} ({this.state.numManagement})
|
||||
<span className={"tooltiptext"}>
|
||||
Leads and oversees employees and office operations. Improves the effectiveness of
|
||||
Engineer and Operations employees
|
||||
</span>
|
||||
</h2>
|
||||
<button className={assignButtonClass} onClick={managementAssignButtonOnClick}>+</button>
|
||||
<button className={managementUnassignButtonClass} onClick={managementUnassignButtonOnClick}>-</button>
|
||||
<br />
|
||||
|
||||
<h2 className={"tooltip"} style={positionHeaderStyle}>
|
||||
{EmployeePositions.RandD} ({this.state.numResearch})
|
||||
<span className={"tooltiptext"}>
|
||||
Research new innovative ways to improve the company. Generates Scientific Research
|
||||
</span>
|
||||
</h2>
|
||||
<button className={assignButtonClass} onClick={rndAssignButtonOnClick}>+</button>
|
||||
<button className={rndUnassignButtonClass} onClick={rndUnassignButtonOnClick}>-</button>
|
||||
<br />
|
||||
|
||||
<h2 className={"tooltip"} style={positionHeaderStyle}>
|
||||
{EmployeePositions.Training} ({this.state.numTraining})
|
||||
<span className={"tooltiptext"}>
|
||||
Set employee to training, which will increase some of their stats. Employees in training do not affect any company operations.
|
||||
</span>
|
||||
</h2>
|
||||
<button className={assignButtonClass} onClick={trainingAssignButtonOnClick}>+</button>
|
||||
<button className={trainingUnassignButtonClass} onClick={trainingUnassignButtonOnClick}>-</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderManualEmployeeManagement() {
|
||||
const corp = this.corp();
|
||||
const division = this.routing().currentDivision; // Validated in constructor
|
||||
const office = division.offices[this.props.currentCity]; // Validated in constructor
|
||||
|
||||
const switchModeOnClick = () => {
|
||||
this.state.employeeManualAssignMode = false;
|
||||
this.corp().rerender();
|
||||
}
|
||||
|
||||
const employeeInfoDivStyle = {
|
||||
color: "white",
|
||||
margin: "4px",
|
||||
padding: "4px",
|
||||
}
|
||||
|
||||
// Employee Selector
|
||||
const employees = [];
|
||||
for (let i = 0; i < office.employees.length; ++i) {
|
||||
employees.push(<option key={office.employees[i].name}>{office.employees[i].name}</option>)
|
||||
}
|
||||
|
||||
const employeeSelectorOnChange = (e) => {
|
||||
const name = getSelectText(e.target);
|
||||
for (let i = 0; i < office.employees.length; ++i) {
|
||||
if (name === office.employees[i].name) {
|
||||
this.state.employee = office.employees[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
corp.rerender();
|
||||
}
|
||||
|
||||
// Employee Positions Selector
|
||||
const emp = this.state.employee;
|
||||
let employeePositionSelectorInitialValue = null;
|
||||
const employeePositions = [];
|
||||
const positionNames = Object.values(EmployeePositions);
|
||||
for (let i = 0; i < positionNames.length; ++i) {
|
||||
employeePositions.push(<option key={positionNames[i]} value={positionNames[i]}>{positionNames[i]}</option>);
|
||||
if (emp != null && emp.pos === positionNames[i]) {
|
||||
employeePositionSelectorInitialValue = positionNames[i];
|
||||
}
|
||||
}
|
||||
|
||||
const employeePositionSelectorOnChange = (e) => {
|
||||
const pos = getSelectText(e.target);
|
||||
this.state.employee.pos = pos;
|
||||
this.resetEmployeeCount();
|
||||
corp.rerender();
|
||||
}
|
||||
|
||||
// Numeraljs formatter
|
||||
const nf = "0.000";
|
||||
|
||||
// Employee stats (after applying multipliers)
|
||||
const effCre = emp ? emp.cre * corp.getEmployeeCreMultiplier() * division.getEmployeeCreMultiplier() : 0;
|
||||
const effCha = emp ? emp.cha * corp.getEmployeeChaMultiplier() * division.getEmployeeChaMultiplier() : 0;
|
||||
const effInt = emp ? emp.int * corp.getEmployeeIntMultiplier() * division.getEmployeeIntMultiplier() : 0;
|
||||
const effEff = emp ? emp.eff * corp.getEmployeeEffMultiplier() * division.getEmployeeEffMultiplier() : 0;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button className={"std-button tooltip"} onClick={switchModeOnClick}>
|
||||
Switch to Auto Mode
|
||||
<span className={"tooltiptext"}>
|
||||
Switch to Automatic Assignment Mode, which will automatically
|
||||
assign employees to your selected jobs. You simply have to select
|
||||
the number of assignments for each job
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<div style={employeeInfoDivStyle}>
|
||||
<select onChange={employeeSelectorOnChange}>
|
||||
{employees}
|
||||
</select>
|
||||
{
|
||||
this.state.employee != null &&
|
||||
<p>
|
||||
Morale: {numeralWrapper.format(this.state.employee.mor, nf)}
|
||||
<br />
|
||||
Happiness: {numeralWrapper.format(this.state.employee.hap, nf)}
|
||||
<br />
|
||||
Energy: {numeralWrapper.format(this.state.employee.ene, nf)}
|
||||
<br />
|
||||
Age: {numeralWrapper.format(this.state.employee.age, nf)}
|
||||
<br />
|
||||
Intelligence: {numeralWrapper.format(effInt, nf)}
|
||||
<br />
|
||||
Charisma: {numeralWrapper.format(effCha, nf)}
|
||||
<br />
|
||||
Experience: {numeralWrapper.format(this.state.employee.exp, nf)}
|
||||
<br />
|
||||
Creativity: {numeralWrapper.format(effCre, nf)}
|
||||
<br />
|
||||
Efficiency: {numeralWrapper.format(effEff, nf)}
|
||||
<br />
|
||||
Salary: {numeralWrapper.formatMoney(this.state.employee.sal)}
|
||||
</p>
|
||||
}
|
||||
{
|
||||
this.state.employee != null &&
|
||||
<select onChange={employeePositionSelectorOnChange} value={employeePositionSelectorInitialValue}>
|
||||
{employeePositions}
|
||||
</select>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const corp = this.corp();
|
||||
const division = this.routing().currentDivision; // Validated in constructor
|
||||
const office = division.offices[this.props.currentCity]; // Validated in constructor
|
||||
|
||||
const buttonStyle = {
|
||||
fontSize: "13px",
|
||||
}
|
||||
|
||||
// Hire Employee button
|
||||
let hireEmployeeButtonClass = "tooltip";
|
||||
if (office.atCapacity()) {
|
||||
hireEmployeeButtonClass += " a-link-button-inactive";
|
||||
} else {
|
||||
hireEmployeeButtonClass += " std-button";
|
||||
if (office.employees.length === 0) {
|
||||
hireEmployeeButtonClass += " flashing-button";
|
||||
}
|
||||
}
|
||||
|
||||
const hireEmployeeButtonOnClick = () => {
|
||||
office.findEmployees({ corporation: corp, industry: division });
|
||||
}
|
||||
|
||||
// Autohire employee button
|
||||
let autohireEmployeeButtonClass = "tooltip";
|
||||
if (office.atCapacity()) {
|
||||
autohireEmployeeButtonClass += " a-link-button-inactive";
|
||||
} else {
|
||||
autohireEmployeeButtonClass += " std-button";
|
||||
}
|
||||
const autohireEmployeeButtonOnClick = () => {
|
||||
if (office.atCapacity()) { return; }
|
||||
office.hireRandomEmployee();
|
||||
this.corp().rerender();
|
||||
}
|
||||
|
||||
// Upgrade Office Size Button
|
||||
const upgradeOfficeSizeOnClick = this.eventHandler().createUpgradeOfficeSizePopup.bind(this.eventHandler(), office);
|
||||
|
||||
// Throw Office Party
|
||||
const throwOfficePartyOnClick = this.eventHandler().createThrowOfficePartyPopup.bind(this.eventHandler(), office);
|
||||
|
||||
return (
|
||||
<div className={"cmpy-mgmt-employee-panel"}>
|
||||
<h1 style={{ margin: "4px 0px 5px 0px" }}>Office Space</h1>
|
||||
<p>Size: {office.employees.length} / {office.size} employees</p>
|
||||
<button className={hireEmployeeButtonClass} onClick={hireEmployeeButtonOnClick} style={buttonStyle}>
|
||||
Hire Employee
|
||||
{
|
||||
office.employees.length === 0 &&
|
||||
<span className={"tooltiptext"}>
|
||||
You'll need to hire some employees to get your operations started!
|
||||
It's recommended to have at least one employee in every position
|
||||
</span>
|
||||
}
|
||||
</button>
|
||||
<button className={autohireEmployeeButtonClass} onClick={autohireEmployeeButtonOnClick} style={buttonStyle}>
|
||||
Autohire Employee
|
||||
<span className={"tooltiptext"}>
|
||||
Automatically hires an employee and gives him/her a random name
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button className={"std-button tooltip"} onClick={upgradeOfficeSizeOnClick} style={buttonStyle}>
|
||||
Upgrade size
|
||||
<span className={"tooltiptext"}>
|
||||
Upgrade the office's size so that it can hold more employees!
|
||||
</span>
|
||||
</button>
|
||||
{
|
||||
!division.hasResearch("AutoPartyManager") &&
|
||||
<button className={"std-button tooltip"} onClick={throwOfficePartyOnClick} style={buttonStyle}>
|
||||
Throw Party
|
||||
<span className={"tooltiptext"}>
|
||||
"Throw an office party to increase your employee's morale and happiness"
|
||||
</span>
|
||||
</button>
|
||||
}
|
||||
<br />
|
||||
|
||||
{this.renderEmployeeManagement()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
277
src/Corporation/ui/IndustryOverview.jsx
Normal file
277
src/Corporation/ui/IndustryOverview.jsx
Normal file
@@ -0,0 +1,277 @@
|
||||
// React Component for displaying an Industry's overview information
|
||||
// (top-left panel in the Industry UI)
|
||||
import React from "react";
|
||||
import { BaseReactComponent } from "./BaseReactComponent";
|
||||
|
||||
import { OfficeSpace } from "../Corporation";
|
||||
import { Industries } from "../IndustryData";
|
||||
import { IndustryUpgrades } from "../IndustryUpgrades";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
import { createProgressBarText } from "../../../utils/helpers/createProgressBarText";
|
||||
|
||||
export class IndustryOverview extends BaseReactComponent {
|
||||
renderMakeProductButton() {
|
||||
const corp = this.corp();
|
||||
const division = this.routing().currentDivision; // Validated inside render()
|
||||
|
||||
var createProductButtonText, createProductPopupText;
|
||||
switch(division.type) {
|
||||
case Industries.Food:
|
||||
createProductButtonText = "Build Restaurant";
|
||||
createProductPopupText = "Build and manage a new restaurant!"
|
||||
break;
|
||||
case Industries.Tobacco:
|
||||
createProductButtonText = "Create Product";
|
||||
createProductPopupText = "Create a new tobacco product!";
|
||||
break;
|
||||
case Industries.Pharmaceutical:
|
||||
createProductButtonText = "Create Drug";
|
||||
createProductPopupText = "Design and develop a new pharmaceutical drug!";
|
||||
break;
|
||||
case Industries.Computer:
|
||||
case "Computer":
|
||||
createProductButtonText = "Create Product";
|
||||
createProductPopupText = "Design and manufacture a new computer hardware product!";
|
||||
break;
|
||||
case Industries.Robotics:
|
||||
createProductButtonText = "Design Robot";
|
||||
createProductPopupText = "Design and create a new robot or robotic system!";
|
||||
break;
|
||||
case Industries.Software:
|
||||
createProductButtonText = "Develop Software";
|
||||
createProductPopupText = "Develop a new piece of software!";
|
||||
break;
|
||||
case Industries.Healthcare:
|
||||
createProductButtonText = "Build Hospital";
|
||||
createProductPopupText = "Build and manage a new hospital!";
|
||||
break;
|
||||
case Industries.RealEstate:
|
||||
createProductButtonText = "Develop Property";
|
||||
createProductPopupText = "Develop a new piece of real estate property!";
|
||||
break;
|
||||
default:
|
||||
createProductButtonText = "Create Product";
|
||||
createProductPopupText = "Create a new product!";
|
||||
return "";
|
||||
}
|
||||
createProductPopupText += "<br><br>To begin developing a product, " +
|
||||
"first choose the city in which it will be designed. The stats of your employees " +
|
||||
"in the selected city affect the properties of the finished product, such as its " +
|
||||
"quality, performance, and durability.<br><br>" +
|
||||
"You can also choose to invest money in the design and marketing of " +
|
||||
"the product. Investing money in its design will result in a superior product. " +
|
||||
"Investing money in marketing the product will help the product's sales.";
|
||||
|
||||
const hasMaxProducts = division.hasMaximumNumberProducts();
|
||||
|
||||
const className = hasMaxProducts ? "a-link-button-inactive tooltip" : "std-button";
|
||||
const onClick = this.eventHandler().createMakeProductPopup.bind(this.eventHandler(), createProductPopupText, division);
|
||||
const buttonStyle = {
|
||||
margin: "6px",
|
||||
display: "inline-block",
|
||||
}
|
||||
|
||||
return (
|
||||
<button className={className} onClick={onClick} style={buttonStyle}>
|
||||
{createProductButtonText}
|
||||
{
|
||||
hasMaxProducts &&
|
||||
<span className={"tooltiptext"}>
|
||||
You have reached the maximum number of products: {division.getMaximumNumberProducts()}
|
||||
</span>
|
||||
}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
renderText() {
|
||||
const corp = this.corp();
|
||||
const division = this.routing().currentDivision; // Validated inside render()
|
||||
|
||||
const vechain = (corp.unlockUpgrades[4] === 1);
|
||||
const profit = division.lastCycleRevenue.minus(division.lastCycleExpenses).toNumber();
|
||||
|
||||
const genInfo = `Industry: ${division.type} (Corp Funds: ${numeralWrapper.formatMoney(corp.funds.toNumber())})`;
|
||||
const awareness = `Awareness: ${numeralWrapper.format(division.awareness, "0.000")}`;
|
||||
const popularity = `Popularity: ${numeralWrapper.format(division.popularity, "0.000")}`;
|
||||
|
||||
let advertisingInfo = false;
|
||||
let advertisingTooltip;
|
||||
const advertisingFactors = division.getAdvertisingFactors();
|
||||
const awarenessFac = advertisingFactors[1];
|
||||
const popularityFac = advertisingFactors[2];
|
||||
const ratioFac = advertisingFactors[3];
|
||||
const totalAdvertisingFac = advertisingFactors[0];
|
||||
if (vechain) { advertisingInfo = true; }
|
||||
|
||||
const revenue = `Revenue: ${numeralWrapper.formatMoney(division.lastCycleRevenue.toNumber())} / s`;
|
||||
const expenses = `Expenses: ${numeralWrapper.formatMoney(division.lastCycleExpenses.toNumber())} /s`;
|
||||
const profitStr = `Profit: ${numeralWrapper.formatMoney(profit)} / s`;
|
||||
|
||||
const productionMultHelpTipOnClick = () => {
|
||||
// Wrapper for createProgressBarText()
|
||||
// Converts the industry's "effectiveness factors"
|
||||
// into a graphic (string) depicting how high that effectiveness is
|
||||
function convertEffectFacToGraphic(fac) {
|
||||
return createProgressBarText({
|
||||
progress: fac,
|
||||
totalTicks: 20,
|
||||
});
|
||||
}
|
||||
|
||||
dialogBoxCreate("Owning Hardware, Robots, AI Cores, and Real Estate " +
|
||||
"can boost your Industry's production. The effect these " +
|
||||
"materials have on your production varies between Industries. " +
|
||||
"For example, Real Estate may be very effective for some Industries, " +
|
||||
"but ineffective for others.<br><br>" +
|
||||
"This division's production multiplier is calculated by summing " +
|
||||
"the individual production multiplier of each of its office locations. " +
|
||||
"This production multiplier is applied to each office. Therefore, it is " +
|
||||
"beneficial to expand into new cities as this can greatly increase the " +
|
||||
"production multiplier of your entire Division.<br><br>" +
|
||||
"Below are approximations for how effective each material is at boosting " +
|
||||
"this industry's production multiplier (Bigger bars = more effective):<br><br>" +
|
||||
`Hardware: ${convertEffectFacToGraphic(division.hwFac)}<br>` +
|
||||
`Robots: ${convertEffectFacToGraphic(division.robFac)}<br>` +
|
||||
`AI Cores: ${convertEffectFacToGraphic(division.aiFac)}<br>` +
|
||||
`Real Estate: ${convertEffectFacToGraphic(division.reFac)}`);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{genInfo}
|
||||
<br /> <br />
|
||||
{awareness} <br />
|
||||
{popularity} <br />
|
||||
{
|
||||
(advertisingInfo !== false) &&
|
||||
<p className={"tooltip"}>Advertising Multiplier: x{numeralWrapper.format(totalAdvertisingFac, "0.000")}
|
||||
<span className={"tooltiptext cmpy-mgmt-advertising-info"}>
|
||||
Total multiplier for this industrys sales due to its awareness and popularity
|
||||
<br />
|
||||
Awareness Bonus: x{numeralWrapper.format(Math.pow(awarenessFac, 0.85), "0.000")}
|
||||
<br />
|
||||
Popularity Bonus: x{numeralWrapper.format(Math.pow(popularityFac, 0.85), "0.000")}
|
||||
<br />
|
||||
Ratio Multiplier: x{numeralWrapper.format(Math.pow(ratioFac, 0.85), "0.000")}
|
||||
</span>
|
||||
</p>
|
||||
}
|
||||
{advertisingInfo}
|
||||
<br /><br />
|
||||
{revenue} <br />
|
||||
{expenses} <br />
|
||||
{profitStr}
|
||||
<br /> <br />
|
||||
<p className={"tooltip"}>
|
||||
Production Multiplier: {numeralWrapper.format(division.prodMult, "0.00")}
|
||||
<span className={"tooltiptext"}>
|
||||
Production gain from owning production-boosting materials
|
||||
such as hardware, Robots, AI Cores, and Real Estate
|
||||
</span>
|
||||
</p>
|
||||
<div className={"help-tip"} onClick={productionMultHelpTipOnClick}>?</div>
|
||||
<br /> <br />
|
||||
<p className={"tooltip"}>
|
||||
Scientific Research: {numeralWrapper.format(division.sciResearch.qty, "0.000a")}
|
||||
<span className={"tooltiptext"}>
|
||||
Scientific Research increases the quality of the materials and
|
||||
products that you produce.
|
||||
</span>
|
||||
</p>
|
||||
<button className={"help-tip"} onClick={division.createResearchBox.bind(division)}>
|
||||
Research
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderUpgrades() {
|
||||
const corp = this.corp();
|
||||
const division = this.routing().currentDivision; // Validated inside render()
|
||||
const office = division.offices[this.props.currentCity];
|
||||
if (!(office instanceof OfficeSpace)) {
|
||||
throw new Error(`Current City (${this.props.currentCity}) for UI does not have an OfficeSpace object`);
|
||||
}
|
||||
|
||||
const upgrades = [];
|
||||
for (const index in IndustryUpgrades) {
|
||||
const upgrade = IndustryUpgrades[index];
|
||||
|
||||
// AutoBrew research disables the Coffee upgrade
|
||||
if (division.hasResearch("AutoBrew") && upgrade[4] === "Coffee") { continue; }
|
||||
|
||||
const i = upgrade[0];
|
||||
const baseCost = upgrade[1];
|
||||
const priceMult = upgrade[2];
|
||||
let cost = 0;
|
||||
switch (i) {
|
||||
case 0: //Coffee, cost is static per employee
|
||||
cost = office.employees.length * baseCost;
|
||||
break;
|
||||
default:
|
||||
cost = baseCost * Math.pow(priceMult, division.upgrades[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
const onClick = () => {
|
||||
if (corp.funds.lt(cost)) {
|
||||
dialogBoxCreate("Insufficient funds");
|
||||
} else {
|
||||
corp.funds = corp.funds.minus(cost);
|
||||
division.upgrade(upgrade, {
|
||||
corporation: corp,
|
||||
office: office,
|
||||
});
|
||||
// corp.displayDivisionContent(division, city);
|
||||
corp.rerender();
|
||||
}
|
||||
}
|
||||
|
||||
upgrades.push(this.renderUpgrade({
|
||||
onClick: onClick,
|
||||
text: `${upgrade[4]} - ${numeralWrapper.formatMoney(cost)}`,
|
||||
tooltip: upgrade[5],
|
||||
}));
|
||||
}
|
||||
|
||||
return upgrades;
|
||||
}
|
||||
|
||||
renderUpgrade(props) {
|
||||
return (
|
||||
<div className={"cmpy-mgmt-upgrade-div tooltip"} onClick={props.onClick} key={props.text}>
|
||||
{props.text}
|
||||
{
|
||||
props.tooltip != null &&
|
||||
<span className={"tooltiptext"}>{props.tooltip}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const division = this.routing().currentDivision;
|
||||
if (division == null) {
|
||||
throw new Error(`Routing does not hold reference to the current Industry`);
|
||||
}
|
||||
|
||||
const makeProductButton = this.renderMakeProductButton();
|
||||
|
||||
return (
|
||||
<div className={"cmpy-mgmt-industry-overview-panel"}>
|
||||
{this.renderText()}
|
||||
<br />
|
||||
|
||||
<u className={"industry-purchases-and-upgrades-header"}>Purchases & Upgrades</u><br />
|
||||
{this.renderUpgrades()} <br />
|
||||
|
||||
{
|
||||
division.makesProducts &&
|
||||
makeProductButton
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
535
src/Corporation/ui/IndustryWarehouse.jsx
Normal file
535
src/Corporation/ui/IndustryWarehouse.jsx
Normal file
@@ -0,0 +1,535 @@
|
||||
// React Component for displaying an Industry's warehouse information
|
||||
// (right-side panel in the Industry UI)
|
||||
import React from "react";
|
||||
import { BaseReactComponent } from "./BaseReactComponent";
|
||||
|
||||
import { OfficeSpace,
|
||||
WarehouseInitialCost,
|
||||
WarehouseUpgradeBaseCost,
|
||||
ProductProductionCostRatio } from "../Corporation";
|
||||
import { Material } from "../Material";
|
||||
import { Product } from "../Product";
|
||||
import { Warehouse } from "../Warehouse";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
import { isString } from "../../../utils/helpers/isString";
|
||||
|
||||
// Creates the UI for a single Product type
|
||||
function ProductComponent(props) {
|
||||
const corp = props.corp;
|
||||
const division = props.division;
|
||||
const warehouse = props.warehouse;
|
||||
const city = props.city;
|
||||
const product = props.product;
|
||||
const eventHandler = props.eventHandler;
|
||||
|
||||
// Numeraljs formatters
|
||||
const nf = "0.000";
|
||||
const nfB = "0.000a"; // For numbers that might be big
|
||||
|
||||
const hasUpgradeDashboard = division.hasResearch("uPgrade: Dashboard");
|
||||
|
||||
// Total product gain = production - sale
|
||||
const totalGain = product.data[city][1] - product.data[city][2];
|
||||
|
||||
// Sell button
|
||||
let sellButtonText;
|
||||
if (product.sllman[city][0]) {
|
||||
if (isString(product.sllman[city][1])) {
|
||||
sellButtonText = `Sell (${numeralWrapper.format(product.data[city][2], nfB)}/${product.sllman[city][1]})`;
|
||||
} else {
|
||||
sellButtonText = `Sell (${numeralWrapper.format(product.data[city][2], nfB)}/${numeralWrapper.format(product.sllman[city][1], nfB)})`;
|
||||
}
|
||||
} else {
|
||||
sellButtonText = "Sell (0.000/0.000)";
|
||||
}
|
||||
|
||||
if (product.marketTa2) {
|
||||
sellButtonText += (" @ " + numeralWrapper.formatMoney(product.marketTa2Price[city]));
|
||||
} else if (product.marketTa1) {
|
||||
const markupLimit = product.rat / product.mku;
|
||||
sellButtonText += (" @ " + numeralWrapper.formatMoney(product.pCost + markupLimit));
|
||||
} else if (product.sCost) {
|
||||
if (isString(product.sCost)) {
|
||||
sellButtonText += (" @ " + product.sCost);
|
||||
} else {
|
||||
sellButtonText += (" @ " + numeralWrapper.format(product.sCost, "$0.000a"));
|
||||
}
|
||||
}
|
||||
const sellButtonOnClick = eventHandler.createSellProductPopup.bind(eventHandler, product, city);
|
||||
|
||||
// Limit Production button
|
||||
let limitProductionButtonText = "Limit Production";
|
||||
if (product.prdman[city][0]) {
|
||||
limitProductionButtonText += " (" + numeralWrapper.format(product.prdman[city][1], nf) + ")";
|
||||
}
|
||||
const limitProductionButtonOnClick = eventHandler.createLimitProductProdutionPopup.bind(eventHandler, product, city);
|
||||
|
||||
// Discontinue Button
|
||||
const discontinueButtonOnClick = eventHandler.createDiscontinueProductPopup.bind(eventHandler, product, division);
|
||||
|
||||
// Market TA button
|
||||
const marketTaButtonOnClick = eventHandler.createProductMarketTaPopup.bind(eventHandler, product, division);
|
||||
|
||||
// Unfinished Product
|
||||
if (!product.fin) {
|
||||
if (hasUpgradeDashboard) {
|
||||
return (
|
||||
<div className={"cmpy-mgmt-warehouse-product-div"}>
|
||||
<p>Designing {product.name}...</p><br />
|
||||
<p>{numeralWrapper.format(product.prog, "0.00")}% complete</p>
|
||||
<br />
|
||||
|
||||
<div>
|
||||
<button className={"std-button"} onClick={sellButtonOnClick}>
|
||||
{sellButtonText}
|
||||
</button><br />
|
||||
<button className={"std-button"} onClick={limitProductionButtonOnClick}>
|
||||
{limitProductionButtonText}
|
||||
</button>
|
||||
<button className={"std-button"} onClick={discontinueButtonOnClick}>
|
||||
Discontinue
|
||||
</button>
|
||||
{
|
||||
division.hasResearch("Market-TA.I") &&
|
||||
<button className={"std-button"} onClick={marketTaButtonOnClick}>
|
||||
Market-TA
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div className={"cmpy-mgmt-warehouse-product-div"}>
|
||||
<p>Designing {product.name}...</p><br />
|
||||
<p>{numeralWrapper.format(product.prog, "0.00")}% complete</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={"cmpy-mgmt-warehouse-product-div"}>
|
||||
<p className={"tooltip"}>
|
||||
{product.name}: {numeralWrapper.format(product.data[city][0], nfB)} ({numeralWrapper.format(totalGain, nfB)}/s)
|
||||
<span className={"tooltiptext"}>
|
||||
Prod: {numeralWrapper.format(product.data[city][1], nfB)}/s
|
||||
<br />
|
||||
Sell: {numeralWrapper.format(product.data[city][2], nfB)} /s
|
||||
</span>
|
||||
</p><br />
|
||||
<p className={"tooltip"}>
|
||||
Rating: {numeralWrapper.format(product.rat, nf)}
|
||||
<span className={"tooltiptext"}>
|
||||
Quality: {numeralWrapper.format(product.qlt, nf)} <br />
|
||||
Performance: {numeralWrapper.format(product.per, nf)} <br />
|
||||
Durability: {numeralWrapper.format(product.dur, nf)} <br />
|
||||
Reliability: {numeralWrapper.format(product.rel, nf)} <br />
|
||||
Aesthetics: {numeralWrapper.format(product.aes, nf)} <br />
|
||||
Features: {numeralWrapper.format(product.fea, nf)}
|
||||
{
|
||||
corp.unlockUpgrades[2] === 1 && <br />
|
||||
}
|
||||
{
|
||||
corp.unlockUpgrades[2] === 1 &&
|
||||
"Demand: " + numeralWrapper.format(product.dmd, nf)
|
||||
}
|
||||
{
|
||||
corp.unlockUpgrades[3] === 1 && <br />
|
||||
}
|
||||
{
|
||||
corp.unlockUpgrades[3] === 1 &&
|
||||
"Competition: " + numeralWrapper.format(product.cmp, nf)
|
||||
}
|
||||
|
||||
</span>
|
||||
</p><br />
|
||||
<p className={"tooltip"}>
|
||||
Est. Production Cost: {numeralWrapper.formatMoney(product.pCost / ProductProductionCostRatio)}
|
||||
<span className={"tooltiptext"}>
|
||||
An estimate of the material cost it takes to create this Product.
|
||||
</span>
|
||||
</p><br />
|
||||
<p className={"tooltip"}>
|
||||
Est. Market Price: {numeralWrapper.formatMoney(product.pCost)}
|
||||
<span className={"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>
|
||||
|
||||
<div>
|
||||
<button className={"std-button"} onClick={sellButtonOnClick}>
|
||||
{sellButtonText}
|
||||
</button><br />
|
||||
<button className={"std-button"} onClick={limitProductionButtonOnClick}>
|
||||
{limitProductionButtonText}
|
||||
</button>
|
||||
<button className={"std-button"} onClick={discontinueButtonOnClick}>
|
||||
Discontinue
|
||||
</button>
|
||||
{
|
||||
division.hasResearch("Market-TA.I") &&
|
||||
<button className={"std-button"} onClick={marketTaButtonOnClick}>
|
||||
Market-TA
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Creates the UI for a single Material type
|
||||
function MaterialComponent(props) {
|
||||
const corp = props.corp;
|
||||
const division = props.division;
|
||||
const warehouse = props.warehouse;
|
||||
const city = props.city;
|
||||
const mat = props.mat;
|
||||
const eventHandler = props.eventHandler;
|
||||
const markupLimit = mat.getMarkupLimit();
|
||||
const office = division.offices[city];
|
||||
if (!(office instanceof OfficeSpace)) {
|
||||
throw new Error(`Could not get OfficeSpace object for this city (${city})`);
|
||||
}
|
||||
|
||||
// Numeraljs formatter
|
||||
const nf = "0.000";
|
||||
const nfB = "0.000a"; // For numbers that might be biger
|
||||
|
||||
// Total gain or loss of this material (per second)
|
||||
const totalGain = mat.buy + mat.prd + mat.imp - mat.sll - mat.totalExp;
|
||||
|
||||
// Competition and demand info, if they're unlocked
|
||||
let cmpAndDmdText = "";
|
||||
if (corp.unlockUpgrades[2] === 1) {
|
||||
cmpAndDmdText += "<br>Demand: " + numeralWrapper.format(mat.dmd, nf);
|
||||
}
|
||||
if (corp.unlockUpgrades[3] === 1) {
|
||||
cmpAndDmdText += "<br>Competition: " + numeralWrapper.format(mat.cmp, nf);
|
||||
}
|
||||
|
||||
// Flag that determines whether this industry is "new" and the current material should be
|
||||
// marked with flashing-red lights
|
||||
const tutorial = division.newInd && Object.keys(division.reqMats).includes(mat.name) &&
|
||||
mat.buy === 0 && mat.imp === 0;
|
||||
|
||||
// Purchase material button
|
||||
const purchaseButtonText = `Buy (${numeralWrapper.format(mat.buy, nfB)})`;
|
||||
const purchaseButtonClass = tutorial ? "std-button flashing-button tooltip" : "std-button";
|
||||
const purchaseButtonOnClick = eventHandler.createPurchaseMaterialPopup.bind(eventHandler, mat, division, warehouse);
|
||||
|
||||
// Export material button
|
||||
const exportButtonOnClick = eventHandler.createExportMaterialPopup.bind(eventHandler, mat);
|
||||
|
||||
// Sell material button
|
||||
let sellButtonText;
|
||||
if (mat.sllman[0]) {
|
||||
if (isString(mat.sllman[1])) {
|
||||
sellButtonText = `Sell (${numeralWrapper.format(mat.sll, nfB)}/${mat.sllman[1]})`
|
||||
} else {
|
||||
sellButtonText = `Sell (${numeralWrapper.format(mat.sll, nfB)}/${numeralWrapper.format(mat.sllman[1], nfB)})`;
|
||||
}
|
||||
|
||||
if (mat.marketTa2) {
|
||||
sellButtonText += " @ " + numeralWrapper.formatMoney(mat.marketTa2Price);
|
||||
} else if (mat.marketTa1) {
|
||||
sellButtonText += " @ " + numeralWrapper.formatMoney(mat.bCost + markupLimit);
|
||||
} else if (mat.sCost) {
|
||||
if (isString(mat.sCost)) {
|
||||
var sCost = mat.sCost.replace(/MP/g, mat.bCost);
|
||||
sellButtonText += " @ " + numeralWrapper.formatMoney(eval(sCost));
|
||||
} else {
|
||||
sellButtonText += " @ " + numeralWrapper.formatMoney(mat.sCost);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sellButtonText = "Sell (0.000/0.000)";
|
||||
}
|
||||
const sellButtonOnClick = eventHandler.createSellMaterialPopup.bind(eventHandler, mat);
|
||||
|
||||
// Market TA button
|
||||
const marketTaButtonOnClick = eventHandler.createMaterialMarketTaPopup.bind(eventHandler, mat, division);
|
||||
|
||||
return (
|
||||
<div className={"cmpy-mgmt-warehouse-material-div"}>
|
||||
<div style={{display: "inline-block"}}>
|
||||
<p className={"tooltip"}>
|
||||
{mat.name}: {numeralWrapper.format(mat.qty, nfB)} ({numeralWrapper.format(totalGain, nfB)}/s)
|
||||
<span className={"tooltiptext"}>
|
||||
Buy: {numeralWrapper.format(mat.buy, nfB)} <br />
|
||||
Prod: {numeralWrapper.format(mat.prd, nfB)} <br />
|
||||
Sell: {numeralWrapper.format(mat.sll, nfB)} <br />
|
||||
Export: {numeralWrapper.format(mat.totalExp, nfB)} <br />
|
||||
Import: {numeralWrapper.format(mat.imp, nfB)}
|
||||
{
|
||||
corp.unlockUpgrades[2] === 1 && <br />
|
||||
}
|
||||
{
|
||||
corp.unlockUpgrades[2] === 1 &&
|
||||
"Demand: " + numeralWrapper.format(mat.dmd, nf)
|
||||
}
|
||||
{
|
||||
corp.unlockUpgrades[3] === 1 && <br />
|
||||
}
|
||||
{
|
||||
corp.unlockUpgrades[3] === 1 &&
|
||||
"Competition: " + numeralWrapper.format(mat.cmp, nf)
|
||||
}
|
||||
</span>
|
||||
</p><br />
|
||||
<p className={"tooltip"}>
|
||||
MP: {numeralWrapper.formatMoney(mat.bCost)}
|
||||
<span className={"tooltiptext"}>
|
||||
Market Price: The price you would pay if you were to buy this material on the market
|
||||
</span>
|
||||
</p> <br />
|
||||
<p className={"tooltip"}>
|
||||
Quality: {numeralWrapper.format(mat.qlt, "0.00a")}
|
||||
<span className={"tooltiptext"}>
|
||||
The quality of your material. Higher quality will lead to more sales
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style={{display: "inline-block"}}>
|
||||
<button className={purchaseButtonClass} onClick={purchaseButtonOnClick}>
|
||||
{purchaseButtonText}
|
||||
{
|
||||
tutorial &&
|
||||
<span className={"tooltiptext"}>
|
||||
Purchase your required materials to get production started!
|
||||
</span>
|
||||
}
|
||||
</button>
|
||||
|
||||
{
|
||||
corp.unlockUpgrades[0] === 1 &&
|
||||
<button className={"std-button"} onClick={exportButtonOnClick}>
|
||||
Export
|
||||
</button>
|
||||
}
|
||||
<br />
|
||||
|
||||
<button className={"std-button"} onClick={sellButtonOnClick}>
|
||||
{sellButtonText}
|
||||
</button>
|
||||
|
||||
{
|
||||
division.hasResearch("Market-TA.I") &&
|
||||
<button className={"std-button"} onClick={marketTaButtonOnClick}>
|
||||
Market-TA
|
||||
</button>
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export class IndustryWarehouse extends BaseReactComponent {
|
||||
// Returns a boolean indicating whether the given material is relevant for the
|
||||
// current industry.
|
||||
isRelevantMaterial(matName, division) {
|
||||
// Materials that affect Production multiplier
|
||||
const prodMultiplierMats = ["Hardware", "Robots", "AICores", "RealEstate"];
|
||||
|
||||
if (Object.keys(division.reqMats).includes(matName)) { return true; }
|
||||
if (division.prodMats.includes(matName)) { return true; }
|
||||
if (prodMultiplierMats.includes(matName)) { return true; }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
renderWarehouseUI() {
|
||||
const corp = this.corp();
|
||||
const division = this.routing().currentDivision; // Validated in render()
|
||||
const warehouse = division.warehouses[this.props.currentCity]; // Validated in render()
|
||||
|
||||
// General Storage information at the top
|
||||
const sizeUsageStyle = {
|
||||
color: warehouse.sizeUsed >= warehouse.size ? "red" : "white",
|
||||
margin: "5px",
|
||||
}
|
||||
|
||||
// Upgrade Warehouse size button
|
||||
const sizeUpgradeCost = WarehouseUpgradeBaseCost * Math.pow(1.07, warehouse.level + 1);
|
||||
const canAffordUpgrade = (corp.funds.gt(sizeUpgradeCost));
|
||||
const upgradeWarehouseClass = canAffordUpgrade ? "std-button" : "a-link-button-inactive";
|
||||
const upgradeWarehouseOnClick = () => {
|
||||
++warehouse.level;
|
||||
warehouse.updateSize(corp, division);
|
||||
corp.funds = corp.funds.minus(sizeUpgradeCost);
|
||||
corp.rerender();
|
||||
return;
|
||||
}
|
||||
|
||||
// Industry material Requirements
|
||||
let generalReqsText = "This Industry uses [" + Object.keys(division.reqMats).join(", ") +
|
||||
"] in order to ";
|
||||
if (division.prodMats.length > 0) {
|
||||
generalReqsText += "produce [" + division.prodMats.join(", ") + "] ";
|
||||
if (division.makesProducts) {
|
||||
generalReqsText += " and " + division.getProductDescriptionText();
|
||||
}
|
||||
} else if (division.makesProducts) {
|
||||
generalReqsText += (division.getProductDescriptionText() + ".");
|
||||
}
|
||||
|
||||
const ratioLines = [];
|
||||
for (const matName in division.reqMats) {
|
||||
if (division.reqMats.hasOwnProperty(matName)) {
|
||||
const text = [" *", division.reqMats[matName], matName].join(" ");
|
||||
ratioLines.push((
|
||||
<div key={matName}>
|
||||
<p>{text}</p>
|
||||
</div>
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let createdItemsText = "in order to create ";
|
||||
if (division.prodMats.length > 0) {
|
||||
createdItemsText += "one of each produced Material (" + division.prodMats.join(", ") + ") ";
|
||||
if (division.makesProducts) {
|
||||
createdItemsText += "or to create one of its Products";
|
||||
}
|
||||
} else if (division.makesProducts) {
|
||||
createdItemsText += "one of its Products";
|
||||
}
|
||||
|
||||
// Current State:
|
||||
let stateText;
|
||||
switch(division.state) {
|
||||
case "START":
|
||||
stateText = "Current state: Preparing...";
|
||||
break;
|
||||
case "PURCHASE":
|
||||
stateText = "Current state: Purchasing materials...";
|
||||
break;
|
||||
case "PRODUCTION":
|
||||
stateText = "Current state: Producing materials and/or products...";
|
||||
break;
|
||||
case "SALE":
|
||||
stateText = "Current state: Selling materials and/or products...";
|
||||
break;
|
||||
case "EXPORT":
|
||||
stateText = "Current state: Exporting materials and/or products...";
|
||||
break;
|
||||
default:
|
||||
console.error(`Invalid state: ${division.state}`);
|
||||
break;
|
||||
}
|
||||
|
||||
// Smart Supply Checkbox
|
||||
const smartSupplyCheckboxId = "cmpy-mgmt-smart-supply-checkbox";
|
||||
const smartSupplyOnChange = (e) => {
|
||||
warehouse.smartSupplyEnabled = e.target.checked;
|
||||
corp.rerender();
|
||||
}
|
||||
|
||||
// Create React components for materials
|
||||
const mats = [];
|
||||
for (const matName in warehouse.materials) {
|
||||
if (warehouse.materials[matName] instanceof Material) {
|
||||
// Only create UI for materials that are relevant for the industry
|
||||
if (this.isRelevantMaterial(matName, division)) {
|
||||
mats.push(<MaterialComponent
|
||||
city={this.props.currentCity}
|
||||
corp={corp}
|
||||
division={division}
|
||||
eventHandler={this.eventHandler()}
|
||||
key={matName}
|
||||
mat={warehouse.materials[matName]}
|
||||
warehouse={warehouse} />);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create React components for products
|
||||
const products = [];
|
||||
if (division.makesProducts && Object.keys(division.products).length > 0) {
|
||||
for (const productName in division.products) {
|
||||
if (division.products[productName] instanceof Product) {
|
||||
products.push(<ProductComponent
|
||||
city={this.props.currentCity}
|
||||
corp={corp}
|
||||
division={division}
|
||||
eventHandler={this.eventHandler()}
|
||||
key={productName}
|
||||
product={division.products[productName]}
|
||||
warehouse={warehouse} />);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={"cmpy-mgmt-warehouse-panel"}>
|
||||
<p className={"tooltip"} style={sizeUsageStyle}>
|
||||
Storage: {numeralWrapper.formatBigNumber(warehouse.sizeUsed)} / {numeralWrapper.formatBigNumber(warehouse.size)}
|
||||
<span className={"tooltiptext"} dangerouslySetInnerHTML={{__html: warehouse.breakdown}}></span>
|
||||
</p>
|
||||
|
||||
<button className={upgradeWarehouseClass} onClick={upgradeWarehouseOnClick}>
|
||||
Upgrade Warehouse Size - {numeralWrapper.formatMoney(sizeUpgradeCost)}
|
||||
</button>
|
||||
|
||||
<p>{generalReqsText}. The exact requirements for production are:</p><br />
|
||||
{ratioLines}<br />
|
||||
<p>{createdItemsText}</p>
|
||||
<p>
|
||||
To get started with production, purchase your required materials
|
||||
or import them from another of your company's divisions.
|
||||
</p><br />
|
||||
|
||||
<p>{stateText}</p>
|
||||
|
||||
{
|
||||
corp.unlockUpgrades[1] &&
|
||||
<div>
|
||||
<label style={{color: "white"}} htmlFor={smartSupplyCheckboxId}>
|
||||
Enable Smart Supply
|
||||
</label>
|
||||
<input type={"checkbox"}
|
||||
id={smartSupplyCheckboxId}
|
||||
onChange={smartSupplyOnChange}
|
||||
style={{margin: "3px"}}
|
||||
checked={warehouse.smartSupplyEnabled}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
{mats}
|
||||
|
||||
{products}
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const corp = this.corp();
|
||||
const division = this.routing().currentDivision;
|
||||
if (division == null) {
|
||||
throw new Error(`Routing does not hold reference to the current Industry`);
|
||||
}
|
||||
const warehouse = division.warehouses[this.props.currentCity];
|
||||
|
||||
const newWarehouseOnClick = this.eventHandler().purchaseWarehouse.bind(this.eventHandler(), division, this.props.currentCity);
|
||||
|
||||
if (warehouse instanceof Warehouse) {
|
||||
return this.renderWarehouseUI();
|
||||
} else {
|
||||
return (
|
||||
<div className={"cmpy-mgmt-warehouse-panel"}>
|
||||
<button className={"std-button"} onClick={newWarehouseOnClick}>
|
||||
Purchase Warehouse ({numeralWrapper.formatMoney(WarehouseInitialCost)})
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
36
src/Corporation/ui/LevelableUpgrade.jsx
Normal file
36
src/Corporation/ui/LevelableUpgrade.jsx
Normal file
@@ -0,0 +1,36 @@
|
||||
// React components for the levelable upgrade buttons on the overview panel
|
||||
import React from "react";
|
||||
import { BaseReactComponent } from "./BaseReactComponent";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
|
||||
export class LevelableUpgrade extends BaseReactComponent {
|
||||
render() {
|
||||
const data = this.props.upgradeData;
|
||||
const level = this.props.upgradeLevel;
|
||||
|
||||
const baseCost = data[1];
|
||||
const priceMult = data[2];
|
||||
const cost = baseCost * Math.pow(priceMult, level);
|
||||
|
||||
const text = `${data[4]} - ${numeralWrapper.formatMoney(cost)}`
|
||||
const tooltip = data[5];
|
||||
const onClick = () => {
|
||||
const corp = this.corp();
|
||||
if (corp.funds.lt(cost)) {
|
||||
dialogBoxCreate("Insufficient funds");
|
||||
} else {
|
||||
corp.upgrade(data);
|
||||
corp.rerender();
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={"cmpy-mgmt-upgrade-div tooltip"} style={{"width" : "45%"}} onClick={onClick}>
|
||||
{text}
|
||||
<span className={"tooltiptext"}>{tooltip}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
106
src/Corporation/ui/MainPanel.jsx
Normal file
106
src/Corporation/ui/MainPanel.jsx
Normal file
@@ -0,0 +1,106 @@
|
||||
// React Component for the element that contains the actual info/data
|
||||
// for the Corporation UI. This panel lies below the header tabs and will
|
||||
// be filled with whatever is needed based on the routing/navigation
|
||||
import React from "react";
|
||||
import { BaseReactComponent } from "./BaseReactComponent";
|
||||
|
||||
import { CityTabs } from "./CityTabs";
|
||||
import { Industry } from "./Industry";
|
||||
import { Overview } from "./Overview";
|
||||
import { overviewPage } from "./Routing";
|
||||
|
||||
import { OfficeSpace } from "../Corporation";
|
||||
|
||||
import { CityName } from "../../Locations/data/CityNames";
|
||||
|
||||
export class MainPanel extends BaseReactComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
division: "",
|
||||
city: CityName.Sector12,
|
||||
}
|
||||
}
|
||||
|
||||
// We can pass this setter to child components
|
||||
changeCityState(newCity) {
|
||||
if (Object.values(CityName).includes(newCity)) {
|
||||
this.state.city = newCity;
|
||||
} else {
|
||||
console.error(`Tried to change MainPanel's city state to an invalid city: ${newCity}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Determines what UI content to render based on routing
|
||||
renderContent() {
|
||||
if (this.routing().isOnOverviewPage()) {
|
||||
// Corporation overview Content
|
||||
return this.renderOverviewPage();
|
||||
} else {
|
||||
// Division content
|
||||
|
||||
// First, check if we're at a new division. If so, we need to reset the city to Sector-12
|
||||
// Otherwise, just switch the 'city' state
|
||||
const currentDivision = this.routing().current();
|
||||
if (currentDivision !== this.state.division) {
|
||||
this.state.division = currentDivision;
|
||||
this.state.city = CityName.Sector12;
|
||||
}
|
||||
|
||||
return this.renderDivisionPage();
|
||||
}
|
||||
}
|
||||
|
||||
renderOverviewPage() {
|
||||
return (
|
||||
<div id="cmpy-mgmt-panel">
|
||||
<Overview {...this.props} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderDivisionPage() {
|
||||
// Note: Division is the same thing as Industry...I wasn't consistent with naming
|
||||
const division = this.routing().currentDivision;
|
||||
if (division == null) {
|
||||
throw new Error(`Routing does not hold reference to the current Industry`);
|
||||
}
|
||||
|
||||
// City tabs
|
||||
const onClicks = {};
|
||||
for (const cityName in division.offices) {
|
||||
if (division.offices[cityName] instanceof OfficeSpace) {
|
||||
onClicks[cityName] = () => {
|
||||
this.state.city = cityName;
|
||||
this.corp().rerender();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const cityTabs = (
|
||||
<CityTabs
|
||||
{...this.props}
|
||||
city={this.state.city}
|
||||
onClicks={onClicks}
|
||||
cityStateSetter={this.changeCityState.bind(this)}
|
||||
/>
|
||||
)
|
||||
|
||||
// Rest of Industry UI
|
||||
const industry = (
|
||||
<Industry {...this.props} currentCity={this.state.city} />
|
||||
)
|
||||
|
||||
return (
|
||||
<div id="cmpy-mgmt-panel">
|
||||
{cityTabs}
|
||||
{industry}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.renderContent();
|
||||
}
|
||||
}
|
||||
323
src/Corporation/ui/Overview.jsx
Normal file
323
src/Corporation/ui/Overview.jsx
Normal file
@@ -0,0 +1,323 @@
|
||||
// React Component for displaying Corporation Overview info
|
||||
import React from "react";
|
||||
import { BaseReactComponent } from "./BaseReactComponent";
|
||||
import { LevelableUpgrade } from "./LevelableUpgrade";
|
||||
import { UnlockUpgrade } from "./UnlockUpgrade";
|
||||
|
||||
import { BribeThreshold } from "../Corporation";
|
||||
import { CorporationUnlockUpgrades } from "../data/CorporationUnlockUpgrades";
|
||||
import { CorporationUpgrades } from "../data/CorporationUpgrades";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
export class Overview extends BaseReactComponent {
|
||||
// Generic Function for Creating a button
|
||||
createButton(props) {
|
||||
let className = props.class ? props.class : "std-button";
|
||||
const displayStyle = props.display ? props.display : "block";
|
||||
const hasTooltip = (props.tooltip != null);
|
||||
if (hasTooltip) {
|
||||
className += " tooltip";
|
||||
}
|
||||
|
||||
return (
|
||||
<a className={className} onClick={props.onClick} style={{display: {displayStyle}}}>
|
||||
{props.text}
|
||||
{
|
||||
hasTooltip &&
|
||||
<span className={"tooltiptext"}>
|
||||
{props.tooltip}
|
||||
</span>
|
||||
}
|
||||
</a>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
// Returns a string with general information about Corporation
|
||||
getOverviewText() {
|
||||
// Formatted text for profit
|
||||
var profit = this.corp().revenue.minus(this.corp().expenses).toNumber(),
|
||||
profitStr = profit >= 0 ? numeralWrapper.formatMoney(profit) : "-" + numeralWrapper.format(-1 * profit, "$0.000a");
|
||||
|
||||
// Formatted text for dividend information, if applicable
|
||||
let dividendStr = "";
|
||||
if (this.corp().dividendPercentage > 0 && profit > 0) {
|
||||
const totalDividends = (this.corp().dividendPercentage / 100) * profit;
|
||||
const retainedEarnings = profit - totalDividends;
|
||||
const dividendsPerShare = totalDividends / this.corp().totalShares;
|
||||
const playerEarnings = this.corp().numShares * dividendsPerShare;
|
||||
|
||||
dividendStr = `Retained Profits (after dividends): ${numeralWrapper.format(retainedEarnings, "$0.000a")} / s<br><br>` +
|
||||
`Dividend Percentage: ${numeralWrapper.format(this.corp().dividendPercentage / 100, "0%")}<br>` +
|
||||
`Dividends per share: ${numeralWrapper.format(dividendsPerShare, "$0.000a")} / s<br>` +
|
||||
`Your earnings as a shareholder (Pre-Tax): ${numeralWrapper.format(playerEarnings, "$0.000a")} / s<br>` +
|
||||
`Dividend Tax Rate: ${this.corp().dividendTaxPercentage}%<br>` +
|
||||
`Your earnings as a shareholder (Post-Tax): ${numeralWrapper.format(playerEarnings * (1 - (this.corp().dividendTaxPercentage / 100)), "$0.000a")} / s<br><br>`;
|
||||
}
|
||||
|
||||
let txt = "Total Funds: " + numeralWrapper.format(this.corp().funds.toNumber(), '$0.000a') + "<br>" +
|
||||
"Total Revenue: " + numeralWrapper.format(this.corp().revenue.toNumber(), "$0.000a") + " / s<br>" +
|
||||
"Total Expenses: " + numeralWrapper.format(this.corp().expenses.toNumber(), "$0.000a") + "/ s<br>" +
|
||||
"Total Profits: " + profitStr + " / s<br>" +
|
||||
dividendStr +
|
||||
"Publicly Traded: " + (this.corp().public ? "Yes" : "No") + "<br>" +
|
||||
"Owned Stock Shares: " + numeralWrapper.format(this.corp().numShares, '0.000a') + "<br>" +
|
||||
"Stock Price: " + (this.corp().public ? numeralWrapper.formatMoney(this.corp().sharePrice) : "N/A") + "<br>" +
|
||||
"<p class='tooltip'>Total Stock Shares: " + numeralWrapper.format(this.corp().totalShares, "0.000a") +
|
||||
"<span class='tooltiptext'>" +
|
||||
`Outstanding Shares: ${numeralWrapper.format(this.corp().issuedShares, "0.000a")}<br>` +
|
||||
`Private Shares: ${numeralWrapper.format(this.corp().totalShares - this.corp().issuedShares - this.corp().numShares, "0.000a")}` +
|
||||
"</span></p><br><br>";
|
||||
|
||||
const storedTime = this.corp().storedCycles * CONSTANTS.MilliPerCycle / 1000;
|
||||
if (storedTime > 15) {
|
||||
txt += `Bonus Time: ${storedTime} seconds<br><br>`;
|
||||
}
|
||||
|
||||
let prodMult = this.corp().getProductionMultiplier(),
|
||||
storageMult = this.corp().getStorageMultiplier(),
|
||||
advMult = this.corp().getAdvertisingMultiplier(),
|
||||
empCreMult = this.corp().getEmployeeCreMultiplier(),
|
||||
empChaMult = this.corp().getEmployeeChaMultiplier(),
|
||||
empIntMult = this.corp().getEmployeeIntMultiplier(),
|
||||
empEffMult = this.corp().getEmployeeEffMultiplier(),
|
||||
salesMult = this.corp().getSalesMultiplier(),
|
||||
sciResMult = this.corp().getScientificResearchMultiplier();
|
||||
if (prodMult > 1) {txt += "Production Multiplier: " + numeralWrapper.format(prodMult, "0.000") + "<br>";}
|
||||
if (storageMult > 1) {txt += "Storage Multiplier: " + numeralWrapper.format(storageMult, "0.000") + "<br>";}
|
||||
if (advMult > 1) {txt += "Advertising Multiplier: " + numeralWrapper.format(advMult, "0.000") + "<br>";}
|
||||
if (empCreMult > 1) {txt += "Empl. Creativity Multiplier: " + numeralWrapper.format(empCreMult, "0.000") + "<br>";}
|
||||
if (empChaMult > 1) {txt += "Empl. Charisma Multiplier: " + numeralWrapper.format(empChaMult, "0.000") + "<br>";}
|
||||
if (empIntMult > 1) {txt += "Empl. Intelligence Multiplier: " + numeralWrapper.format(empIntMult, "0.000") + "<br>";}
|
||||
if (empEffMult > 1) {txt += "Empl. Efficiency Multiplier: " + numeralWrapper.format(empEffMult, "0.000") + "<br>";}
|
||||
if (salesMult > 1) {txt += "Sales Multiplier: " + numeralWrapper.format(salesMult, "0.000") + "<br>";}
|
||||
if (sciResMult > 1) {txt += "Scientific Research Multiplier: " + numeralWrapper.format(sciResMult, "0.000") + "<br>";}
|
||||
|
||||
return txt;
|
||||
}
|
||||
|
||||
// Render the buttons that lie below the overview text.
|
||||
// These are mainly for things such as managing finances/stock
|
||||
renderButtons() {
|
||||
// Create a "Getting Started Guide" button that lets player view the
|
||||
// handbook and adds it to the players home computer
|
||||
const getStarterGuideOnClick = this.corp().getStarterGuide.bind(this.corp());
|
||||
const getStarterGuideBtn = this.createButton({
|
||||
class: "a-link-button",
|
||||
display: "inline-block",
|
||||
onClick: getStarterGuideOnClick,
|
||||
text: "Getting Started Guide",
|
||||
tooltip: "Get a copy of and read 'The Complete Handbook for Creating a Successful Corporation.' " +
|
||||
"This is a .lit file that guides you through the beginning of setting up a Corporation and " +
|
||||
"provides some tips/pointers for helping you get started with managing it.",
|
||||
});
|
||||
|
||||
// Create a "Bribe Factions" button if your Corporation is powerful enough.
|
||||
// This occurs regardless of whether you're public or private
|
||||
const canBribe = (this.corp().determineValuation() >= BribeThreshold);
|
||||
const bribeFactionsOnClick = this.eventHandler().createBribeFactionsPopup.bind(this.eventHandler());
|
||||
const bribeFactionsClass = (canBribe ? "a-link-button" : "a-link-button-inactive");
|
||||
const bribeFactionsBtn = this.createButton({
|
||||
class: bribeFactionsClass,
|
||||
display: "inline-block",
|
||||
onClick: bribeFactionsOnClick,
|
||||
text: "Bribe Factions",
|
||||
tooltip: (canBribe
|
||||
? "Use your Corporations power and influence to bribe Faction leaders in exchange for reputation"
|
||||
: "Your Corporation is not powerful enough to bribe Faction leaders"),
|
||||
|
||||
});
|
||||
|
||||
const generalBtns = {
|
||||
bribeFactions: bribeFactionsBtn,
|
||||
getStarterGuide: getStarterGuideBtn,
|
||||
};
|
||||
|
||||
if (this.corp().public) {
|
||||
return this.renderPublicButtons(generalBtns);
|
||||
} else {
|
||||
return this.renderPrivateButtons(generalBtns);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Render the buttons for when your Corporation is still private
|
||||
renderPrivateButtons(generalBtns) {
|
||||
const fundingAvailable = (this.corp().fundingRound < 4);
|
||||
const findInvestorsClassName = fundingAvailable ? "std-button" : "a-link-button-inactive";
|
||||
const findInvestorsTooltip = fundingAvailable ? "Search for private investors who will give you startup funding in exchangefor equity (stock shares) in your company" : null;
|
||||
|
||||
const findInvestorsOnClick = this.corp().getInvestment.bind(this.corp());
|
||||
const goPublicOnClick = this.corp().goPublic.bind(this.corp());
|
||||
|
||||
const findInvestorsBtn = this.createButton({
|
||||
class: findInvestorsClassName,
|
||||
onClick: findInvestorsOnClick,
|
||||
style: "inline-block",
|
||||
text: "Find Investors",
|
||||
tooltip: findInvestorsTooltip
|
||||
});
|
||||
const goPublicBtn = this.createButton({
|
||||
class: "std-button",
|
||||
onClick: goPublicOnClick,
|
||||
style: "inline-block",
|
||||
text: "Go Public",
|
||||
tooltip: "Become a publicly traded and owned entity. Going public " +
|
||||
"involves issuing shares for an IPO. Once you are a public " +
|
||||
"company, your shares will be traded on the stock market."
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
{generalBtns.getStarterGuide}
|
||||
{findInvestorsBtn}
|
||||
{goPublicBtn}
|
||||
<br />
|
||||
{generalBtns.bribeFactions}
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
// Render the buttons for when your Corporation has gone public
|
||||
renderPublicButtons(generalBtns) {
|
||||
const corp = this.corp();
|
||||
|
||||
const sellSharesOnClick = this.eventHandler().createSellSharesPopup.bind(this.eventHandler());
|
||||
const sellSharesOnCd = (corp.shareSaleCooldown > 0);
|
||||
const sellSharesClass = sellSharesOnCd ? "a-link-button-inactive" : "std-button";
|
||||
const sellSharesTooltip = sellSharesOnCd
|
||||
? "Cannot sell shares for " + corp.convertCooldownToString(corp.shareSaleCooldown)
|
||||
: "Sell your shares in the company. The money earned from selling your " +
|
||||
"shares goes into your personal account, not the Corporation's. " +
|
||||
"This is one of the only ways to profit from your business venture."
|
||||
const sellSharesBtn = this.createButton({
|
||||
class: sellSharesClass,
|
||||
display: "inline-block",
|
||||
onClick: sellSharesOnClick,
|
||||
text: "Sell Shares",
|
||||
tooltip: sellSharesTooltip,
|
||||
});
|
||||
|
||||
const buybackSharesOnClick = this.eventHandler().createBuybackSharesPopup.bind(this.eventHandler());
|
||||
const buybackSharesBtn = this.createButton({
|
||||
class: "std-button",
|
||||
display: "inline-block",
|
||||
onClick: buybackSharesOnClick,
|
||||
text: "Buyback shares",
|
||||
tooltip: "Buy back shares you that previously issued or sold at market price.",
|
||||
});
|
||||
|
||||
const issueNewSharesOnClick = this.eventHandler().createIssueNewSharesPopup.bind(this.eventHandler());
|
||||
const issueNewSharesOnCd = (corp.issueNewSharesCooldown > 0);
|
||||
const issueNewSharesClass = issueNewSharesOnCd ? "a-link-button-inactive" : "std-button";
|
||||
const issueNewSharesTooltip = issueNewSharesOnCd
|
||||
? "Cannot issue new shares for " + corp.convertCooldownToString(corp.issueNewSharesCooldown)
|
||||
: "Issue new equity shares to raise capital.";
|
||||
const issueNewSharesBtn = this.createButton({
|
||||
class: issueNewSharesClass,
|
||||
display: "inline-block",
|
||||
onClick: issueNewSharesOnClick,
|
||||
text: "Issue New Shares",
|
||||
tooltip: issueNewSharesTooltip,
|
||||
});
|
||||
|
||||
const issueDividendsOnClick = this.eventHandler().createIssueDividendsPopup.bind(this.eventHandler());
|
||||
const issueDividendsBtn = this.createButton({
|
||||
class: "std-button",
|
||||
display: "inline-block",
|
||||
onClick: issueDividendsOnClick,
|
||||
text: "Issue Dividends",
|
||||
tooltip: "Manage the dividends that are paid out to shareholders (including yourself)",
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
{generalBtns.getStarterGuide}
|
||||
{sellSharesBtn}
|
||||
{buybackSharesBtn}
|
||||
<br />
|
||||
{issueNewSharesBtn}
|
||||
{issueDividendsBtn}
|
||||
<br />
|
||||
{generalBtns.bribeFactions}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Render the UI for Corporation upgrades
|
||||
renderUpgrades() {
|
||||
// Don't show upgrades
|
||||
if (this.corp().divisions.length <= 0) { return; }
|
||||
|
||||
// Create an array of all Unlocks
|
||||
const unlockUpgrades = [];
|
||||
Object.values(CorporationUnlockUpgrades).forEach((unlockData) => {
|
||||
if (this.corp().unlockUpgrades[unlockData[0]] === 0) {
|
||||
unlockUpgrades.push(this.renderUnlockUpgrade(unlockData));
|
||||
}
|
||||
});
|
||||
|
||||
// Create an array of properties of all unlocks
|
||||
const levelableUpgradeProps = [];
|
||||
for (let i = 0; i < this.corp().upgrades.length; ++i) {
|
||||
const upgradeData = CorporationUpgrades[i];
|
||||
const level = this.corp().upgrades[i];
|
||||
|
||||
levelableUpgradeProps.push({
|
||||
upgradeData: upgradeData,
|
||||
upgradeLevel: level,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className={"cmpy-mgmt-upgrade-container"}>
|
||||
<h1 className={"cmpy-mgmt-upgrade-header"}> Unlocks </h1>
|
||||
{unlockUpgrades}
|
||||
|
||||
<h1 className={"cmpy-mgmt-upgrade-header"}> Upgrades </h1>
|
||||
{
|
||||
levelableUpgradeProps.map((data) => {
|
||||
return this.renderLevelableUpgrade(data);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderUnlockUpgrade(data) {
|
||||
return (
|
||||
<UnlockUpgrade
|
||||
{...this.props}
|
||||
upgradeData={data}
|
||||
key={data[0]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
renderLevelableUpgrade(data) {
|
||||
return (
|
||||
<LevelableUpgrade
|
||||
{...this.props}
|
||||
upgradeData={data.upgradeData}
|
||||
upgradeLevel={data.upgradeLevel}
|
||||
key={data.upgradeData[0]}
|
||||
/>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<p dangerouslySetInnerHTML={{__html: this.getOverviewText()}}></p>
|
||||
{this.renderButtons()}
|
||||
<br />
|
||||
{this.renderUpgrades()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
17
src/Corporation/ui/Root.jsx
Normal file
17
src/Corporation/ui/Root.jsx
Normal file
@@ -0,0 +1,17 @@
|
||||
// Root React Component for the Corporation UI
|
||||
import React from "react";
|
||||
import { BaseReactComponent } from "./BaseReactComponent";
|
||||
|
||||
import { HeaderTabs } from "./HeaderTabs";
|
||||
import { MainPanel } from "./MainPanel";
|
||||
|
||||
export class CorporationRoot extends BaseReactComponent {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<HeaderTabs {...this.props} />
|
||||
<MainPanel {...this.props} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user